Prove what your agent did —
to someone who doesn’t trust you.
AI agents are just starting to take consequential actions — placing orders, moving money, changing records. When one does, the only proof it happened as intended is the operator's own word. An Agent Action Capsule fixes that: a tamper-evident, content-private record of the action that anyone can verify from the record itself — without trusting the operator.
It's early — for the technology and for this profile. The aim is to get the record of what agents do right while it's still being figured out: in the open, verifiable by anyone, and built to be donated so it ends up owned by no one. (Roughly the role TLS plays for a connection, applied to an agent's actions.)
pip install capsule-emit → receipt = seal(payload) — a signed, witnessed record a stranger can verify. No config, keys, or account required. See it as real, runnable code →
A tamper-evident record of what your AI agent did.
Say your agent pays an invoice. Six months later an auditor asks: did it really only pay approved vendors, for the right amounts? Today your only answer is your own logs — your word for it. An Agent Action Capsule is a signed, privacy-preserving capsule of each consequential action, witnessed by an independent log, so you can hand the auditor proof they can check for themselves — without giving them access to your systems, and without asking them to trust you.
Who it's for today: agent developers who want verifiable records, and standards / security folks. It's early and built in the open — not yet a turnkey compliance product. What exactly is a capsule? →
Agents take actions. Right now, you have to trust the operator that they happened as claimed.
The Agent Action Capsule closes that gap with three properties — the same shape SCITT (the IETF effort standardizing transparency for signed statements, now standardized in RFC 9943 (the SCITT Architecture), with the COSE Receipts specification now published as RFC 9942) defines for software supply chains, profiled for agent actions.
Sealed at the moment of action
A capsule is a statement committing to the action, its inputs and outputs (by digest), and the model/runtime that produced it — content-addressed by default, and COSE-signed at the Signed-Statement tier (COSE is the standard format for signing records like this). Tamper any byte and verification fails.
Witnessed by an independent log
The statement is registered to a SCITT Transparency Service, which returns a receipt proving inclusion. The log can't quietly drop or rewrite history.
Anyone can check, offline
An auditor, reviewer, or regulator verifies the signature and the inclusion proof from the bytes alone — no access to the operator's systems. You trust the log's key, not the operator.
Seal from the framework you already use.
One capsule, one witness, one verify — an adapter only changes where you hook in, over a ~30-line base. No protocol change; input and output are sealed automatically. Adapters seal consequential actions (writes + sensitive reads), not every call — what counts? → Pick your runtime and copy the code:
from mcp.server.fastmcp import FastMCP
from capsule_emit.adapters.mcp import MCPCapsuleEmitter
server = FastMCP("po-agent")
emitter = MCPCapsuleEmitter(operator="acme-co", developer="goose-agent@v1")
@server.tool() # Goose connects over MCP
@emitter.tool(effect_type="write_order") # capsule-emit seals every call
def submit_order(vendor, amount, po_number):
return place(vendor, amount, po_number)
server.run() # stdio — add to Goose as an extensionfrom capsule_emit.adapters.mcp import MCPCapsuleEmitter
emitter = MCPCapsuleEmitter(operator="acme-co", developer="po-agent@v1")
@emitter.tool("submit_order") # one line — every call sealed + witnessed
def submit_order(vendor, amount, po_number):
return place(vendor, amount, po_number)from capsule_emit.adapters.langchain import LangChainCapsuleEmitter
emitter = LangChainCapsuleEmitter(operator="acme-co", developer="research-agent@v1")
# attach as a callback — every tool call on the run is sealed
agent.invoke(payload, config={"callbacks": [emitter]})from capsule_emit.adapters.crewai import CrewAICapsuleEmitter
emitter = CrewAICapsuleEmitter(operator="acme-co", developer="ops-agent@v1")
safe_tool = emitter.wrap(my_tool) # one capsule per tool call
agent = Agent(role="AP clerk", tools=[safe_tool])from capsule_emit.adapters.hermes import HermesCapsuleEmitter
emitter = HermesCapsuleEmitter(operator="acme-co", developer="hermes-agent@v1")
result = execute_tool(name, inputs)
emitter.after_tool(name, inputs, result) # one line at the tool boundary# 1. run the capsule-emit policy service (gRPC ExtMcp hook)
pip install "capsule-emit[agentgateway]"
capsule-emit-agentgateway # listens on :50051
# 2. point agentgateway at it — seal tools/call only (in config.yaml)
mcpGuardrails:
processors:
- kind: remote
host: "localhost:50051"
methods: { "tools/call": full } # reads pass through
failureMode: failOpen # capsule outage degrades gracefullyDon't see your framework? The base is ~30 lines — add an adapter or open a request ↗. Full guides live in capsule-emit/docs/adapters.
Purpose-built for agent actions — not generic attestation.
Its tamper-evident seal is the capsule_id — a SHA-256 of the statement's canonical form (RFC 8785 JCS); recompute it and it must match. And it's content-private by construction: a capsule carries digests of your inputs and outputs, never the raw prompts, vendors, or amounts. Around that seal it commits exactly what an agent action needs to be accountable:
The may/did, bound to its effect
What the agent decided and whether it executed, was confirmed, denied, or blocked — with a confirmed-effect binding, so the claim and the real outcome can't drift apart.
Which model decided, by digest
The model that decided, with the full input it saw — system prompt, context, tools, and the action's arguments — and the output, each committed as a SHA-256 digest. The proof travels; the raw values stay with you.
Trails for human-in-the-loop
Confirm, supersede, and escalate links turn approved → executed → confirmed into one verifiable chain — the basis for review and selective disclosure.
That's the shape a build-artifact attestation doesn't give you — and the reason to standardize one agent-action profile together rather than reinvent it. What's in a capsule → · tamper one, watch the seal break →
One statement layer. Any transparency service. Neutral, donatable substrate.
The capsule is a statement-layer profile — it makes no claim about which verifiable-data-structure the log uses. Each layer is a separate open-source library.
agent-action-capsule — the Signed Statement format (COSE_Sign1 over application/agent-action-capsule+json) + the reference verifier.capsule-emit — seal an action in one call, or wrap an existing tool with one decorator. The agent-developer on-ramp.scitt-cose — verifies SCITT receipts across verifiable-data-structures (vds = the log's proof format): RFC9162_SHA256 (vds=1) and CCF ccf.v1 (vds=2).capsule-anchor — a neutral, product-free SCITT Transparency Service. Live at anchor.agentactioncapsule.org.Composes with what you already run — it doesn't replace it.
Identity, authorization, payments, runtime gates — each proves its own slice, and each is self-attested about it. The capsule composes with all of them by digest-reference, and adds the one thing none can self-provide: a record checkable by someone who trusts neither the operator nor any single layer.
| Leg | Answers | Doesn't answer |
|---|---|---|
| WHO — Identity e.g. SPIFFE/WIMSE, agent IDs | which accountable principal — who the agent is | what it did |
| CAN — Authorization e.g. OAuth/AAuth, GNAP, policy | what it may do | what it actually did, and the outcome |
| Payments / settlement e.g. AP2 | whether a human authorized the spend | what was actually done, end-to-end |
| AUDIT — Runtime gate / observability e.g. a policy gateway, your logs | what you say happened | nothing to a party who doesn't trust you — it's self-attested |
| WHAT — Agent Action Capsule | what it provably did | composes with all of the above |
Each layer is self-attested about its own slice; the capsule is the independent record of what was actually done that they all commit into. Adopting it doesn't fork your stack — it references the others' evidence by digest. How it composes → · what's worth sealing →
Independently-verifiable records, joined by a shared action digest.
An accountable record often needs to answer more than one question — was the action permitted, which human authorized it, what the agent actually did, did the runtime enforce correctly. The Agent Action Capsule answers what it did. It composes with records that answer the others: each is produced and verified on its own, and they join by reference to a shared digest over the action — the join key every record refers to.
| Slot | Answers | Filled by |
|---|---|---|
| CAN — Authorization e.g. OAuth/AAuth, GNAP, policy | was the agent permitted to act? | an authorization record |
| WHO — Named-human authorization e.g. a device-bound authorization receipt | which accountable human authorized this exact action, before it ran? | an offline-verifiable authorization receipt |
| WHAT — Agent Action Capsule | what did the agent actually do? (verdict-complete, byte-stable) | the Agent Action Capsule |
| AUDIT — Runtime gate e.g. a policy gateway, observability log | did the runtime enforce correctly, in causal order, tamper-evidently? | a gateway or observability record |
Any conforming record may fill a slot; the set is open by design. Each slot may root in a different trust anchor, and the join holds even if one party is compromised or under review — no slot is a required root of trust for another. Digest equality is a join key, not proof of truth, authorization, or sufficiency: each record's native verification, digest recomputation, and receipt verification stay separate results that a verifier must never collapse into one boolean. How it composes with your stack →
The binding underneath: CPB
For records to join on the same digest, they need one shared way to compute it. That is the Canonical Payload Binding (CPB) — a small companion IETF draft that defines how a payload binds to a SCITT receipt and how a payload class declares and resolves its canonical form. Each payload class declares its canonicalization and exclusion set once, in an open registry, and inherits receipt binding and typed digest reference without restating the mechanics. The Agent Action Capsule is CPB's first registered payload class.
CPB — the spec, why it helps, and the registry →
CPB spec: draft-mih-sokolov-scitt-payload-binding ↗ · Registry: payload-class registry of record ↗
From the bytes. Offline. Trust the log's key — not the operator.
This is what an auditor runs against a ledger of capsules. Tamper any field and ok turns false.
# install the reference verifier pip install agent-action-capsule # verify a ledger of sealed actions, offline agent-action-capsule verify --store ledger.jsonl capsule_id 9f2a…c14 ok capsule_id 4b07…8de ok # inclusion on the public log: substrate.receipt_verified: True
Inputs & outputs committed by digest
The capsule seals SHA-256 digests of what went in and came out. Raw values stay local; the proof travels.
Signature + inclusion, independently
The signature proves who sealed it; the receipt proves the log included it. Both check from the bytes.
VDS-agnostic
The same statement verifies whether the log uses RFC 9162 Merkle proofs or Microsoft CCF. The action layer never changes.
One config change per rung — start in ten minutes, scale as you need.
Structured records, offline verify
Set CAPSULE_ANCHOR=false. Structured records, local ledger file, offline verification. Zero services. The ten-minute first touch — no network, no account.
Page renders: self-attested / not witnessed
Real receipts, your trust domain
Deploy your own capsule-anchor instance. Real inclusion receipts within your org — tamper-evident across teams, honest internal separation of duties.
Policy descriptor tier: self-operated
Third-party verifiable
One config change: point at the public witness. Records become third-party-verifiable; permalinks are shareable. No signup, no key, no cost.
Policy descriptor tier: public
Full adoption guide: ADOPT.md ↗
Only a hash leaves. Witness anywhere — including your own VPC.
A capsule is content-private by construction. When you witness it, the only thing that travels to the log is a digest and a timestamp — never prompts, payloads, reasoning, or PII. The raw content stays under your control.
Zero-setup proofs
Witness at the shared, open log at anchor.agentactioncapsule.org. A digest + timestamp leaves; your data never does.
Residency control
Run the open witness log in the region or jurisdiction you need (e.g. EU, Singapore). The hash stays in your jurisdiction.
Nothing leaves
Self-host the witness (capsule-anchor) container inside your own environment — then even the hash never leaves your walls.
The capsule is witness-agnostic, so you can move or mix witnesses without changing the record. One caveat: a digest only hides values that aren't guessable — for low-entropy fields (a short amount, a known ID), salt before hashing. What a digest hides →
Tested against other implementations — not just our own.
The statement layer is fixed; the verifiable-data-structure is the log's choice. We've proven that holds across vendors.
Shared test vectors
Our RFC9162_SHA256 cross-implementation vectors were contributed to, and merged into, the SCITT working group's examples repository — a reference anyone can verify against. It's a merged contribution, not a WG endorsement of this profile.
ietf-wg-scitt/examples ↗Two-party, two logs
One capsule, registered to our RFC9162 log and a real Microsoft CCF node — both receipts verify under our verifier stack. (CCF uses vds=2; RFC 9162 uses vds=1.) Tested against CCF; not a Microsoft endorsement.
scitt-cose ↗Implementation report
We intend to bring an implementation report and the shared test vectors to the SCITT working group at IETF 126 (Vienna) — connecting the verifier, the vectors, and the plug-fest.
AAC: draft-mih-scitt-agent-action-capsule-04 ↗ · CPB: draft-mih-sokolov-scitt-payload-binding-02 ↗Every layer is open source.
Read it, run it, fork it. The tooling is Apache-2.0; the specification follows the IETF Trust's terms (BCP 78/79, with code components under the Revised BSD License). Built to be donated to a neutral home, not owned.
Scope. The open project is the record layer — the profile, the producer (with example constraint manifests), the verifier, and the witness log. Acting on those constraints at runtime (enforcement) is a separate concern you compose with a policy gateway: the capsule records what happened, it doesn't gate. How the project is governed →
Built by an agent developer who wanted proof, not promises.
The Agent Action Capsule was created by Steven Mih — a startup founder and agent developer with a long background in open source, including helping steward openly and neutrally governed software (the Presto Foundation, under the Linux Foundation). He built it after hitting the wall everyone building agents hits: once an agent takes a real action, the only "proof" it happened as intended is the operator's own word. The capsule is the answer — a verifiable record anyone can check, built to be owned by no one.
Why build it this way? Verifiable records of what agents do are infrastructure the whole ecosystem depends on — and we think AI safety and open standards matter far too much for that layer to be controlled by any single company. So the design goal from day one is to give it away.
Where it stands today. The project is stewarded by Action State Group, which also operates the reference services (the public log and the verifier) for now — with the explicit intent to donate the profile, the trademark, and the services to a neutral foundation as the ecosystem matures. The governance model is public and modeled on Linux Foundation practice, and co-maintainers are welcome to join. Read the governance model → · comments on the draft are welcome at spec@actionstate.ai and in the IETF SCITT working group.
Mint your own capsule — in under 60 seconds.
One button. No signup. No install. Your agent action sealed client-side, witnessed by the public log, and handed back as a shareable permalink anyone can verify.
Playground launching soon — see the quickstart to seal your first capsule now.
An open profile to shape together — not another silo to fork.
The capsule is open and built to be donated. The useful move is to improve one shared profile together — feedback, competing ideas, and adapters all welcome. Ways in:
Seal your agent's actions
Wrap a tool with one decorator, witness each call, and verify from the bytes.
Quickstart → Adopters — start here ↗Add an adapter
Bring your framework's seam onto the shared base, or open a request — so producers stay one format.
capsule-emit ↗Help the standard
The profile is an individual IETF Internet-Draft. Review it, bring test vectors, and engage in SCITT.
Read the draft ↗Who's already using it.
New here? Read how the project is governed → · Join the conversation on GitHub.