Proof of what your AI agents did.
agent-custody records it, denies what was never authorized, and proves it to anyone.
A gateway between an agent and its tools. Every call is checked against a grant a person signed and a policy, then forwarded or denied, and a signed receipt is issued either way. The receipt's hash lands in a log nobody in the chain can rewrite. For every agent framework, in any language.
Register for a free accountView GitHub Verify a receipt
bun run demo, against a stand-in Stripe.The problem
Your agents' record is their own word.
When an agent acts wrongly, the only account of it is the log its own process wrote, kept by the team that ran it. Every field is a claim. Nobody outside the team can tell what was authorized from what merely happened.
Made-up authority
The agent refunds £50,000. Its log says the customer asked for it. Nobody signed anything that allowed it.
Looks like: a closed ticket
A log that can be edited
The team that ran the agent holds the log. After the incident, the entry that matters is gone, or different, and nobody can tell.
Looks like: a clean audit
Evidence nobody else can check
Traces sit in a vendor account. The auditor, the customer, or the regulator gets a screenshot and a promise.
Looks like: compliance
- decision
- denied no permit policy matched
- tool
- stripe.refund observed
- asked for
- refund £50,000.00 to cust_123 claimed
- gateway checked
- customer cust_123, verified true observed, fetched by the gateway
- policy
- refunds up to £1,000, verified customer · ba4e4461ffc4…
- agent
- support-agent attested
- authorized by
- user_456 attested, a grant they signed
- log
- leaf 2 of 2 · root 910a95eef12e…
Open in the verifierFrom the published conformance vectors. Runs in your browser; nothing is uploaded.
A receipt proves what was signed, observed, and logged, and labels everything else as the agent's own claim. The proof table says which is which, for whoever has to sign off. Where the data goes, what reaches the log, and how secrets are handled: the FAQ.
How it works
Authorize. Gate. Record. Log. Verify.
- 01Authorize
A person signs a grant: which agent, which tools, for how long. The gateway trusts that key and nothing else.
- 02Gate
Every call goes through the gateway. It fetches the facts itself, evaluates the policy, and forwards or denies before the tool hears anything.
- 03Record
One signed receipt per call, allowed or denied: who authorized it, what the agent asked, what the gateway checked, what happened.
- 04Log
The receipt's hash goes to a Merkle log whose signed heads are published on a second host. The operator cannot rewrite it unnoticed.
- 05Verify
Anyone with the public keys checks a receipt, in the shell or in the browser, offline. No account, no access to the agent.
Denied at runtime
The call never reaches the tool.
A policy is a Cedar file. The gateway evaluates it against what the agent asked and the facts it fetched itself. Consequential calls are logged before they are forwarded, so the evidence exists before the side effect does. A denial is a receipt too.
Not a trace
Not a trace. Not an application log.
| Application log | Trace OpenTelemetry, LangSmith | Gateway receipt | |
|---|---|---|---|
| Written by | the agent's process | the agent's process | a gateway the agent talks to, signing with its own key |
| Says the call was allowed or denied before the tool ran | no | no | yes, and the denial is a receipt too |
| Who authorized it | not recorded | not recorded | the grant a person signed, embedded and verified |
| Can a third party show the record was not rewritten | no | no | yes: a Merkle log with heads signed by a key the operator does not hold |
| Who can check it | whoever has the log access | whoever has the tracing account | anyone with the public keys, offline |
Traces stay useful. A receipt can be exported to OpenTelemetry or Splunk as one span or event per call, with the receipt id as the trace id, so the evidence and the observability sit side by side.
Quick start
A verified receipt in ten minutes.
- 1Install and make keys
Node 22 or later. One key for the gateway, one for the person who signs grants.
- 2Sign a grant
Which agent, which tools, for how long. The gateway trusts the principal's public key.
- 3Put the gateway in front of the tools
It is an MCP server. Point your agent at it instead of at the tools, or use an SDK adapter: Claude Code, Claude Agent SDK, OpenAI Agents SDK, LangChain, Vercel AI, Python.
- 4Verify the receipt
In the shell, or drop it on the browser verifier. Register a tenant on the hosted log and the receipt's hash is somewhere you cannot rewrite.
# 1. install and make keys npm install @agent-custody/receipts npx agent-custody keygen --dir keys --name gateway npx agent-custody keygen --dir keys --name principal # 2. sign a grant for the agent npx agent-custody grant --key keys/principal.key \ --principal user_456 --agent support-agent \ --scopes customer.lookup,stripe.refund --out grant.json # 3. run the gateway in front of the tools npx agent-custody gateway --config gateway.json # 4. verify a receipt it issued npx agent-custody verify receipts/<id>.json \ --issuer-key keys/gateway.pub --principal-key keys/principal.pub
{
"identity": { "keyFile": "keys/gateway.key" },
"grantFile": "grant.json",
"trustedPrincipalKeys": ["keys/principal.pub"],
"policyFile": "policy.cedar",
"upstream": { "command": "your-mcp-server" },
"precommit": ["stripe.refund"],
"receiptsDir": "receipts",
"log": { "url": "https://log.agent-custody.dev/t/<tenant>/",
"tokenEnv": "AGENT_CUSTODY_LOG_TOKEN", "hashOnly": true }
}The whole path, with every command's output, is Getting started. Twenty runnable tutorials cover the rest.
Where to go
Pick a stack: Claude Code, OpenAI Agents, LangChain, Vercel AI, OpenClaw, DeepSeek Harness, Hermes, Python. Ten minutes to a receipt that verifies in the browser.
The SDK path records the agent's own word.Make it evidenceThe gateway, a signed grant, and a log run by someone else. For calls that move money or touch production.
Hosted log: free to 10,000 appends a month.For security reviewThe questionnaire with every no left as a no, the threat model, the compliance mapping, and the FAQ on where the data goes: what a receipt holds, what reaches the log, how secrets are handled.
Dated, and honest about the witness.This repository is developed under custody: every tool call the coding agent makes is a receipt, hash-logged to our tenant on the hosted log. The custody page shows the hook, the policy, the keys, and two of those receipts to verify. Everything you run yourself is Apache-2.0.