Relationships
#4154 Agent sessions: define the versioned session data contract and how the dashboard finds it
Opened by skunk-ape · 10/30/2026· Shipped 10/30/2026
Part of agent observation (scope doc: https://claude.ai/artifact/NdQUomjuVAfo4SsPuRWYWk; harness survey #4117, OTEL research #4118). Agent sessions show what a coding agent did in a swamp repo: its turns, its tool calls, and whether each call used swamp, went around it (a bypass), or neither, with findings that say what to tune.
How it ships. The data comes from the harnesses' own local session files (Claude Code transcripts, Codex rollouts), which need no hooks or setup. An unpublished extension imports them as ordinary repo data. A core dashboard page shows them, hidden unless the repo has session data the viewer can read, with a Preview chip. No flag: until the extension is published, nobody else gets data, so nobody sees the page.
Reference prototype (local, private, not for sharing): ~/scratch/agent-sessions-prototype/ on Seth's machine. See its README.
Goal
Define the data contract between the agent-sessions extension, which writes session data, and the dashboard page, which reads it. Both #4155 and the extension issues build on this one.
Scope
- Session schema, versioned from day one. Start from the prototype's
sessions.json:- session: id, repo, harness, harness version, model, start time;
- turns: number, start, end, tokens (input, output, cache read, cache write);
- calls: id, tool, start, end, ok, the redacted command text, label (swamp / bypass / neutral), category, and the rule that decided the label;
- findings: severity, text, the calls each one points at;
- swamp span roots per call, where known. Prompts and replies are never part of the schema.
- Where it lives. One data item per session, with a tag or type the page can find. Decide whether the schema is exported for extension authors (as a type or JSON schema) or documented only.
- How the page finds it. Check whether the dashboard's existing data query can list items by that tag, under the viewer's read access. Add a filter only if it can't.
- Version handling. What the page does with a schema version it doesn't know: skip the session with a note, or ask for a re-import.
- Sync default. Session data written to
data/syncs to a shared datastore by default (DEFAULT_DATASTORE_SUBDIRSinsrc/domain/datastore/datastore_config.ts). Decide whether that's acceptable while the extension is unpublished, and record the decision for later.
Volume (measured 2026-10-29)
One heavy user's October: 9,028 top-level Claude Code sessions (most from automation such as claude -p in verify workflows; median 1 call, p90 9, max 1,089) plus subagent transcripts, 70.8k tool calls, 2.8 GB of raw transcript. Converted, a call is about 0.9–1.4 KB, mostly command text: 25 KB for a small session, 230 KB for a 169-call one, about 1.5 MB for the largest. A typical interactive user in one repo is a few hundred sessions and a few MB a month.
Subagents keep full detail. The point is to see what agents and subagents do, so subagent calls are stored and shown call by call like the parent's, never summarised away or hidden by default.
Designing for that volume
- Summary and detail per session. The catalog indexes metadata and tags but not content (
design/enablers/data-query.md, Catalog). Keep what the sessions table needs (repo, harness, start, length, turns, calls, label counts, failed calls, tokens, flags, subagent count, headless or interactive) in tags or a small summary item, and the turns and calls in a detail item loaded only when a session is opened. Listing sessions and the "is there any data" check then never read content. - Subagents in the schema. A subagent is a child session with its own turns and calls at full detail, linked to its parent session and to the call that started it. Decide whether it lives inside the parent's detail item or as its own detail item linked from it; either way the summary counts its calls, and the classifier and findings run over them.
- One version per session. Data is immutable and versioned, so re-imports add versions. Use
garbageCollection: 1for session data. - A lifetime, for example 90 days, configurable, so storage is bounded. Long-range trends (before/after) come from small daily rollups the extension writes; rollups are for trends only and never replace session or subagent detail inside the lifetime.
- A text cap on stored command text (for example 2 KB, with a
truncatedflag). Heredoc writes otherwise carry whole files. - The sync-default decision above matters more at these numbers: thousands of small files per month are slow to sync to S3.
Out of scope
The page itself, the extension, live capture through hooks, joining spans to exact calls.
Shipped
Click a lifecycle step above to view its details.
Sign in to post a ripple.