All posts
AI SecurityAgent GovernanceKill ChainsMicrosoft AGT

Why Microsoft's Agent Governance Toolkit Misses Kill Chains

May 29, 2026·8 min read·Elam Olame Mugabo

In April 2026, Microsoft released the Agent Governance Toolkit (AGT) — an open-source framework for governing AI agent behavior in enterprise deployments. It's a serious piece of engineering. It enforces policies, validates tool calls, and generates audit logs. Within weeks it had 1,300+ GitHub stars.

There's one attack it cannot catch. And it's the one that actually matters in production.

What Microsoft AGT Does Well

AGT is a policy enforcement layer for agent actions. You define rules — "agents can read from /reports/* but not /hr/*" — and AGT evaluates each request against those rules before execution.

It handles:

  • Resource access control (can this agent touch this resource?)
  • Action type enforcement (can this agent delete files?)
  • Agent identity verification (is this a known, registered agent?)
  • Audit logging of decisions

For point-in-time authorization — "should this specific request be allowed?" — AGT is solid.

The problem is that point-in-time authorization is the wrong threat model for autonomous agents.

The Stateless Problem

AGT is stateless. It evaluates each request independently, with no memory of what the agent has done before.

This is a fundamental architectural constraint, not an oversight. Stateless systems are simpler to build, easier to reason about, and scale well. For human users — where each login session is relatively short and discrete — stateless authorization works.

Autonomous agents are different. They run continuously. They make dozens or hundreds of requests. They can be compromised mid-session. And the most dangerous attacks don't look dangerous request-by-request — they only become visible across a sequence.

The Attack AGT Can't See

Consider a realistic enterprise scenario. An AI agent — a financial reporting assistant — is registered with access to /reports/* and authorized to read and search.

Here's what happens over 5 minutes:

[REQUEST]  action=read  resource=/reports/q1_2026.pdf    → PERMIT
[REQUEST]  action=read  resource=/reports/q2_2026.pdf    → PERMIT
[REQUEST]  action=read  resource=/reports/q3_2026.pdf    → PERMIT
[REQUEST]  action=read  resource=/reports/q4_2026.pdf    → PERMIT
[REQUEST]  action=read  resource=/reports/annual_2025.pdf → PERMIT
[REQUEST]  action=read  resource=/reports/forecast_2027.pdf → PERMIT
[REQUEST]  action=search resource=/reports/* query="salary" → PERMIT
[REQUEST]  action=read  resource=/reports/compensation.pdf → PERMIT
[REQUEST]  action=read  resource=/reports/board_strategy.pdf → PERMIT
[REQUEST]  action=read  resource=/reports/acquisition_targets.pdf → PERMIT

[REQUEST]  action=export resource=/reports/* destination=external → ???

What does AGT see on that 11th request?

An export action against /reports/*. If export is in the agent's authorized actions — PERMIT. If it's not — DENY.

What AGT cannot see: that the previous 10 requests form a systematic data enumeration pattern. That the agent read every sensitive financial document in sequence. That the combination of bulk reads followed immediately by an export attempt is a textbook BULK_READ_THEN_EXFIL kill chain.

Each individual request was clean. The sequence was an attack.

How AgentGate Sees It

AgentGate is stateful. It maintains a behavioral baseline per agent across 24-hour sessions, tracking velocity, access patterns, resource sensitivity gradients, and sequential behavior.

Here's what the same scenario looks like through AgentGate:

[REQUEST]  action=read  resource=/reports/q1_2026.pdf
[DECISION] PERMIT  trust=0.91  (behavioral: nominal)

[REQUEST]  action=read  resource=/reports/q2_2026.pdf
[DECISION] PERMIT  trust=0.89  (velocity: elevated)

[REQUEST]  action=read  resource=/reports/q3_2026.pdf
[DECISION] PERMIT  trust=0.87  (pattern: sequential enumeration detected)

... 7 more reads ...

[REQUEST]  action=export  resource=/reports/*
[KILL CHAIN] *** BULK_READ_THEN_EXFIL detected ***
             10 reads in 4m32s followed by export attempt
             Pattern: data enumeration → exfiltration

[DECISION] *** DENY ***
[REASON]   Kill chain: bulk read then exfiltration sequence.
           No single request triggered this. The sequence did.

[AUDIT]    entry #4821 — HMAC-chained, tamper-evident, sealed pre-execution
[ALERT]    security team notified instantly

The export request was blocked before it executed. The audit record was sealed before the decision was communicated — not assembled after the fact. A regulator asking "what authorized this agent to act?" gets cryptographic proof that existed before the consequence.

The Kill Chains AGT Misses

BULK_READ_THEN_EXFIL is one of several multi-step attack patterns that are invisible to stateless authorization:

  • SENSITIVITY_RAMP — agent gradually escalates from low-sensitivity to high-sensitivity resources, staying within authorized scope the entire time
  • DIRECTORY_SWEEP — systematic enumeration of a directory structure before targeted extraction
  • READ_THEN_DELETE — reads a resource, then deletes it; each action individually authorized
  • INJECTION_PIVOT — agent reads an external resource containing prompt injection, then executes instructions embedded in it
  • TRUST_ESCALATION — child agent claims more scope than parent granted through delegation chain manipulation

Every one of these attacks consists entirely of individually authorized requests. A stateless system sees a sequence of PERMITs. A stateful system sees a kill chain.

The Pre-Execution Sealing Difference

There's a second gap beyond behavioral analysis: when the audit record is created.

A log assembled after execution can be manipulated between the action and the record. It answers the question "what happened?" — but not "was this authorized before it happened?"

AgentGate seals a Merkle-chained decision record before the action executes. The record contains the agent identity, action, resource, policy version, trust score, and decision — all committed before execution fires. Any mutation between authorization and execution invalidates the record.

This is the distinction the ATAP open agent trust protocol described when it incorporated AgentGate's pre-execution sealing approach in v0.3.1 and v0.3.2 this week: "An accountability record written after execution is a log, not a proof. A seal tells you what was authorized — and can be verified independently."

For EU AI Act Article 12 compliance — which requires evidence that AI systems acted within their authorized scope — this distinction is not optional.

A Fair Comparison

This isn't a takedown of Microsoft AGT. It solves a real problem and does it well. For organizations that need point-in-time policy enforcement with Microsoft ecosystem integration, it's a reasonable choice.

The comparison:

Capability Microsoft AGT AgentGate
Static resource access control
Agent-aware policy evaluation
Stateful behavioral analysis (24h)
Kill chain detection across sessions
Purpose alignment scoring
Delegation chain integrity Partial
Pre-execution audit sealing
Prompt injection detection
Open source
Self-hosted
Microsoft ecosystem integration Native

If you're deep in the Azure/Microsoft stack and your threat model is point-in-time policy violations, AGT is worth evaluating.

If your agents run continuously, make sequential decisions, and operate in environments where the sequence of individually authorized actions can constitute an attack — you need stateful behavioral analysis.

The Bottom Line

The difference between a normal agent run and a data exfiltration is the sequence. Not any single request — the pattern across requests.

A stateless governance tool cannot see sequences. It sees requests.

AgentGate sees both.


AgentGate is open source, MIT licensed, and self-hosted. Three lines to integrate with LangGraph, LangChain, AutoGen, or any Python/TypeScript agent framework.

Try the live kill chain demo: tryagentgate.com/playground

GitHub: github.com/ElamOlame31/agentgate-public

Try AgentGate

Open source, MIT licensed. Three lines to integrate with LangGraph, LangChain, AutoGen, or any Python/TypeScript agent framework.