Skip to content

AI agents · What a run leaves behind · Slide and type to change it

Traces, checkpoints and receipts

When an agent run ends, or breaks, three different records answer three different questions. A trace says what happened. A checkpoint says where to pick up. A receipt says that a named check passed on exactly this content. Slide a run along, then edit a file and watch a receipt go stale.

Three records, three questions

People say log for all of it, and that hides what each record is for. A trace is the story: what happened, in what order, how long it took, what failed. A checkpoint is a save point: enough state to carry on from, so a broken run does not start again. A receipt is a claim you can check: this named check passed, on exactly this content. The first looks back, the second looks forward, and the third is only worth anything while it still matches.

Below is one invented run. Slide to where it stops and see what each record would tell you.

6 of 9: run_check no-todo

Files now, as one digest: 19168467b572

Trace

What happened, in order.

invoke_agent builder root span, never ended

  1. 1. read_file notes.md 40 ms ✓ ok
  2. 2. edit_file parse.ts 60 ms ✓ ok
  3. 3. run_check no-todo 220 ms ✓ ok
  4. 4. run_check non-empty 90 ms ✓ ok
  5. 5. edit_file format.ts 70 ms ✓ ok
  6. 6. run_check no-todo 3000 ms ✕ error: timed out

Checkpoint

Where to pick up.

Written after step 4, when every check the run needs was current. It holds the files as digest f828c18d044d.

Resume from there and repeat 2 steps:

  • 5. edit_file format.ts
  • 6. run_check no-todo

Receipts

Which checks are proved for the files now.

  • no-todo ✕ Stale

    Issued at step 3 for digest f828c18d044d. The files have changed since.

  • non-empty ✕ Stale

    Issued at step 4 for digest f828c18d044d. The files have changed since.

Step 6 failed with a timeout, which is not a failed check, so it issued nothing.

Invented runFigure 1. One invented run of nine steps. Slide to where it stops: the trace is everything up to there, the checkpoint is the last save point, and each receipt is current only if it was issued for the files as they are now.

A trace: what happened

The vocabulary most tools share comes from OpenTelemetry: a trace is the path of one request, made of spans; a span is one unit of work, with its own id and a parent, a start and an end, key-value attributes, timed events inside it, and a status of unset, error or ok [OpenTelemetry: traces]. A run is a natural fit: the agent’s run is the root span, and each model call, tool call and check is a child.

OpenTelemetry’s conventions for agents name an invoke_agent span and attach to it the agent’s name and id, the model and a conversation id where known, and an error type when the operation fails [OpenTelemetry: GenAI spans (development)]. Those conventions are marked as in development, so treat the names as likely to move. They also mark the prompts and replies themselves as opt-in, because they are likely to hold sensitive data [OpenTelemetry: GenAI spans (development)].

Traces are also how failures get studied. The MAST study of why multi-agent systems fail is built on over 1,600 annotated execution traces [Cemri et al. (MAST, preprint)]. A run you cannot replay in your head from its trace is a run you cannot learn from.

A checkpoint: where to resume

A checkpoint is state, not history. LangGraph’s documentation describes a checkpointer saving snapshots of a graph’s state for each thread, so a run can resume after an interruption or recover from a failure [LangGraph: persistence (vendor)]. Anthropic’s write-up on long-running agents does the same with plainer tools: a progress file and git commits, so that a fresh session can read them and pick up [Anthropic 2025 (vendor)].

The word is used for two things. Anthropic’s guide to building agents also says an agent can pause for human feedback at checkpoints [Anthropic 2024 (vendor)]: there a checkpoint is a place to ask, not a place to save. In the figure, a checkpoint is a save point, written when every check the run needs is current, so resuming never starts from work nobody has verified.

A receipt: proof for this content

A green tick is only a claim until it says what it is a tick for. A receipt names the check and holds a digest of the content it passed on. Supply-chain attestations work the same way: an in-toto statement names its subjects by digest and says what is claimed about them [in-toto: Statement v1], so it can be matched to an artifact by its content and not by what it is called. A receipt here is the small version of that idea.

The consequence is the point of Figure 2: edit one file and the digest changes, so every receipt for the old content is stale at once, and only running the check again on the new content makes a new one. A check that fails issues no receipt at all.

e8241ecfb2c0
04d23fbea213
f1bad726cb64

The files together: digest 19168467b572. Try adding the word TODO to a file.

Receipts: 2 of 2 current

  • no-todo ✓ Current · No file contains the word TODO.

    Vouches for digest 19168467b572. The files are now 19168467b572.

  • non-empty ✓ Current · No file is empty.

    Vouches for digest 19168467b572. The files are now 19168467b572.

Try itFigure 2. Edit any file: its digest changes, and every receipt for the old content is stale. Run the checks and a receipt is issued again, but only for a check that passes. Put the text back exactly and the old receipts are current again, because the digest matches.

On my own sites the same rule gates shipping. A full verify run on the finished work leaves a receipt, and the ship step accepts it only if it matches the tree as it is now: an edit or a rebase makes it stale, and the run has to be done again. A commit that changes nothing does not.

What to record

For each span: its name, ids (trace, span, parent), start and end, status, and the attributes you will want when it goes wrong, such as the tool or model name, sizes, counts and the exit code. Put the decisions the run made inside it as events: the classification of a failure, a retry, the budget saying no. That is a suggestion for how to use the span model, not part of the standard.

For each checkpoint: the step it follows, a digest of the state, and where the state is. For each receipt: the check’s name, its result, the digest of the content, and when and by what it was issued. Leave out, unless you need them, the text of prompts, replies and tool results, which the OpenTelemetry conventions treat as opt-in for the reason above [OpenTelemetry: GenAI spans (development)], and anything you would not put in any other log.

My view

What to take with a pinch of salt

  • The run, the files and the timings are invented. Nothing here records a real agent.
  • The digests are real SHA-256, shortened on screen. A real receipt keeps the whole digest and is signed or stored where the run cannot rewrite it; the figure does neither.
  • The figure keeps a digest per file only to tell you which file changed. A receipt itself needs just the one digest.
  • The checkpoint rule (written when every needed check is current) is one design, not a standard. LangGraph and Anthropic checkpoint differently.
  • I could not find a standard for agent receipts. The in-toto statement is the nearest published idea I found, and it is for software supply chains.

Sources

  • OpenTelemetry: traces · OpenTelemetry documentation, "Traces": a trace, its spans, and a span’s context, attributes, events and status. Read 2026-11-01
  • OpenTelemetry: GenAI spans (development) · OpenTelemetry semantic conventions v1.37.0, gen-ai-agent-spans.md: the invoke_agent span and its attributes; status "Development", so it may change; message content is opt-in because it is likely to be sensitive. Those conventions have since moved to their own repository. Read 2026-11-01
  • LangGraph: persistence (vendor) · LangChain documentation, "Persistence" (LangGraph; a vendor describing its own product): a checkpointer saves graph state snapshots per thread, so a run can resume after an interruption or recover from a failure. Read 2026-11-01
  • Anthropic 2025 (vendor) · J. Young, "Effective harnesses for long-running agents", Anthropic Engineering (2025-11-26; a vendor describing its own approach): a progress file and git commits so a fresh session can pick up where the last one stopped. Read 2026-11-01
  • Anthropic 2024 (vendor) · E. Schluntz and B. Zhang, "Building effective agents", Anthropic Engineering (2024-12-19; a vendor describing its own approach): an agent can pause for human feedback at checkpoints. Read 2026-11-01
  • in-toto: Statement v1 · in-toto Attestation Framework, Statement v1: an attestation names its subjects by digest and says what is claimed about them in a typed predicate. Read 2026-11-01
  • Cemri et al. (MAST, preprint) · M. Cemri et al., "Why Do Multi-Agent LLM Systems Fail?", arXiv:2503.13657 (preprint): 1,600+ annotated execution traces from 7 frameworks. Read 2026-11-01

Sources as read on 2026-11-01.