The full upstream README, mirrored here for reference. Install config, tool schemas, adoption signals, and an original overview live on the Agentguard listing page.
60 seconds to a safe first run. Your agent already has an MCP config. Put agentguard in front of it, run the agent once in dry-run, and read what it would have done:
agentguard is an MCP policy proxy for agents that touch production. It sits between the agent and its MCP servers, sees every tool call, and enforces one YAML file:
spend_usd across every provider, from tool arguments (stripe_create_charge.amount), tool results (cost_usd), and — with the SDK's guarded fetch — LLM token usage from OpenAI, Anthropic and Gemini responses. The call that would exceed the cap gets CAP_EXCEEDED with the remaining budget.approval.tools: [crm_delete_*] makes the agent get APPROVAL_REQUIRED + an id; a human runs agentguard approve <id> (or clicks the button in Slack) and the agent's identical retry goes through once.agentguard kill (a file), AGENTGUARD_KILL=1 (env), or POST /kill (HTTP): every run halts instantly with KILLED until agentguard resume.agk_… key with its own allowlist, denylist and caps. Only the key's hash lives in the policy.agentguard diff shows what would have changed.(tool, normalized args) 3× in the last 30 calls, or an A→B→A→B cycle, returns LOOP_DETECTED. Timestamps, ids, whitespace and key order are ignored.tool_calls, writes, deletes, emails, spend_usd and custom counters, per run and per day.prev_hash and hash; agentguard verify proves no entry was edited, removed from the middle, or reordered (see Limits for what a local chain cannot prove on its own).No LLM calls. No phone-home. No account. MIT.
Two install paths, one policy engine: the MCP proxy (npx @agentwares/agentguard, stdio + Streamable HTTP, multiple upstreams) and the SDK/middleware (@agentwares/agentguard-sdk) for OpenAI Agents SDK, LangChain or plain-function tools that never go through MCP.
init writes agentguard.yaml next to your config, backs the config up (*.agentguard-backup), and replaces its servers with one entry:
Tools keep their names (prefixed <upstream>__ only on collision). Your MCP client sees one server; agentguard connects to all of them and holds their credentials.
Spawned with no arguments at all — what an install from the MCP registry does — agentguard serves the same stdio proxy and reads AGENTGUARD_CONFIG or ./agentguard.yaml. In a terminal it prints the help instead.
Prefer HTTP (several agents, scoped keys, Slack approve buttons)? agentguard proxy --http --port 8788 and point clients at http://127.0.0.1:8788/mcp with an X-Run-Id header per run and Authorization: Bearer agk_… per agent.
agentguard init generates this file with every knob explained inline. The short form:
Classification order: classify.* patterns → MCP annotations.readOnlyHint / destructiveHint → verb heuristics (get/list/search… read, create/update/delete/send/execute… write, pay/charge/refund… + stripe_*/x402_* spend). agentguard tools prints every tool with its class and why.
Every block is an in-band tool result with isError: true and a JSON body the model can act on:
Codes: KILLED, APPROVAL_REQUIRED (retryable once approved), APPROVAL_DENIED, LOOP_DETECTED, CAP_EXCEEDED, TOOL_DENIED, UNKNOWN_TOOL, UPSTREAM_ERROR. Successful and faked results carry _meta.agentguard = { class, verb, mode, outcome, dryRun, seq, run_id }.
Run identity: X-Run-Id header (HTTP) → _meta.runId on the call → session → one id per proxy process. Per-run caps and the loop window are per run; per-day caps are per policy (and per agent).
| Command | What it does |
|---|---|
agentguard init [--client path] [--all] [--no-probe] [--mode enforce] [--undo] | generate the policy, rewrite the client config (project-level by default) |
agentguard proxy [--http --port 8788] [--agent name] [--run-id id] [--mode m] | run the proxy (stdio default) |
agentguard report [--run id | --all] [--json] | what this run did / would have destroyed / spent; where it was halted; chain status |
agentguard diff [--run id] | mutation diff of faked writes |
agentguard verify [audit.jsonl] | recompute the hash chain; exit 1 on the first break |
agentguard status [--run id] | counters vs caps, kill state, pending approvals, running HTTP proxy |
agentguard tools [--json] | every exposed tool with class, verb, upstream and the reason |
agentguard kill [reason] / agentguard resume | halt everything now / clear it |
agentguard approvals [--all] / approve <id> / deny <id> [--note …] | the approval queue |
agentguard key create <agent> [--allow p]… [--deny p] [--writes n] [--spend n] [--mode m] / key list / key revoke <agent> | scoped credentials |
agentguard connect <key> [--write] [--client path] [--all] [--url base] | point this machine's MCP client at a hosted proxy (paid tiers); prints the config, --write merges it in |
agentguard permission-diff [--base ref] [--head ref] [--fail-on-widen] | which config changes widen agent permissions (also a GitHub Action) |
The CLI enforces policy on your machine and needs no account. The paid tiers move enforcement
server-side — shared state across machines, retained audit, alerting — and connect is how you
point a client at yours:
Unlike init, connect adds one remote server and leaves the rest of your config alone. The key
comes from your dashboard; everything else — proxy URL, mode, band — is answered by the server.
HTTP control endpoints (token in .agentguard/http.json): GET /health, GET /status?run=, POST /kill, POST /resume, GET|POST /approve/:id, /deny/:id, GET /approvals.
pnpm test runs the CLI suite (24 tests; 64 more in agentguard-core, 10 in the SDK): the engine over InMemoryTransport, the spawned stdio proxy, the Streamable HTTP proxy with X-Run-Id, scoped keys and control endpoints, init against real configs, and a recorded-fixture replay (fixtures/recorded/crm-session.json; re-record with RECORD_FIXTURES=1). pnpm conformance runs the official @modelcontextprotocol/conformance server suite against the proxy with a sample server behind it (tools, resources, prompts, completions, logging, progress, sampling and elicitation are relayed).
fetch (or spend.tools rules for MCP tools that call models).outputSchema; agents that depend on real ids from a create → update chain will see plausible but fake ids. dry_run.tools lets you fake only the dangerous tools in enforce mode.agentguard approve <id> command.agentguard verify prints the head hash and the entry count — record them (CI log, ticket, chat) to close the gap, or use the hosted tier, which publishes a daily Merkle root you can check the run against.@agentwares/agentguard-sdk — the same engine for OpenAI Agents SDK / LangChain / plain functions, plus the guarded fetch for LLM spend.@agentwares/agentguard-core — the Web-standard policy engine (bring your own stores).agentguard.yaml, .claude/settings.json or mcp.json.| Path | What |
|---|---|
apps/agentguard-cli | the agentguard CLI and MCP proxy — published as @agentwares/agentguard |
packages/agentguard-core | the policy engine, Web-standard — published as @agentwares/agentguard-core |
packages/agentguard-sdk | middleware for non-MCP tool calls — published as @agentwares/agentguard-sdk |
permission-diff | the GitHub Action, uses: agentwares/agentguard/permission-diff@main |
This repo is generated from the agentwares monorepo, which stays private because it also holds the paid products. Issues and pull requests here are read and applied upstream.