Guarded Automation: Agents That Run Operations Module 5 · The Record of Every Action

The Receipt Query

Last reviewed · content updated

Intermediate

What you'll learn

~14 min
  • Query a verified receipt chain by agent, action, and time window, and explain why the chain must be verified first
  • Produce Timeline and Decisions rows that paste into an incident record's own column shape, with action_receipt_id stored as a searchable string
  • Name what a vendor's published agent-action audit schema does not capture, next to this training's own receipt fields

Before the detail — Decision: answer “what did this agent attempt, and when” from a receipt chain that has already been verified, never from a log nobody has checked. Outcome: rows an incident commander can paste straight into the record instead of reconstructing from memory or a raw file. Artifact: a receipt query tool’s timeline and decision output, already shaped to the incident record’s own columns. Status of what follows: reusable guidance, built on 1.4’s receipt schema and 5.1’s verifier.

Prompt first: verify, then ask

Before trusting any answer to "what did the agent do last Tuesday,"
verify the log, then query it. Given a receipts log and a chain
verifier for it, write:
1. the exact command that confirms the chain is intact, with an
anchor if one exists
2. a query for one named agent's actions in a given time window
3. a query that returns only the rows where the guard actually made
a call - a denial, a compensation, a halt - in the shape: time /
decision / what was known / what was assumed / who decided
Do not run #2 or #3 until #1 has printed clean. If #1 fails, the next
step is finding out why the chain does not verify, not querying it
anyway.

The training’s own query tool states the reason in its own header: nothing in it verifies the chain — run the verifier first, because a query over an unverified log is a query over a story. The prompt orders the steps to make that a habit, not a caveat someone reads once and forgets under pressure.

Verify first, then ask what happened

5.1 owns the verifier and the anchor; this lesson assumes a chain that has already passed both, and asks the next question. Run against MU-AI-011’s nine-call storm-night chain, a stats query returns ten of ten rows, broken down by outcome — denied=4 verified=3 compensated=1 restored=1 KILLED=1 — by action, and by decision — allow=3 ask=1 compensation=1 deny=4 halted=1. That is a shape an incident commander can read in seconds instead of scrolling ten raw log lines one at a time.

Skipping straight to a query without checking the chain first is not a shortcut; it is a guess wearing a command’s output as a costume, and it is the same assessor-hours spent twice — once to answer the question, again later to find out the answer could not be trusted.

Timeline rows paste into the record unchanged

The query tool’s --timeline option emits rows in exactly the column shape of section 3, Timeline, of the incident-record template in Operating in Production (a separate training in this series) — Time (UTC) / Who / What happened or was decided — so an agent’s own actions paste into a human incident record instead of being summarized into it by whoever is holding the pen during a live event. One real row from the storm-night run:

| 2026-09-14T19:42:00Z | mu-ai-011 | `pre_position_crew` {"crews":14,"feeder_id":"F-2291"} - REFUSED by the envelope: 'crews'=14 exceeds the envelope maximum 3<br>`action_receipt_id=AR-EF7DF8B481D7; agent_id=mu-ai-011; autonomy=L1-approval-required; class=compensable; seq=3; row_hash=99e27f6c131a7522; ...

The tool emits that as one line, and the <br> is deliberate: it is what makes the evidence break onto its own line once the row is pasted into a markdown record, instead of running into the description. The row is shown trimmed at row_hash here; the real one continues with the pre-state and post-state hashes.

Everything after action_receipt_id= in that cell is the same identifier 1.4’s receipt schema already carries — this lesson does not re-derive that schema, it quotes it. Operating in Production 1.4 keeps to the same discipline for its own two cross-record identifiers, trace_id and release_record_id: it stores ids, no join — the record holds the key, and whatever owns the other side of it resolves the key on its own terms. The same rule applies here. These rows paste; they do not reach into a second database to reconcile anything, and action_receipt_id is nothing more than a string a later reader can search for.

Decisions are a narrower cut, and they say what was assumed

The --decisions option only emits a row where the guard actually made a call — a denial, a compensation, a halt. A row that simply verified is timeline material, not a decision under uncertainty, because nobody decided anything by letting a correct action through. The command emits seven rows in this run: four denials, the failed action, its inverse receipt, and the halt. Every row’s “what was assumed” column reads the same way: nothing — the bound was read from the envelope, not inferred from the request. That is not filler text; it is the exact fact a reviewer is checking for, and it never changes from row to row because the guard never guesses a limit it was not handed.

What a vendor’s own receipt schema still leaves out

Azure SRE Agent publishes nine customEvents, including AgentToolExecution and ApprovalDecision; IncidentActivitySnapshot carries AgentAutonomyLevel. Set next to 1.4’s receipt, it lacks pre-state, post-state, approver identity, tamper evidence, and a stated retention rule, while log custody remains a deployment question. A published schema that records what happened without also proving the log was not the agent’s own homework is missing exactly the property this training builds first.

One hedge, stated once: OpenTelemetry’s execute_tool and invoke_agent spans now live in the moved semantic-conventions-genai repository, which carries zero releases, and all remain at Development stability — vocabulary worth watching, not yet a receipt-store schema.

Buying a product whose own audit trail cannot show pre-state, post-state, or who approved what is buying evidence that will not survive being contested — a contract question worth asking before the incident, not during it.

Stop and escalate when a timeline or decisions query is run against a chain the verifier has not passed this shift, or when a request comes in to add a field to the receipt schema that no available product actually populates — the first is a process fix, verify then query; the second is a purchasing conversation with whoever owns the gateway budget, not a workaround written into the query tool.

KNOWLEDGE CHECK

An incident commander wants to paste 'what the agent did between 19:40 and 19:48' straight into section 3 of the incident record. The receipt chain has not been verified yet this shift. What is the right order of operations?

Key takeaway

A receipt query is only as trustworthy as the chain it reads, which is why 5.1’s verifier runs first, every time. Timeline and decisions queries turn that verified chain into rows in the incident record’s own shape, keyed by action_receipt_id under the same stores-ids discipline Operating in Production 1.4 already applies to its own cross-record keys. What a vendor’s own published schema still leaves out is exactly what 1.4 built in from the start: pre-state, post-state, and an identity behind every approval. 5.3 reads five other organizations’ agent-action incidents in their own words, and names which lesson in this training would have caught each one.

LEADERSHIP DECISION no incident record cites an agent's actions
from a receipt chain that has not been run
through the verifier that shift
PRACTITIONER ACTION query only a verified chain, paste timeline
and decisions rows in unchanged, and name a
missing pre-state or approver field in a
vendor product as a gap rather than guess it
SUCCESS MEASURE every agent-drafted row in an incident record
traceable to a verified action_receipt_id -
an audit finding avoided
Search lessons