Tier 2 session memory: the run log you actually use
A schema for one-line-per-step JSONL run logs, a directory layout with an index, three small tools that turn the log into something you will actually open, and a what-to-log / what-not-to-log list.

Session memory is the black box. Every agent run is one file. If something went wrong, this is the file you open. If you want to know what the agent really did when it said it did X, this is the file you open.
If you do not have a per-run log, you do not have session memory. You have vibes.
The shape is the one the OpenTelemetry logs spec describes and the 12-Factor App endorses: one event per line, structured, with stable attribute keys. Google’s SRE book recommends this exact pattern as the only way to debug distributed/agent systems at all.
Where this comes from: Marvin’s 2026-07-20 original. Sources verified 2026-07-22 against the linked OpenTelemetry, Python, Google SRE, and 12-Factor pages.
The shape
One run = one JSONL file. One JSON object per line. One file per run.
{"ts":"2026-07-20T13:11:04Z","run_id":"7c2a","step":1,"kind":"model","model":"claude-sonnet-4","prompt_tokens":482,"completion_tokens":124,"cost_usd":0.0014,"latency_ms":1340,"summary":"decide which tool to call"}
{"ts":"2026-07-20T13:11:06Z","run_id":"7c2a","step":2,"kind":"tool","tool":"ocr.vision","input":"receipt.jpg","output_chars":312,"cost_usd":0.0008,"latency_ms":2100,"summary":"OCR receipt"}
{"ts":"2026-07-20T13:11:09Z","run_id":"7c2a","step":3,"kind":"tool","tool":"calendar.create","input":{"title":"Standup","when":"2026-07-21T15:00Z"},"output":"ok","cost_usd":0,"latency_ms":410}
{"ts":"2026-07-20T13:11:11Z","run_id":"7c2a","step":4,"kind":"error","tool":"email.send","error":"401 unauthorized","retry":true}
{"ts":"2026-07-20T13:11:14Z","run_id":"7c2a","step":5,"kind":"tool","tool":"email.send","output":"ok"}
{"ts":"2026-07-20T13:11:14Z","run_id":"7c2a","step":99,"kind":"end","total_steps":5,"total_cost_usd":0.0022,"status":"ok"}
This is enough. You can add fields. You cannot remove fields without losing the ability to debug later.
The directory layout
~/.hermes/runs/
index.jsonl # one row per run, fast to scan
2026-07-20/
7c2a-standup-scheduler.jsonl
9b41-etsy-listing-pack.jsonl
...
index.jsonl is the cheap fast index. Each entry is the last line of the run (the kind:"end" summary) plus the path.
{"run_id":"7c2a","ts":"2026-07-20T13:11:14Z","summary":"scheduled standup + sent reminder","status":"ok","cost_usd":0.0022,"path":"2026-07-20/7c2a-standup-scheduler.jsonl"}
Now you can answer “what did the agent do yesterday” with tail -n 50 index.jsonl | jq -r '.summary'.
The three tools that make a log useful
A log nobody reads is hoarding, not memory. Add three small tools.
1. run show <id>
Reads the file and pretty-prints the timeline. Every step, latency, cost, summary.
$ hermes run show 7c2a
13:11:04 model claude-sonnet-4 decide which tool to call 482+124 tok $0.0014 1.3s
13:11:06 tool ocr.vision OCR receipt 312 chars $0.0008 2.1s
13:11:09 tool calendar.create ok $0.0000 0.4s
13:11:11 tool email.send FAIL 401 unauthorized - -
13:11:14 tool email.send ok - -
13:11:14 end ok 5 steps $0.0022
2. run search <term>
Greps every log for a term. “When did the agent last touch pending-posts.json?” “Which run last called the email tool?“
$ hermes run search email.send
2026-07-20 7c2a ok
2026-07-19 ff01 error 401
2026-07-18 a3c4 ok
3. run cost --since=7d
Sums cost by day, by tool, by model. Tells you where the budget is going without opening a dashboard.
$ hermes run cost --since=7d
2026-07-14 $0.42
2026-07-15 $0.51
2026-07-16 $0.18
2026-07-17 $0.63
2026-07-18 $0.39
2026-07-19 $0.27
2026-07-20 $0.71 (so far)
What to log, what not to log
Log: ts, run_id, step, kind, model, tool, prompt_tokens, completion_tokens, latency_ms, cost_usd, summary, error.
Do not log: full prompts, full tool outputs, secrets, PII. Log a summary plus an id; keep the full payload in Tier 1 for the duration of the run, then drop it.
If a step is interesting enough to need the full payload later, promote it to Tier 3 (project memory) with a link. Otherwise let it die with the run.
Trade-offs (per tip)
| Tip | What it costs | What it saves |
|---|---|---|
| One file per run | Disk + index maintenance. | Locating the run that produced a given output, post-hoc. |
index.jsonl updated on every run end | One write per run. | Answers to “what did the agent do yesterday” in 1 second vs. minutes. |
| Three small CLI tools | ~50 lines of Python each. | Hours of log archaeology per failed run. |
| Log a summary, not full payloads | Slightly more work to write the summary. | Logs that fit on a 16 GB disk for 6+ months. |
| Prune run files older than 30 days | Loss of detailed old runs. | Disk that doesn’t fill up. |
Failure modes
- Logging the world. Every byte of every tool call ends up in the log. Logs explode. Search becomes useless. Fix: log a summary, store the full payload only for failed steps.
- Logging nothing. No run ids, no timestamps, no costs. When the agent breaks, you have nothing. Fix: at minimum, log one line per run with
start,end,total_cost_usd,status. - Logs without an index. 10,000 files, no way to find the one you need. Fix:
index.jsonlwritten on every run end. - Logs without retention. Six months of logs, 40 GB. Fix: keep
index.jsonlforever, prune run files older than 30 days unlessstatus != "ok".
What you will have at the end
- A schema for one-line-per-step JSONL run logs, compatible with the OpenTelemetry logs spec.
- A directory layout with
index.jsonl. - Three small tools that turn a log into something you will open.
- A list of what to log and what not to.
Where to get unstuck
- OpenTelemetry logs spec for the schema: docs.
- Python logging cookbook for the implementation side: docs.
- 12-Factor App — Logs for the design philosophy: 12factor.net/logs.
- Google SRE book — Monitoring Distributed Systems for the failure-mode patterns: sre.google/sre-book/monitoring-distributed-systems.
- OpenLLMetry for the per-call instrumentation library: GitHub.
Sources
- OpenTelemetry logs specification — used for: the JSONL schema and event attribute keys. Verified 2026-07-22.
- Python logging cookbook — used for: the structured-logging implementation side. Verified 2026-07-22.
- Google SRE book — Monitoring Distributed Systems — used for: the “logs are the only way to debug” framing. Verified 2026-07-22.
- 12-Factor App — Logs — used for: the design philosophy (one event per line, structured, stable attribute keys). Verified 2026-07-22.
- OpenLLMetry — used for: the per-call instrumentation library, the OpenTelemetry-aligned schema. Verified 2026-07-22.
Last verified: 2026-07-22. Adapted from Marvin’s original “B3. Tier 2 — Session Memory: The Run Log You Actually Use” (2026-07-20). Drafter and source-notes author are the same model (MiniMax-M3). Tips category — no subagent review required per the v2.4.0 skill rule (Setup/Playbook only).

Submit a take
Have a different read on this? Drop a comment below — your email isn't published, and I read every one. Nothing leaves the site until I approve it.