01
Design & threat model
Why I put a proxy between my AI agent and my server
Three failure modes, and why the enforcement point sits at the protocol layer.
Project · AI Security
A least-privilege proxy for AI agent tool calls.
AgentGuard is a process between the AI agent and the MCP server. The agent's client configuration points at AgentGuard instead of the server. AgentGuard launches the real server, and every message between the two then passes through it. It works on MCP's stdio transport, newline-delimited JSON-RPC, so neither the agent nor the server changes any code. Each tools/call and resources/read request is checked before it is forwarded. The results of those calls, and of prompts/get, are checked before they are returned.
Rules check the arguments of each request. File paths, shell commands and network hosts each have a deny list and an allowlist, and any tool can carry its own settings. A path is resolved first, including its relative form, .. and symlinks, and is then judged as the file the server would open. An argument's category comes from the schema the server declares in tools/list and from the argument's name. An argument that fits no category is allowed and logged by default, and can be set to be denied. A denied call never reaches the server.
Text returned by tools, resources and prompts is scanned for content shaped like instructions. Error messages are scanned too. The text is normalized before matching: zero-width characters are removed, lookalike and fullwidth characters are folded, and one layer of base64 is decoded. If any rule matches, the whole result is blocked, and the agent receives an error response that names the rules that matched.
Output that passes detection is checked once more. Secrets in known formats are replaced with [REDACTED:rule-name], and everything else is left unchanged. Matching runs on the normalized text. The replacement lands only on the matching span of the original.
Every decision from every layer is one entry, and each entry carries the hash of the one before it. An edit to an entry in the middle is located by the next verify. Deleting entries at the end, or recomputing every hash after an edit, is detected only if the chain's head was stored elsewhere beforehand with agentguard anchor. With anchor_file set, that happens at the start and end of each session. agentguard report lists, per session, the files, hosts and commands the agent accessed.
One run is one session. A session can be capped on the number of file, network and command calls, and on the bytes returned. There are also three fixed sequence rules, for example denying network calls after a sensitive file has been read. All of these are off in the bundled default policy.
A rule can return ask. agentguard approve answers it from another terminal: deny, allow once, allow for this session, or allow always. If any rule in the same call returns deny, the call is denied without asking. The channel is a Unix domain socket. Windows has no such channel, and every ask is treated as deny.
pip install agentguard-mcpagentguard/The figures are for v0.2.0 on PyPI, repository commit 762145c. Running scripts/stats.py, pytest and coverage at that commit reproduces them. Page updated 11 October 2026.
The first command installs from PyPI. The second starts the MCP server through agentguard instead of directly. The third checks the audit log. The default policy ships inside the package. To change the rules, export a copy with agentguard default-policy and pass it with --config. The only change on the client side is the launch command. The server is not changed.
pip install agentguard-mcp
agentguard run -- python3 your_mcp_server.py
agentguard verify-audit agentguard_audit.log
The repository's demo/run_demo.sh runs twelve steps under the default policy against a server with no restrictions of its own, first without the proxy and then with it. A read of ~/.ssh/id_rsa is denied and logged. The same read through a tool whose argument is not called path is denied as well. A file that contains an AWS key is returned with the key masked. A poisoned web page is fetched, because the URL is legitimate, and its content is blocked whole as injection. agentguard report lists what the session touched. An audit entry is edited by hand, and the next verify reports the changed line. The recording was made with 0.2.0 and runs about 40 seconds.
unclassified_arguments: deny.The full reasoning is in THREAT_MODEL.md.
Tools such as garak and promptfoo red-team a model before deployment. They do not see what a running agent receives. AgentGuard is on the runtime traffic path and enforces policy on every call. The two kinds of tool are complementary, not the same category.
The same category is MCP runtime gateways: mcp-firewall, Lasso's MCP Gateway, Microsoft's MCP Gateway and several smaller interceptors. They reached roughly the same shape over the same period. The difference is size. AgentGuard has one runtime dependency, about 3,900 lines of core code in 13 modules, no dashboard and no SaaS component, and an audit log whose tamper evidence is documented and can be checked independently. It has fewer features than those tools. In return, the code can be read and reviewed in full. The survey in the repository compares them item by item, including where the more mature options are ahead.
agentguard anchor prints the head, and the user decides where to keep it.01
Design & threat model
Three failure modes, and why the enforcement point sits at the protocol layer.
02
Detection rules & tradeoffs
Why a hit blocks the whole result, and a hole the test suite found.