Retrieved article excerpt
Open article · Retrieved 2026-09-11T06:23:17.908793+00:00
AgentFence Stop unsafe agent tool calls before they reach your MCP server AgentFence is a local tool-call firewall. It evaluates the exact MCP tool and
arguments, decides allow / deny / ask before forwarding, and writes a
redacted audit receipt you can verify offline. flowchart LR
A["Agent tool call"] --> B{"AgentFence policy"}
B -->|ALLOW| C["MCP server"]
B -->|DENY / ASK| D["Stop before side effect"]
B --> E["Redacted receipt"] Loading See the boundary in under a minute The maintained, offline demo runs AgentFence in front of a real MCP stdio
session. An allowed read returns prompt-injected text; the resulting .env write is denied before the upstream server sees it. git clone https://github.com/dgenio/agentfence.git cd agentfence
./examples/demo-blocked-call.sh AgentFence flagship MCP demo
ALLOW filesystem.read path=project-notes.txt -> upstream
DENY filesystem.write path=.env -> BlockedByPolicy before upstream
PROOF upstream received tools: ["filesystem.read"]
PASS safe read executed; injected .env write blocked before side effect. The demo's tiny policy , exact MCP requests , and expected audit receipt are committed and exercised in CI. The full command also prints the normalized
receipt and verifies its hash chain. The scenario explanation shows how the proof works. Security boundary: AgentFence governs tool calls that pass through its
configured CLI/proxy boundary. It is not a sandbox and does not prevent prompt
injection; it limits what a successful injection can cause at mediated tool
boundaries. Calls that bypass AgentFence are outside its control, and ask requires a trustworthy approval path. See CLAIMS and when not to use AgentFence . AgentFence is a single, local Go binary with no account or built-in telemetry.
It can wrap an MCP stdio server, gate a streamable-HTTP server, or evaluate
recorded tool calls in CI. Policies are deny-by-default; audit logs can be
hash-chained and signed. Who it's for: security and platform operators who need to gate agents they
did not write, with a policy and audit trail they control. New here? Follow the 10-minute Quickstart — from
install to a policy-gated MCP setup with an observed allow and deny. Then see
the Daily Driver guide for day-to-day operation and CLAIMS for what AgentFence does and does not promise. VeriCordon: inspectable authorization evidence in CI Generate inspectable authorization evidence for the exact calls and policy
AgentFence evaluated. VeriCordon turns a policy, representative call JSONL,
and optional policy fixtures into a human-readable report.md plus a versioned report.json . - uses : dgenio/agentfence/[email protected] with : policy : agentfence.yaml calls : testdata/tool-calls.jsonl tests : testdata/policy-tests.yaml The safe downloadable artifact excludes raw audit.jsonl by default. Missing
evidence stays partial / not_evaluated ; exact-action + effective-policy
binding is reported only for the calls whose supplied audit evidence supports
it. No account or hosted service is required. See the VeriCordon authorization-evidence guide for
the copy/paste workflow, minimal inputs, a real missing-evidence example, the
fresh-consumer 3/3 binding result, and the explicit non-claims. Current status AgentFence is in active development. The table below distinguishes what works
today from what is planned. Do not assume planned features are usable yet. Capability Status Where to read more JSONL batch policy evaluation ( check ) Implemented Quickstart Allow / deny / ask decisions Implemented docs/policy-language.md Path, argument, URL, and shell-command constraints Implemented docs/policy-language.md Tool groups and wildcard matching Implemented docs/policy-language.md Strict policy validation ( validate ) Implemented Quickstart Single-call trace ( explain ) Implemented agentfence explain --help Policy fixture tests ( policy test ) Implemented examples/policy-tests.yaml Regex-based redaction of audit values Implemented docs/policy-language.md Structured output modes (text / json / jsonl) Implemented agentfence check --help CI gating via --fail-on Implemented agentfence check --help VeriCordon Markdown + JSON authorization evidence Implemented docs/evidence-bundle.md Pre-built release binaries Implemented Pre-built binaries Detection / prevention / audit-only / dry-run modes Documented docs/modes.md Interactive TTY approval for ask decisions Implemented Approval and dry-run Approval timeout with default-deny Implemented Approval and dry-run Dry-run evaluation mode Implemented Approval and dry-run MCP stdio proxy ( agentfence proxy ) Implemented docs/integration-guide.md , docs/architecture.md Policy enforcement on intercepted tools/call Implemented docs/integration-guide.md Stateless MCP 2026-07-28 tool-call shape/headers Tested examples/hero-requests.jsonl , internal/httpproxy Tamper-evident hash-chained audit logs Implemented docs/threat-model.md Ed25519-signed audit events ( --sign-key ) Implemented docs/audit-event-schema.md , docs/threat-model.md Audit anchors ( audit anchor / verify --anchor ) Implemented docs/threat-model.md Audit-log rotation and retention ( --audit-max-* ) Implemented docs/threat-model.md Durable audit writes ( --audit-fsync ) Implemented docs/threat-model.md External audit sinks ( --audit-sink syslog/HTTP) Implemented docs/threat-model.md Audit event JSON Schema Implemented docs/audit-event-schema.md Audit-log summarisation ( audit summarize ) Implemented agentfence audit summarize --help weaver-spec trace export ( audit export ) Implemented docs/interop.md Fuzz coverage for parser, glob, and redaction Implemented make fuzz MCP streamable-HTTP proxy ( agentfence proxy-http ) Implemented docs/architecture.md , docs/integration-guide.md Confused-deputy / taint escalation Implemented docs/threat-model.md , docs/policy-language.md Reusable policy packs ( init --pack ) Implemented docs/policy-language.md GitHub Action for CI policy checks Implemented docs/integration-guide.md Typed reason codes on every decision Implemented docs/audit-event-schema.md Structured operational logging ( --log-format json ) Implemented docs/observability.md Decision metrics ( check --metrics ) Implemented docs/observability.md Prometheus metrics endpoint ( --metrics-listen ) Implemented docs/observability.md Why this exists Tool-capable agents are useful, but they can also be risky: Prompt injection can trigger unsafe calls. Agents may take destructive actions too quickly. Sensitive values can leak into logs. Teams need an audit trail of what was allowed, denied, or sent for approval. AgentFence is a practical local control point before execution. Install Install script (Linux/macOS) curl -fsSL https://raw.githubusercontent.com/dgenio/agentfence/main/scripts/install.sh | sh The script detects your OS/arch, downloads the matching release archive, and verifies it against checksums.txt (failing closed on a mismatch) before
installing to ~/.local/bin . Pin a version or change the directory with AGENTFENCE_VERSION / AGENTFENCE_INSTALL_DIR . Homebrew (macOS/Linux) brew install dgenio/tap/agentfence Installs the binary plus shell completions and the man page. The tap is updated
automatically on each release. Windows (Scoop / winget) scoop bucket add dgenio https: // github.com / dgenio / scoop - bucket
scoop install agentfence # or winget install dgenio.agentfence Container image A minimal, non-root, multi-arch (amd64/arm64) image is published to GHCR: docker run --rm ghcr.io/dgenio/agentfence:latest version See docs/distribution.md for
running the HTTP proxy in a container with a mounted policy and audit-log
volume. Pre-built binaries Pre-built binaries for Linux, macOS, and Windows (amd64 and arm64) are
published on the GitHub Releases page for each tagged release. Each release includes a checksums.txt , a cosign
signature, and an SBOM for verification (see docs/distribution.md ).
Download the archive matching your platform, extract it, and put the agentfence binary on your PATH . Archives also bundle shell completions
( completions/ ) and the man page ( manpages/agentfence.1 ). Build from source go build -o agentfence ./cmd/agentfence To embed a release version at build time (compatible with goreleaser): go build -ldflags " -X main.Version=0.1.0 " -o agentfence ./cmd/agentfence Or via the project Makefile: make build VERSION=0.1.0 Quickstart Run the built-in demo: ./agentfence demo Run policy checks against example tool calls: ./agentfence check --policy examples/policy.yaml --call examples/tool-calls.jsonl Write audit events to an append-only, owner-readable log: ./agentfence check --policy examples/policy.yaml --call examples/tool-calls.jsonl --audit-log audit.jsonl Sign each event (writer authentication), rotate the log, and ship a copy to an
external sink — then verify the chain and the signatures offline: ./agentfence audit keygen --private audit.key --public audit.pub
./agentfence check --policy examples/policy.yaml --call examples/tool-calls.jsonl \
--audit-log audit.jsonl --tamper-evident --sign-key audit.key \
--audit-max-size 10485760 --audit-keep 5 --audit-sink syslog://127.0.0.1:514
./agentfence audit verify --log audit.jsonl --pubkey audit.pub Publish an anchor so a third party can later detect silent deletion or
truncation, then check the log against it: ./agentfence audit anchor --log audit.jsonl --out audit.anchor.json # commit this somewhere you don't control ./agentfence audit verify --log audit.jsonl --anchor audit.anchor.json Sign the anchor so a verifier can confirm it was not itself swapped for one
naming an earlier event: ./agentfence audit anchor --log audit.jsonl --out audit.anchor.json --sign-key audit.key
./agentfence audit verify --log audit.jsonl --anchor audit.anchor.json --anchor-pubkey audit.pub Get machine-readable output for CI pipelines: ./agentfence check --policy examples/policy.yaml --call examples/tool-calls.jsonl --output json
./agentfence check --policy examples/policy.yaml --call examples/tool-calls.jsonl --output jsonl | jq ' .decision ' check --summary <file> writes a compact JSON gate summary (per-decision
counts, top denied tools/reasons, and whether --fail-on matched) alongside the
decision stream, so CI can surface "what was denied" without recomputing it with jq . Write it to a file for a clean machine-readable artifact — it is
produced even when --fail-on fails the run. ( --summary - writes to stderr
instead, which is convenient for logs but, on a gate failure, also carries
diagnostic lines and so is not pure JSON.) ./agentfence check --policy examples/policy.yaml --call examples/tool-calls.jsonl \
--no-interactive --fail-on deny --output json --summary gate-summary.json policy test and audit verify share the same --output text|json convention
as check , explain , and audit summarize , so every gate the pipeline runs
can be consumed structurally while preserving each command's exit code: ./agentfence policy test --policy examples/policy.yaml --tests examples/policy-tests.yaml --output json
./agentfence audit verify --log audit.jsonl --output json Validate a policy file before use (catches typos and unknown fields): ./agentfence validate --policy examples/policy.yaml Approval and dry-run modes check exposes three operator controls for the ask decision and for
"evaluate without enforcing" workflows: --no-interactive — never prompt; auto-deny any ask decision. The audit
reason is non-interactive: ask auto-denied . Use this in CI. --approval-timeout <duration> — bound the wait for a y/N response (e.g. 30s , 2m ). On expiry the call is denied with reason approval timeout . 0 (the default) waits forever. --dry-run — evaluate policy and write audit records but never invoke the
approver and never propagate a non-zero exit from --fail-on . Each audit
record carries "mode": "dry_run" so downstream readers can distinguish
simulated decisions from enforced ones. Text output is suffixed with [dry-run] . Typical CI invocation: ./agentfence check \
--po