mech.app
AI Agents

Microsoft's Agent Governance Toolkit: Sub-Millisecond Policy Enforcement for Every Tool Call

Runtime policy layer that intercepts agent actions before execution, achieving 0% violation rate vs. 26.67% for prompt-based safety across 20+ frameworks.

Source: github.com
Microsoft's Agent Governance Toolkit: Sub-Millisecond Policy Enforcement for Every Tool Call

Microsoft shipped a governance layer that sits between agent intent and tool execution. The Agent Governance Toolkit (AGT) intercepts every tool call, resource access, and inter-agent message before it runs, evaluates it against deterministic policy rules in under 0.1 milliseconds, and logs the decision. In red-team testing, prompt-based safety (“please follow the rules”) had a 26.67% policy violation rate. AGT’s application-layer enforcement: 0.00%.

This is not a sandbox or credential vault. It’s a policy engine that works across LangChain, CrewAI, AutoGen, OpenAI Agents, Google ADK, Semantic Kernel, AWS Bedrock, and 20+ frameworks. You define rules (no database writes after 5pm, no file access outside /tmp, no API calls to untrusted domains), and AGT enforces them at the action boundary, not the prompt boundary.

The Interception Architecture

AGT operates at the application layer, not the LLM layer. When an agent decides to call a tool, AGT intercepts the action before the tool executes. The flow:

  1. Agent generates tool call intent (function name, parameters, context)
  2. AGT policy engine receives the action metadata
  3. Policy rules evaluate in parallel (deterministic checks, no LLM inference)
  4. Decision: allow, deny, or modify
  5. Audit log records the decision and context
  6. Tool executes only if allowed

The interception happens via framework-specific adapters. For LangChain, AGT wraps the tool invocation layer. For AutoGen, it hooks into the agent’s action execution loop. For OpenAI Agents, it intercepts the function call before the API request completes. Each adapter translates framework-specific action metadata into AGT’s common action schema.

from agent_governance_toolkit import PolicyEngine, Action

# Define policy rules
policy = PolicyEngine()
policy.add_rule("no_db_writes_after_hours", lambda action: 
    not (action.tool == "database.write" and datetime.now().hour >= 17)
)

# Intercept tool call
action = Action(
    tool="database.write",
    params={"table": "users", "data": {...}},
    agent_id="agent-001",
    timestamp=datetime.now()
)

decision = policy.evaluate(action)  # < 0.1ms
if decision.allowed:
    execute_tool(action)
else:
    log_violation(decision.reason)

The policy engine does not call an LLM. It runs deterministic checks: string matching, regex patterns, time-based rules, resource quotas, and identity verification. This is why latency stays under 0.1ms even for complex policies.

Zero-Trust Identity for Agents

Agents share credentials and API keys by default. AGT introduces per-agent identity with scoped permissions. Each agent gets a unique identity token that maps to a set of allowed actions. The policy engine verifies the token before allowing any tool call.

Identity enforcement works in three layers:

  • Agent identity: Each agent has a unique ID and role (researcher, executor, coordinator)
  • Tool permissions: Policies map agent roles to allowed tools (researchers can read, executors can write)
  • Resource scopes: Policies define which resources each agent can access (agent-001 can only write to /tmp/agent-001)

This prevents lateral movement. If one agent is compromised (via prompt injection or tool misuse), it cannot escalate privileges or access resources outside its scope.

Framework Support and Adapter Design

AGT works with 20+ frameworks because it uses a plugin architecture. Each framework gets an adapter that translates its action model into AGT’s common schema. The adapter handles:

  • Action extraction: Parse tool calls from framework-specific formats
  • Context injection: Add agent ID, timestamp, and execution context
  • Result handling: Pass policy decisions back to the framework’s execution layer

Supported frameworks include LangChain, CrewAI, AutoGen, OpenAI Agents, Google ADK, Semantic Kernel, AWS Bedrock, Haystack, and LlamaIndex. The adapter layer is open for extension, so you can add support for custom frameworks.

The common action schema looks like this:

@dataclass
class Action:
    tool: str              # Tool name (e.g., "file.read")
    params: dict           # Tool parameters
    agent_id: str          # Unique agent identifier
    timestamp: datetime    # When the action was requested
    context: dict          # Additional metadata (session, user, etc.)

Audit Logging Without Bottlenecks

Every action generates an audit log entry. The log includes the action metadata, policy decision, execution result, and timing. AGT uses async logging to avoid blocking the agent execution loop. Logs are buffered in memory and flushed to storage in batches.

Log storage is pluggable. You can write to local files, S3, Azure Blob Storage, or a database. The default is structured JSON logs with indexed fields for querying.

Example log entry:

{
  "action_id": "act-12345",
  "agent_id": "agent-001",
  "tool": "database.write",
  "params": {"table": "users"},
  "decision": "denied",
  "reason": "no_db_writes_after_hours",
  "timestamp": "2026-05-22T17:05:00Z",
  "latency_ms": 0.08
}

Logs are queryable for compliance audits, security investigations, and reliability analysis. You can trace every action an agent took, why it was allowed or denied, and how long it took.

OWASP Agentic Top 10 Coverage

AGT addresses all 10 OWASP Agentic AI security risks:

RiskAGT Mitigation
Prompt injectionPolicy enforcement blocks unauthorized actions regardless of prompt
Insecure tool useTool permissions scoped per agent identity
Excessive agencyResource quotas and time-based restrictions
Unauthorized accessZero-trust identity with per-agent scopes
Data leakageAudit logs track all data access and exfiltration attempts
Model manipulationPolicy checks run before tool execution, not after LLM output
Insecure inter-agent communicationMessage-level policy enforcement for agent-to-agent calls
Inadequate monitoringStructured audit logs with sub-millisecond latency tracking
Supply chain risksFramework adapters isolate AGT from third-party code
Uncontrolled resource consumptionRate limits and quota enforcement per agent

The policy engine runs before the agent can execute any action, so even if the LLM is compromised, the governance layer blocks violations.

Deployment Shapes

AGT runs in three modes:

  1. In-process: Policy engine runs in the same process as the agent (lowest latency, simplest deployment)
  2. Sidecar: Policy engine runs as a separate process on the same host (isolation without network overhead)
  3. Remote: Policy engine runs as a centralized service (multi-agent deployments, shared policy state)

In-process mode is the default. You instantiate the policy engine in your agent code and call it directly. Latency is under 0.1ms because there’s no IPC or network hop.

Sidecar mode uses Unix domain sockets or named pipes for IPC. Latency is under 0.5ms. This mode isolates the policy engine from the agent process, so a crash in the agent doesn’t take down the governance layer.

Remote mode uses gRPC or HTTP/2 for communication. Latency is 1-5ms depending on network conditions. This mode is for multi-agent systems where you want centralized policy management and shared audit logs.

Failure Modes and Reliability

AGT is designed to fail closed. If the policy engine is unreachable or returns an error, the agent blocks the action. This prevents security bypasses but can cause availability issues if the policy engine goes down.

To mitigate this, AGT supports:

  • Policy caching: Agents cache policy decisions for repeated actions (cache hit rate > 90% in production)
  • Fallback policies: If the policy engine is unreachable, agents use a local fallback policy (deny-by-default or allow-by-default)
  • Health checks: Agents ping the policy engine before each action batch to detect failures early

Policy evaluation is deterministic and stateless, so you can run multiple policy engine replicas behind a load balancer. If one replica fails, the agent retries on another replica.

When to Use AGT vs. Prompt-Based Safety

ApproachViolation RateLatencyAuditabilityFramework Support
Prompt-based safety26.67%0msNoneAll
AGT policy enforcement0.00%< 0.1msFull20+ frameworks
Sandboxing (Claw Patrol, DeltaBox)Low10-50msPartialLimited
Credential vaults (Agent Vault)N/A5-10msPartialAll

Prompt-based safety is easy to implement but unreliable. You add instructions to the system prompt (“do not access production databases”), but the LLM can ignore them or be tricked via prompt injection.

AGT is deterministic. The policy engine does not rely on the LLM to follow rules. It enforces rules at the action boundary, so even a compromised LLM cannot bypass governance.

Sandboxing (like Claw Patrol or DeltaBox) isolates the agent’s execution environment but does not enforce fine-grained policies. You can prevent file system access entirely, but you cannot allow read-only access to /tmp while blocking writes to /etc.

Credential vaults (like Agent Vault) manage secrets but do not enforce usage policies. You can store API keys securely, but you cannot prevent an agent from calling an API 1000 times per second.

Technical Verdict

Use AGT when you need deterministic policy enforcement for production agents. It’s the right choice if:

  • You have compliance requirements (SOC 2, HIPAA, GDPR) that mandate audit logs for every agent action
  • You run multi-agent systems where agents need different permission scopes
  • You deploy agents in environments where prompt injection is a realistic threat
  • You need sub-millisecond policy checks without blocking the agent execution loop

Avoid AGT if:

  • You run single-purpose agents with no external tool access (no actions to govern)
  • You already have a sandboxed execution environment that meets your security requirements
  • You need policy decisions based on LLM reasoning (AGT is deterministic, not inferential)
  • You cannot tolerate fail-closed behavior (AGT blocks actions when the policy engine is unreachable)

AGT is production-quality but in public preview. Expect breaking changes before GA. The Python SDK is the most mature. TypeScript, .NET, Rust, and Go SDKs are available but less tested.