Repository navigation
Enforcement is no longer tied to a vendor. Until now a contract could only be enforced through an LLM wire format, a vendor SDK client, or the Claude Code hook — and the framework integrations could only measure. This release makes enforcement available anywhere an agent runs.
MCP guard — any client that speaks MCP
Change one line in your MCP config:
{"command": "agentassert-abc-mcp-guard",
"args": ["--contract", "contract.yaml", "--", "npx", "-y", "your-mcp-server"]}A denied tool call is answered before the server ever sees it, so the tool never runs. Works in Claude Code, Codex, Cursor, VS Code, Antigravity and Windsurf with no client-specific code.
It relays JSON-RPC rather than modelling MCP — it recognises one method and passes everything else through untouched — so it takes no dependency on the mcp package and does not break when the protocol grows.
Enforcement in any agent framework
from agentassert_abc.enforce import bridge_from_yaml
from agentassert_abc.enforce.shims import crewai_before_tool_hook
guard = bridge_from_yaml("contract.yaml", surface="crewai")
crew = Crew(agents=[...], before_tool_call_hooks=[crewai_before_tool_hook(guard)])| Framework | How a denial is spelled |
|---|---|
| CrewAI | before-tool hook returns False |
| LangChain / LangGraph | the tool handler is never called |
| DeerFlow | built on LangGraph — covered by the same shim |
| Microsoft Agent Framework | the middleware chain is not continued |
| AgentScope | the acting hook raises |
| Anything else | drive EnforcementBridge directly in a few lines |
Shims are matched to their framework by shape rather than by importing it, so agentassert-abc[enforce] pulls in no agent framework.
Where enforcement is not possible
docs/enforcement-coverage.md states, per client, where contracts can be enforced and where only measurement is available. Copilot, Antigravity and Windsurf route their built-in editor and shell through neither MCP nor any hook — that limit is in the table, not a footnote.
Fixed
- A tool call whose contract could not be evaluated is no longer scored afterwards. Previously an evaluation failure could be followed by scoring the result, recording the agent as violating an invariant that never ran.
- The same contract now behaves identically whether measuring or enforcing. Nested state was passed through unflattened on the measurement side, so a field that resolved under enforcement silently scored as violated under measurement.
- The Claude Code hook, installer and CLI shipped with no tests. Coverage for that package goes from 0% to 95%.
1,697 tests, 93% coverage.
pip install "agentassert-abc[enforce,mcp]"