Skip to main content

AI Agent Session Audit Trails: Cost, Tokens, and Model Attribution

Atomic session attestations summarize which changes an AI coding session recorded, which model metadata was reported, and—when the integration supplies usage—its tokens and cost. When Atomic receives a supported session-end event, it attempts to create this audit node for sessions that recorded at least one change, and the attestation travels with its covered changes on push.

Content addressing makes an attestation tamper-evident under its hash; it does not authenticate the model provider or the origin of hook-reported metadata. Treat agent and model fields as captured attribution unless a separate signed artifact establishes a stronger claim.

What Is an Attestation?​

When a supported agent session ends, Atomic attempts to create an attestation covering the changes that session actually recorded. The attestation aggregates data from the provenance entries embedded in each covered change:

Session: agent-ses_3781fc7a6ffet5c6r1ILy1BEbv
│
├── Turn 1: Change ABCD23EF (provenance: claude-sonnet-4-5, 3.2k tokens, $0.04)
├── Turn 2: Change DEFG45HJ (provenance: claude-sonnet-4-5, 5.1k tokens, $0.06)
└── Turn 3: Change JKLM67NP (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: ABCD23EF, DEFG45HJ, JKLM67NP

Viewing Attestations​

Inspect One Change's Embedded Provenance​

atomic change <change-hash>

The default change view renders the first embedded provenance entry as === Attestation ===, with that change's provider, model, tool, suggestion type, available tokens and cost, session identifier, and turn metadata. It also includes === Change Ledger === with the observed goals, tools, edits, decisions, and verification associated with the change.

Despite its display heading, this inline block is embedded provenance attached to one change. atomic agent attest lists and inspects separate session-level attestation artifacts that can aggregate several covered changes.

List All Session 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 Session 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):
ABCD23EF
DEFG45HJ
JKLM67NP

Coverage:
dev ████████████░░░░░░░░ 3/5 (60%)

Filter by View​

$ atomic agent attest --view 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 recorded at least one change:

  1. Read the session's recorded changes — use the change hashes recorded by this session, excluding inherited parent-view history
  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 attributionsession.agent_name / session.agent_vendorCaptured from hook events (OpenCode sends provider/model)

Fallback Behavior​

If no provenance usage data is found in the changes but the session payload includes a model name, the attestation creates a minimal model entry. Token and cost fields can remain unavailable when the integration does not report them.

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)
...

Automatic resumed-session generation avoids covering the same change twice within that session chain, while the previous_attestation link preserves the session's segmented 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 view, 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/{change-hash[0:2]}/{full-change-hash}.change
.atomic/changes/{attestation-hash[0:2]}/{full-attestation-hash}.attest

Content Addressing​

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
agentAttestAgentHook-reported agent attribution (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​