Skip to main content

Attestations

Attestations are graph-level audit nodes that summarize an AI agent session โ€” cost, token usage, model breakdown, code change statistics, and which changes are covered. They are created automatically when a session ends and travel with the changes they cover on push.

What Is an Attestation?โ€‹

When an agent session ends (the user closes the conversation, or the session is deleted), Atomic creates an attestation covering all the changes recorded during that session. The attestation aggregates data from the provenance entries embedded in each covered change:

Session: agent-ses_3781fc7a6ffet5c6r1ILy1BEbv
โ”‚
โ”œโ”€โ”€ Turn 1: Change ABC123 (provenance: claude-sonnet-4-5, 3.2k tokens, $0.04)
โ”œโ”€โ”€ Turn 2: Change DEF456 (provenance: claude-sonnet-4-5, 5.1k tokens, $0.06)
โ””โ”€โ”€ Turn 3: Change GHI789 (provenance: claude-sonnet-4-5, 4.1k tokens, $0.05)
โ”‚
โ–ผ
Attestation XMJZ3IPF
โ”œโ”€โ”€ Agent: OpenCode (anthropic)
โ”œโ”€โ”€ Session: agent-ses_3781fc...
โ”œโ”€โ”€ Models: claude-sonnet-4-5 (12.4k tokens, $0.15)
โ”œโ”€โ”€ Code: +116 lines, -8 lines
โ”œโ”€โ”€ Wall time: 3m 42s
โ””โ”€โ”€ Changes covered: ABC123, DEF456, GHI789

Viewing Attestationsโ€‹

List All Attestationsโ€‹

$ atomic agent attest

XMJZ3IPF OpenCode ยท claude-sonnet-4-5 ยท 12.4k tokens ยท 3m 42s ยท 3 changes
R3KQP7YN Claude Code ยท claude-sonnet-4-5 ยท 8.1k tokens ยท 1m 15s ยท 1 change

โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
Total: $0.27 ยท 4 changes covered ยท 20.5k tokens

Inspect a Specific Attestationโ€‹

$ atomic agent attest --hash XMJZ3IPF

Attestation XMJZ3IPF

Agent: OpenCode
Session: agent-ses_3781fc7a6ffet5c6r1ILy1BEbv
Changes: 3 changes
Wall time: 3m 42s
Cost: $0.15
Tokens: 12.4k
Code: +116 -8

Model Breakdown:
claude-sonnet-4-5: 3.2k in / 9.2k out ยท $0.15

Changes Covered (3):
ABC12345
DEF45678
GHI78901

Coverage:
dev โ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–ˆโ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘โ–‘ 3/5 (60%)

Filter by Stackโ€‹

$ atomic agent attest --stack dev

Verbose Outputโ€‹

$ atomic agent attest --verbose

Shows per-model token breakdown and per-change details for every attestation.

How Attestations Are Createdโ€‹

Automatic Creation at Session Endโ€‹

When the TurnOrchestrator receives a session-end event and the session had at least one turn:

  1. Query the agent stack history โ€” get all change hashes on the agent's stack
  2. Check for existing attestations โ€” find which changes are already covered by prior attestations from the same session (for resumed sessions)
  3. Determine new changes โ€” filter to changes not yet attested
  4. Load each change โ€” read provenance entries (model, tokens, cost) and file operations (lines added/removed)
  5. Aggregate data:
    • Per-model token and cost totals
    • Total lines added and removed from the CRDT semantic layer
    • Wall duration from session timestamps
  6. Build and save โ€” create the attestation with all aggregated data

Data Sourcesโ€‹

The attestation pulls data from two places:

DataSourceHow It Gets There
Model namechange.provenance[].modelSet by build_turn_provenance() at record time
Token countschange.provenance[].tokensSet by build_turn_provenance() at record time
Costchange.provenance[].costSet by build_turn_provenance() at record time
Lines added/removedchange.file_ops[].line_ops[]Generated by the CRDT semantic layer during recording
Wall durationsession.started_at / session.ended_atTracked by the TurnOrchestrator
Agent identitysession.agent_name / session.agent_vendorSet from hook events (OpenCode sends provider/model)

Fallback Behaviorโ€‹

If no provenance data is found in the changes (e.g., changes recorded without the agent hooks), but the session knows the model name, the attestation still creates a minimal model entry. This ensures the attestation always names the model, even when token/cost data is unavailable.

Resumed Sessionsโ€‹

When an agent session is resumed (e.g., claude --resume or continuing an OpenCode session), the attestation system handles it correctly:

  1. Finds existing attestations for this session ID
  2. Determines which changes are new (not yet covered)
  3. Creates a new attestation covering only the new changes
  4. Chains to the previous attestation via the previous_attestation field
$ atomic agent attest --hash R3KQP7YN

Attestation R3KQP7YN

Agent: Claude Code
Previous: XMJZ3IPF # โ† chains to the prior attestation
Notes: Resumed session (1 new change, 4 total in session)
...

This ensures every change is covered by exactly one attestation, with a clear chain showing the session's history.

On-Demand Generationโ€‹

The server API also supports generating attestations on demand from the provenance data in changes:

POST /tenant/:id/portfolio/:id/project/:id/attestations/generate

This reads the provenance entries from every change on a stack, aggregates them, and creates an attestation. This is useful when:

  • Changes were pushed before the attestation was created locally
  • You want to regenerate an attestation with updated data
  • The local attestation was lost or corrupted

Storage and Transportโ€‹

On Diskโ€‹

Attestations are stored in the same two-level directory structure as changes:

.atomic/changes/
โ”œโ”€โ”€ AB/
โ”‚ โ”œโ”€โ”€ ABCDEF1234567890.change # A change
โ”‚ โ””โ”€โ”€ ABCDEF1234567890.attest # An attestation
โ””โ”€โ”€ XM/
โ””โ”€โ”€ XMJZ3IPF...........attest # Another attestation

Content Addressingโ€‹

Like all Atomic artifacts, attestations are content-addressed:

data = postcard::serialize(attestation)
hash = blake3(MAGIC_BYTES + data)
path = .atomic/changes/{hash[0:2]}/{hash}.attest

Pushโ€‹

When you push changes, Atomic automatically uploads attestations that cover the pushed changes:

$ atomic push origin

โœ“ Pushed 3 changes
โœ“ XMJZ3IPF attestation ($0.15, 3 covered)

An attestation is only uploaded when all of its covered changes have been pushed. This ensures the server never has an attestation referencing changes it doesn't have.

Data Modelโ€‹

Attestationโ€‹

FieldTypeDescription
versionu8Schema version for forward compatibility
timestampi64Unix epoch seconds when created
agentAttestAgentAgent identity (name, display name, vendor)
session_idStringSession this attestation covers
cost_usdf64Total cost across all models
duration_api_msu64API processing time
duration_wall_msu64Wall clock duration of the session
code_changesCodeChangeStatsLines added and removed
modelsVec<ModelUsage>Per-model token and cost breakdown
changes_coveredVec<Hash>Hashes of changes this attestation covers
previous_attestationOption<Hash>For resumed sessions โ€” chains to prior attestation
notesOption<String>Human-readable context

ModelUsageโ€‹

FieldTypeDescription
modelStringModel identifier (e.g., claude-sonnet-4-5)
input_tokensu64Prompt/input tokens
output_tokensu64Completion/output tokens
cache_read_tokensu64Tokens read from cache
cache_write_tokensu64Tokens written to cache
cost_usdf64Cost for this model's usage

CodeChangeStatsโ€‹

FieldTypeDescription
lines_addedu64Total lines added across all covered changes
lines_removedu64Total lines removed across all covered changes

Web UIโ€‹

The Atomic web UI renders attestations on the Attestations tab of each project. The display includes:

  • Summary card โ€” Agent name, cost, tokens, duration, change count, lines changed
  • Models Used โ€” Per-model breakdown with token counts and cost
  • Provenance Graphs โ€” Interactive visualization of the session's decision DAG (from the provenance graphs associated with covered changes)
  • Timeline โ€” Temporal view of the session's activity

See Alsoโ€‹