Check the record. Don't take our word for it.
This page states what this build enforces, how a surface reaches the decision, and how you verify a receipt without us. This site's tests fail if copy invents a certification or an unbounded claim.
Each block carries the hash of the one before it. Change a record and every later link breaks.
Enforced in this build
- When a check can't complete, the call is refused. Recent releases closed fail-open paths found in our own audit, each with a regression test.
- When a call is routed through PyxGrant, the model is not the enforcement point. PyxGrant decides before the call reaches the tool, the model, or the other agent.
- A held call needs a signed human decision — on the tool plane, the model plane, and A2A, not only tools. Nobody answering means it is refused, and an agent can't approve its own call unless you allow it. A rule can require N distinct Ed25519 approver keys, each bound to the exact payload and optionally to the rendering shown; a shared-secret HMAC name does not count toward a quorum, and the first valid deny refuses the call. Receipts and revocation checks on those planes match the tool plane when the path is routed through us.
- What runs is re-hashed against what was approved, so a swapped call is refused.
- Under the hardened profile, untrusted content that entered the session with no human break since can hold or refuse an irreversible or egress sink. The finding names the taint source.
- A grant minted for one principal is refused if this session acts as another (refused at bind).
- Under the hardened profile, a wrapped child MCP server's outbound HTTP(S) is pinned through the egress cage by default. A bind failure is non-fatal (the child runs without it). A raw socket, a non-proxy-aware runtime, or the agent's own process still needs OS egress default-deny — off until you apply it.
- Under the hardened profile, an agent can't rewrite its own MCP config or PyxGrant's policy. A pinned policy isn't replaced by an edit nobody approved.
- Under the hardened profile, high blast-radius actions are held or refused before they run. A hardened gateway also requires an operator-minted signed root token; a stripped-env child posing as root is refused.
- Every decision is written to a hash-chained log sealed with Ed25519, with no plaintext secret in it. Model and A2A chains are sealed the same way. Grant receipts and evidence packs can sign through the same external Signer — including a PKCS#11 HSM validated against SoftHSM. Post-quantum is a co-signature: with the PQ driver enabled, receipts carry ML-DSA-65 and Ed25519 over the same bytes; classical verifiers still accept them.
- A freeze reaches tool, model, A2A, and AG-UI traffic, including sampling and elicitation responses in flight, and can follow mid-stream, tool-result, and A2A-response legs. Freezing a parent grant expands over the grant lineage on every plane — a child-bound model or A2A call is held with the tool subtree. Resume is reversible; revoke is not. After revoke, provider re-read can prove the grant is gone (
TARGET_VERIFIED) or catch a self-reported OK that left it live (TARGET_FAILED). - Console Assurance can replay a signed session chain, seal a recovery drill without executing undos, surface standing-access discover, and show the path to one-file offline evidence. Revoke-with-proof and pack export remain operator CLI actions. A host whose on-host sensor is dark is not shown as proven coverage.
- When enabled, A2A outcome-divergence withholds a peer result whose task/context does not match what was authorized; a graduated
hitl.risk_laddercan step flag → hold → block → freeze as session risk rises. Optional auto-freeze on reliability, wall-clock, tool-cost, or SLA breach is off by default. pyxgrant evidence proveexports a pack, verifies it against a pinned published key, prints re-derived prevented-spend and closed-loop counts, then flips one byte of a copy to show it fails.evidence export|verifyis the same pack without the skeptic walk. Embedded-key verify is integrity and re-derivation, not authenticity, until you pin an external key (-strict -pubkey).- A policy file served with
-policy-verify-keymust carry a detached signature that verifies against an off-host key, or the gateway refuses to start. The byte pin alone is not enough once that gate is set. - A data-plane agent cannot call MCP management methods such as registry, config, or tools/register. Ordinary tool calls are untouched.
- An OIDC verifier with no issuer refuses every token. A missing issuer is not accept-anyone.
- A restricted or irreversible tool result on SSE is buffered until the verdict. A deny releases no bytes. Bytes that already left on another stream stay sent. Streaming model responses that need a complete-body gate are buffered the same way.
- Configuration written from the console goes through a versioned store with append-only history and fail-closed validation. Removing a user, token, or SSO binding from that store revokes it live — not only on the next restart. The console binds to loopback; a Postgres-backed store, Helm chart, and per-tenant isolation (file or Postgres) exist for shared deploys. Each gateway keeps deciding from its own policy without the console.
- Receiver-signed outcomes on tool results can be required when you enable them.
What reaches PyxGrant, and how.
PyxGrant can only decide what is routed to it. Each row says how a surface reaches it and what happens at the edges.
| Surface | How it reaches PyxGrant | Status |
|---|---|---|
| MCP tool calls | An inline proxy in front of each server, over stdio or HTTP | Enforced Refused calls never reach the server, and results are cleaned before the model sees them. A restricted or irreversible tool result on SSE is held until the verdict. Management methods from a data-plane agent are denied. Look-alike server names and tenant isolation are checked on the live path, not only as a library. |
| A coding agent's built-in shell and file tools | The Claude Code and Cursor hook, or hook generic | Enforced if installed Allow, ask, or deny before the tool runs. PostToolUse scans a document the agent just read for macros and injected text. Codex, Gemini, Copilot, Windsurf, Cline, and Aider use the same decide path through |
| Model API calls | The model proxy | Enforced if routed Budgets, rate limits, held models, the shared agency counter, and injection checks. Signed holds, receipts, and revocation apply on this plane as on tools. Under the hardened profile an unpriced model is refused. A client pointed straight at the provider isn't seen. |
| Agent-to-agent calls | The A2A proxy | Enforced once configured With no A2A policy it only observes. The design-partner profile refuses to start that way. Signed holds, receipts, and revocation apply here as on tools. Optional Form B checks that a peer's declared result task/context matches the authorized request; a divergent id is withheld in enforce. That check is self-consistency on an untrusted peer — not an independent provider read-back. Streamed responses are not task-correlated. |
| Your own agents: LangGraph, CrewAI, Python | The decision service on loopback | Your code asks Enforced when your code asks first and honors the answer. |
| Agentic browsers | A loopback decision daemon | Your code asks The daemon decides and holds. The in-browser shim that calls it isn't part of this build. |
| Payments, plant controllers, voice agents | Domain decisions | Decides only PyxGrant approves, holds, or refuses. |
| Web destinations | An egress-capture forward proxy | Enforced if routed Every host is classified. |
| Finding agents | Machine scans, plus Microsoft Graph, Okta, and Amazon Bedrock inventories | Observed
|
| Sensitive data in results and arguments | Pattern checks and a local semantic layer | Partial Known formats such as keys, cards, SSNs, and record numbers, plus sensitive meaning without keywords. Not everything is caught. |
| Calls that skip PyxGrant | Reconciliation against the provider's own audit export | Named afterwards An inline gateway can't stop a call that never reaches it. It names each one if you supply the export. Hardened pins a wrapped server's HTTP(S) through the egress cage; coverage-gap quarantine and OS egress default-deny stay off until you set them. None of those see a raw socket that ignores the proxy. |
| Every file and syscall on the host | Child confine, plus optional Linux sensor | Partial Kernel refuse is Linux: an opt-in privileged sensor can refuse exec in-kernel (eBPF LSM and fanotify-PERM). Landlock and optional seccomp cover a wrapped child; policy can require the fence, including |
You don't have to trust us to check the record.
1. Keep the key apart
Set audit.signing_key_path, supply the key from the environment, or point grant and seal signing at an external KMS / PKCS#11 HSM, so whoever can read the log can't re-sign it. PyxGrant warns when a software key sits beside the log.
2. Walk the chain
pyxgrant audit verify-all checks every record's link to the one before it and the Ed25519 seal over the chain head.
3. Check a receipt offline
pyxgrant receipt verify checks one decision against a published key bundle or JWKS, with no call to us. A hybrid receipt also carries the ML-DSA-65 leg when the PQ driver was enabled. pyxgrant evidence prove walks export → pinned-key verify → re-derived totals → a one-byte tamper that must fail. Embedded-key verify is integrity, not authenticity, until you pin an external key.
4. Closed-loop
Authorized and what actually ran either match, diverge, or are not yet verified. No receipts means retention is off, not all-clear. The console shows this live.
5. Coverage attest
A signed list of what this binary enforces, detects, or proves. It is not a coverage percentage.
6. Flight Recorder
One signed, hash-linked trace across every session that shares a run, not only one session's log.
What PyxGrant records, and what it doesn't.
Recorded
- The agent that acted, and the person it acted for
- Server, tool, decision, reasons, and findings
- Detected secrets and personal data as fingerprints, not plaintext
- Held calls, who decided them, and when
Never done
- Keystroke logging or screen recording
- Productivity scoring or ranking developers
- Emotion inference
- Training on customer data