Microsoft Agent Governance Toolkit and Intercis
The Microsoft Agent Governance Toolkit is a library your agent imports. Intercis is a proxy your agent's base URL points at. That one difference sets most of the rows below, and it does not settle the choice: the toolkit is free, open source, speaks five languages and covers ground we do not touch. Five of the twelve rows below go to the toolkit.
| Intercis | Microsoft Agent Governance Toolkit, from the repositoryRead 18 September 2026 from a local clone of github.com/microsoft/agent-governance-toolkit at commit 8f1d0e1, MIT licence. |
How to check | |
|---|---|---|---|
| Where enforcement runs |
Out of the agent's process, in the path of the provider call. The agent's base URL
points at us and the agent's code does not change. We govern Anthropic's
POST /v1/messages and OpenAI's POST /v1/responses and
POST /v1/chat/completions. Being in the path is a configuration
setting, not a law: a process that can change its own base URL can call the
provider directly, so pair us with an egress rule that blocks direct calls to the
provider APIs. Without that rule we are a control a compromised process can walk
around.
|
In the agent's own process, with an out-of-process option that is still called by
the application. README.md, "Security": "AGT enforces governance at
the application middleware layer, not at the OS kernel level. The policy engine
and agents share the same process boundary." docs/FAQ.md section 1
lists where it runs as "In-process middleware or sidecar alongside each agent".
The sidecar is not transparent: docs/FAQ.md section 2 states
"Transparent tool-call interception is not yet implemented in the sidecar. The
agent or orchestration layer must call the sidecar API explicitly".
|
Toolkit: read README.md under "Security", docs/FAQ.md
sections 1 and 2. Intercis: intercis.io/limitations,
first cost. Both costs are real and neither disappears by choosing the other
product.
|
| What happens on a deny |
The action is removed from the response rather than labelled in it. On a deny the
proxy builds a synthetic provider-shaped reply: the model's tool_use
block is gone, one assistant text block naming the policy is in its place, and
stop_reason becomes end_turn. The agent runtime never
receives a tool call, so it has nothing to execute. The three enforcement verdicts
are allow, deny and observe.
|
The toolkit returns a decision and the application carries it out.
policy-engine/docs/security-model.md, "Trust Boundaries": "The host
enforcement boundary lies after ACS returns a verdict. The host must block,
transform, escalate, or proceed in accordance with the result." The same file lists
"Compromised host application" in its threat table with the status "Out of scope"
and the note "ACS returns decisions but cannot force malicious host code to obey
them." In the Python quick start the deny surfaces as a
GovernanceDenied exception raised inside the caller
(README.md, "Quick Start").
|
Toolkit: policy-engine/docs/security-model.md, "Trust Boundaries" and
the threat matrix row "Compromised host application"; README.md,
"Quick Start". Intercis:
intercis.io/validation-report, "What a deny
actually does", which shows the response before and after; in the repository,
grep -n _make_blocked_response apps/proxy/main.py.
|
| What each side can and cannot see |
Only traffic that crosses the Anthropic and OpenAI API wire is judged. A tool the
provider runs on its own servers has already run by the time the response reaches
us: hosted MCP calls, web search, file search, code interpreter and image
generation are listed in _HOSTED_ITEM_TYPES in
apps/proxy/openai_routes.py, and each one is observed, not governed:
it writes one observe row and is never judged or blocked. A provider or a route we
do not speak yet is not governed, and adding one is engineering work on our side.
|
Whatever the application routes through it, and nothing else.
policy-engine/docs/security-model.md: "An uninstrumented call path is
outside the ACS guarantee", and its threat table lists "Policy bypass through
uninstrumented paths" with the status "Host responsibility". It sees MCP tool calls
the sidecar is asked about (docs/FAQ.md section 2) and eight lifecycle
points including input, model call, tool call and output
(policy-engine/README.md, "Intervention points").
docs/LIMITATIONS.md sections 1, 7 and 8 state it does not govern
reasoning, knowledge retrieved by RAG, or the credentials an agent holds.
|
Toolkit: policy-engine/docs/security-model.md, "Trust Boundaries" and
"Out Of Scope Threats And Non Goals"; docs/LIMITATIONS.md sections 1,
7, 8. Intercis: intercis.io/limitations, second and
fifth costs; intercis.io/validation-report,
"Hosted MCP tool calls are observed, not governed".
|
| Streaming | Buffered, and the cost is ours to carry. To judge a tool call we have to see all of it, so a streamed response is collected in full, reassembled and judged before any of it reaches the agent. That adds latency equal to the length of the stream before the first token arrives, and on an interactive coding agent a person waits through it. We publish no latency number. |
Not covered at the token level. docs/LIMITATIONS.md section 11 states
policies are evaluated per action at invocation time.
policy-engine/docs/security-model.md states "ACS does not provide
token or chunk level streaming enforcement. Hosts evaluate complete model and
output snapshots", and requires that "The host must aggregate streams before
calling post_model_call or output".
|
Toolkit: docs/LIMITATIONS.md section 11;
policy-engine/docs/security-model.md, "Out Of Scope Threats And Non
Goals" and "Required Integration Invariants". Intercis:
intercis.io/limitations, third cost;
intercis.io/validation-report, "There is no
latency figure". Both sides need the whole response before they can judge it.
|
| Languages and frameworks | Language-independent and framework-independent, because we are not in the code. Any agent in any language on any framework is governed if its provider calls reach us, and the agent's code does not change. The bound is the other way round: we speak three provider routes, so a provider we do not speak is not governed however the agent is written. |
Broader than ours, and this is a row where the toolkit is ahead. Five language
packages: Python, TypeScript, .NET, Rust and Go (README.md, "Install";
docs/FAQ.md section 4). README.md, "Framework Support"
lists fourteen integrations including Microsoft Agent Framework, Semantic Kernel,
AutoGen, LangGraph, LangChain, CrewAI, the OpenAI Agents SDK, Google ADK,
LlamaIndex, Haystack, Dify and Azure AI Foundry. docs/FAQ.md section 4
states Python has the full stack and the other four carry core governance.
|
Toolkit: README.md, "Install" and "Framework Support";
docs/PACKAGE-FEATURE-MATRIX.md for per-language coverage. Intercis:
intercis.io/limitations, fifth cost, which names the
three routes.
|
| Policy language and who writes the rules | We ship the rules and you narrow them. The deterministic deny list is ours, maintained by us, and it is the floor under every tenant; on top of it a tenant sets modes and exclusions and an LLM classifier runs only when the deny list misses. Nobody writes Rego to use Intercis, and nobody can read our rule set either: Intercis is closed source, permanently, and the deny-list patterns are not published. |
You write them, in one of several languages. README.md, "Quick Start"
shows a YAML policy with condition expressions and actions
deny and require_approval.
policy-engine/README.md, "Policies" lists the supported types as
rego, cedar, test and custom,
so rules can be Open Policy Agent Rego or Cedar. A manifest binds one policy per
intervention point.
|
Toolkit: README.md, "Quick Start"; policy-engine/README.md,
"Policies" and "Manifest schema overview". Intercis:
intercis.io/validation-report, "What the pattern
layer catches"; the closed-source position is the decision record dated 2026-07-27
in our repository.
|
| Audit record and tamper evidence | One row per governed event in a database the agent cannot reach. A row carries the tenant, the agent, the tool name, a short excerpt of the command or path, the verdict, the policy, whether an injection was seen, the wire route, a command fingerprint, the classifier status and reason, and the structured tool input. A trigger computes a SHA-256 over the previous row's hash and every length-prefixed column of the event except that tool input, one chain per tenant; rows recorded before 2026-09-20 are hashed over ten named fields. No client role holds UPDATE or DELETE. We call it tamper-evident, not tamper-proof: anyone holding database-owner rights can rewrite rows and recompute the hashes. |
An append-only log with cryptographic chaining, described in a formal spec.
SECURITY.md, threat table: "Audit tampering ... Append-only audit log
with cryptographic chaining". README.md, "Specifications" lists "Audit
and Compliance" with Merkle audit and 157 conformance tests.
docs/LIMITATIONS.md section 2 is explicit that the log records what
the agent attempted, not whether the action succeeded. Their guidance is to write
the log outside the agent: SECURITY.md, "Operator guidance": "Enable
audit logging to an external, append-only store. Agents should not have write
access to their own audit logs."
|
Toolkit: SECURITY.md, threat table and "Operator guidance";
docs/specs/AUDIT-COMPLIANCE-1.0.md; docs/LIMITATIONS.md
section 2. Intercis:
intercis.io/validation-report, "The record the
decision leaves behind", and run the published verifier,
verify_event_chain.py, on the
published sample,
sample-chain.json, yourself.
|
| Identity | Bound to the API key, and only when you bind it. An Intercis key can be bound to exactly one agent; then the identity is a property of the credential, a header naming a different agent is refused with an audit row, and an inactive agent fails closed. An unbound key is the weaker case and is the default for every key issued before the change: the agent id is self-asserted in a header and checked only for existence inside the tenant, so one holder of a tenant key can present another registered agent's id. We have no cryptographic agent identity. |
Cryptographic, and this is a row where the toolkit is ahead. Agents carry a
decentralised identifier verified by an Ed25519 signature, with trust scores and
delegation chains (README.md, "How It Works" and "Packages";
docs/specs/AGENTMESH-IDENTITY-TRUST-1.0.md, 135 conformance tests).
Two honest wrinkles are in their own docs: docs/LIMITATIONS.md section
12 records two different identifier prefixes across the SDKs, and
SECURITY.md carries advisory GHSA-5j58-vjjg-pcgm, in
which the HTTP trust middleware accepted caller-supplied identity without binding
it to the whole request, fixed in 5.0.1.
|
Toolkit: README.md, "Packages"; docs/LIMITATIONS.md
section 12; SECURITY.md, "Security Advisories". Intercis: the decision
record dated 2026-09-02 on agent identity binding to the API key, in our
repository, which states the residual in its own words.
|
| Sandboxing and process isolation | None. Intercis does not sandbox, isolate or terminate a process. We judge provider calls and write the record; everything the agent does that is not a provider call is outside us. If what you need is an execution sandbox, this product is not it. |
Present, and this is a row where the toolkit is ahead: we have nothing here.
README.md, "Packages" lists Agent Runtime as "Execution sandboxing
with four privilege rings" and Agent Hypervisor for execution audit and command
denylist enforcement, with a formal spec and 80 conformance tests. They bound the
claim themselves: README.md, "Security" says enforcement is at the
application middleware layer, not the OS kernel, and recommends "Run each agent in
a separate container for OS-level isolation"; docs/LIMITATIONS.md
section 6 lists "OS kernel / hardware isolation" under what AGT is not.
|
Toolkit: README.md, "Packages" and "Security";
docs/specs/AGENT-HYPERVISOR-EXECUTION-CONTROL-1.0.md;
docs/LIMITATIONS.md section 6. Intercis:
intercis.io/limitations lists what we cover; no sandbox
appears on it or on
intercis.io/validation-report.
|
| Measured numbers published | How often our own rules flag work that was fine. On 4,764 governed tool calls from our own Dogfood tenant, all labelled benign, today's rules flag 737. That is 15.47%, Wilson 95% 14.47% to 16.52%. The window is 25 August to 4 September 2026 with 31 August excluded, the day a four-hour classifier outage voided it under our own runbook; the full window including that day reads 13.46% and is printed too. Separately, the deterministic deny list catches 40 of 47 payloads in our own in-repo threat corpus, 85.1% recall, and that corpus is written by the defender, so it measures regression stability and not adversarial robustness. We publish no latency number at all. |
Test counts, a policy-evaluation latency figure, and a self-assessed standards
mapping. README.md states "992 conformance tests" and, under
"Documentation", "10 formal specs, 992 conformance tests"; its own Specifications
table lists eleven rows, so treat the spec count as approximate and the test count
as theirs. docs/LIMITATIONS.md section 3 publishes policy evaluation
at under 0.1 ms and is careful about it: that number "measures the
policy engine only", and the same section gives 5 to 50 ms per
governed inter-agent interaction for a multi-agent mesh. Their OWASP claim is
theirs and we do not endorse or dispute it:
docs/compliance/owasp-agentic-top10-architecture.md reads "Official
ASI coverage: 7/10 Full, 3/10 Partial, 0 Gaps", and the same file opens with their
own disclaimer that it "is an internal self-assessment mapping, NOT a validated
certification or third-party audit". They also publish a re-runnable
false-positive figure for one component:
docs/benchmarks/prompt-injection-evaluation.md reports the Rust
prompt-injection detector on a 280-row synthetic smoke corpus, 16 of 170 benign
rows flagged (0.0941) and 7 of 110 attack rows caught (recall 0.0636), reproduced
with bash benchmarks/prompt-injection/run-smoke.sh. Their own caveat
sits beside it: the numbers "should not be presented as production AGT detector
performance". A rate of that kind measured on real agent traffic was not found in a
search of every markdown file in the repo at this commit.
|
Toolkit: README.md, "Specifications"; docs/LIMITATIONS.md
section 3; docs/compliance/owasp-agentic-top10-architecture.md,
"Coverage Summary" and the disclaimer above it. Intercis:
intercis.io/validation-report and
intercis.io/validation-report/benign-corpus,
and re-run python scripts/detection_bench.py yourself. The two figures
in this row are not comparable and this page does not set them side by side as if
they were: theirs is one detector on a 280-row synthetic corpus, with their own
caveat beside it, and ours is the whole rule set on 4,764 real calls from one
tenant, ours.
|
| Licence, cost and how you buy | Paid, closed source and hosted. $200 a month for the first agent and $190 for each additional agent, on the pilot page. The entry point is a 90-day pilot on the Team tier with no commitment required, and the pilot is paid at that rate. The only tiers are Team and Enterprise, and there is no self-serve signup. You cannot read our source, and we do not sell or support a self-hosted build; how one would be licensed is not decided. Putting us in the path also adds a trust boundary your prompts and tool inputs cross in plaintext, and the classifier call goes out on an Intercis credential carrying the tool name and the full tool input. |
Free and open source, and this is a row where the toolkit is ahead. MIT licence
(LICENSE, and README.md, "License"), installed with
pip install, npm install,
dotnet add package, cargo add or go get
(README.md, "Install"). docs/LIMITATIONS.md section 5
states the core packages carry zero Azure or Microsoft dependencies and run
offline, on AWS, GCP, on-premises or air-gapped. You can read every rule and fork
it.
|
Toolkit: LICENSE; README.md, "Install" and "License";
docs/LIMITATIONS.md section 5. Intercis:
intercis.io/pilot for the price,
intercis.io/limitations for the fourth cost.
|
| Maturity and who maintains it | One person, pre-revenue, and we will not dress that up. Intercis is a solo-founder company in Raleigh, North Carolina. It has no customer, no logo, no revenue figure and no compliance certification: not SOC 2 certified, no audit underway, no auditor engaged, and no SOC 2 or ISO 27001 evidence package generated. Per-provider route maintenance is ours for as long as the product exists. |
A Microsoft-led open-source project in public preview, and on team size this row is
theirs. README.md carries a "Public Preview" notice reading
"production-quality public preview releases. May have breaking changes before GA",
and CHANGELOG.md repeats it. MAINTAINERS.md, last updated
May 2026, lists a project lead and five core maintainers: three of those six are at
Microsoft and three are at other organisations. The contributor ladder is written
down in GOVERNANCE.md. The CHANGELOG.md "Unreleased"
section carries entries marked BREAKING. Security reports go to
secure@microsoft.com under a 90-day coordinated disclosure policy
(SECURITY.md).
|
Toolkit: README.md, the Public Preview notice;
MAINTAINERS.md; GOVERNANCE.md;
SECURITY.md; CHANGELOG.md. Intercis:
intercis.io/validation-report, "Intercis is not
SOC 2 certified", and intercis.io/limitations, fifth
cost.
|
What was read, and what a "not found" cell means. The Microsoft column comes from files
opened whole in a local clone at commit 8f1d0e1 on 18 September 2026:
README.md, SECURITY.md, MAINTAINERS.md,
CHANGELOG.md (head), docs/LIMITATIONS.md,
docs/FAQ.md (sections 1 to 4),
docs/compliance/owasp-agentic-top10-architecture.md (head),
policy-engine/README.md and
policy-engine/docs/security-model.md. Six further files appear above as
signposts for the reader and were not opened. So a cell saying something is not in the
repository means not in the files named here, and the one search of every markdown file in
the clone is the one named in the measured-numbers row.
When each is the better choice
When the toolkit is the better choice
Most of the time, on this evidence. It costs nothing, you can read every rule, and it speaks five languages and a dozen frameworks. If you write all the agent code yourself and can hold the line in code review, an in-process library is the cheaper guard and the faster one. If you need an execution sandbox, privilege rings or cryptographic agent identity, we do not have them and the toolkit does. If your agents are Microsoft Agent Framework or Semantic Kernel, it is one middleware registration.
When a proxy is
When the agent process itself is part of the threat. A library the application calls can be skipped by the application: their own security model puts a compromised host out of scope and says a decision cannot force malicious host code to obey it. A proxy outside the process removes that skip, and the audit log sits somewhere the agent cannot write to. It also helps when several teams use different frameworks and you would rather change one setting than every service. The price is an infrastructure change, buffered streaming, and an egress rule to stop a compromised process routing around us.
Both at once
They stack, and saying so is more honest than picking. The library catches what it catches before the request leaves; the proxy judges what reaches the wire. Switch one off and the other still runs. The cost is two sets of rules to keep straight. The same argument, in the same words, is on proxy against SDK enforcement.