Open record format

What was this agent allowed to do?

ACTION-v1 is the record that answers it. A declared tool action is checked against policy before it runs, and the outcome is signed either way. A refusal is a record in its own right.

The problem

A log describes what happened after it happened, and it is written by the system that produced it. That was tolerable when an AI produced text. It stops being tolerable when an agent selects tools and changes something outside itself: deploys code, moves money, opens a door, writes to a record system.

The question a reviewer asks months later is not whether the model was clever. It is what the agent was permitted to do, who decided, and whether anyone outside the operator can check that now.

The record

Thirteen fields and not a number among them, so the whole class of cross-language number formatting disagreement cannot arise. The arguments are hashed rather than carried, so a record holds no prompt, no customer data and no case detail.

Entry 001 · production refusalBLOCKED
v"action-1"the profile, chosen explicitly
action_id"05e9c6e2-ef87-49aa…"this decision
org_id"8bfc5d74-bc36-43b7…"whose boundary
session_id"demo-mcp-1787431402"the agent session
intent_hash"27b603d4a361df01…"the instruction it was bound to
agent"mcp-client"claimed by the caller, never verified
tool"git.push_production"the action it declared
args_hash"44136fa355b3678a…"arguments hashed, never carried
outcome"BLOCKED"refused before anything ran
policy_applied["policy_demo_no_prod_push", …]what was evaluated
timestamp"2026-08-22T20:43:25Z"when
public_key"9Y3Eiq6V8QjRDUM5…"the key that signed it
signature"vjqoIEKioLfnATGe…"over the canonical bytes of the rest

The full specification is normative, including the field-by-field statement of which claims the issuer attests and which it merely records.

What an action record proves, and where it stops

It proves

  • The holder of the published key evaluated these policies over exactly this declared action
  • The outcome that was reached, and when
  • That the session was bound to an intent that could not be changed once set
  • That not one signed field has moved since

It does not prove

  • That the action was correct, wise or safe. The record is about permission, not judgement
  • Who the agent was. That identity is supplied by the caller and recorded, never verified
  • What the caller then executed, unless the boundary performed the action itself. A refusal has no such gap, because nothing ran
  • That every action was recorded. Proving none was left out is an open problem and we treat it as one

Verifying one

Two independent implementations, TypeScript and Python, agree on every published conformance vector, and a cross-implementation sweep re-checks that agreement on every change rather than at release. In August it caught a canonicalisation divergence in our own browser checker, fixed the same day and documented in public. Selecting the format is explicit, never guessed from the shape of the fields.

curl -sL https://app.aqta.ai/samples/sample-action.json -o record.json
npx aqta-verify-receipt record.json --profile action-1 --key <published key>

That sample is a real record from the production gateway: an agent proposed git.push_production, and policy refused it before anything ran. It is entry 001 of the Refusal Ledger, a public ledger of real refusals, each one verifiable the same way. The key comes from the published key endpoint, pinned once. Change one character of the file and the signature fails. Every record the format defines is also published as conformance vectors, valid and deliberately broken, so you can check the checker.

Where it sits

Agents increasingly act through the Model Context Protocol and similar tool interfaces, which settle how an agent reaches a tool. ACTION-v1 is the evidence at that boundary. Authorisation decides whether the action happens; the record decides who can prove it afterwards.

It is a sibling of ATTESTATION-v1, which records what an AI decided on a model call. Same key, same reference verifiers, same offline check. The in-browser checker reads both: pick the agent-action sample there, or use the command above.

The physical boundary

The same record governs a machine command. In the edge signer, a tool is a command to a controller, the arguments are the setpoint, and the outcome is signed at the cell before the command moves. A demonstrator press cell runs the real policy engine and the real signer end to end: a press cycle needs a grant signed by the plant's designated approver, a grant the scheduler signs for itself is refused by name, and power is released only through a single-use permit that fails closed. Only the load is simulated.

What that does not yet do, stated before anyone has to find it: nothing physically refuses to energise. The interlock runs in the same process it guards, so it proves a decision was made; it does not yet make acting without one impossible. The designed assembly sources the enable line from a secure element, so a compromised controller cannot close it. That step is laboratory work, and it is the interesting part. Regulation (EU) 2023/1230 on machinery, which applies from 20 January 2027, asks that safety software with self-evolving behaviour record its safety-related decision process and retain it for a year. It does not ask for cryptographic evidence, and we do not claim it does; it names the record this format already produces.