Live betaCtrlB Session Store

A new kind of agent memory that keeps every detail

CtrlB Session Store keeps every message, tool call and tool result of your agent sessions. Your agents search it when they need a detail.

Illustrative example

Agent context

25%
SummaryFixed the retry tests in refunds. Next: update the docs.
  1. #38PromptKeep refund retries under 3.
  2. #41bashpytest tests/refunds -k retry
  3. #42ResultFAILED test_retry.py::test_cap
  4. #57Editsrc/refunds.py
  5. #90PromptWhich test failed before the fix?
  6. #91Searchsearch_sessions("retry.py")
  7. #92AnswerFound at #42: test_cap in test_retry.py failed.Exact row

Session store

4 rows kept
  1. #38PromptKeep refund retries under 3.
  2. #41bashpytest tests/refunds -k retry
  3. #42ResultFAILED test_retry.py::test_capHit
  4. #57Editsrc/refunds.py
Compaction removes rows from the context. The session store keeps every row, and the agent finds it with one search.
  • 6%Exact answers left after compaction
  • 81 to 94%Detail recall, with a search instruction
  • +37 to 63 ptsSmaller model with the store beats larger without
  • 1.4 s vs 189 sSearch at 100× the record, against grep
A new kind of agent memory

Other memory decides early. This one decides late.

Compaction and extracted memory choose what to keep before the question exists.

Illustrative example

Turn 90 asks

Which test failed before the fix?

Compaction summary

Decides at compaction

Fixed the retry tests in refunds. Next: update the docs.

Not in the summary

29%detail recall

Extracted memory

Decides when it writes

  • Prefers pytest
  • Refunds live in src/refunds.py
  • Retries capped at 3
Never extracted

37%detail recall

CtrlB Session Store

Decides when your agent asks

  1. #41bashpytest tests/refunds -k retry
  2. #42ResultFAILED test_retry.py::test_cap
  3. #57Editsrc/refunds.py
#42: test_cap failed

81%detail recall

One model (GPT-6 Luna) and the same 100 detail questions for all three, asked at real compaction points.

Memory that decides when it writes has to guess which details will matter. The session store keeps every row, so the agent decides at read time, when it knows the question.

From your agent to a search

Hooks upload every turn, and your agent searches the record when it needs a detail.

Illustrative example
  1. Your agent

    Claude Code or Codex runs as usual.

    Subagents too.

  2. Hooks upload

    At the end of each turn, before compaction and at session end.

    Secrets are redacted first.

  3. Your bucket

    One row per message, tool call and tool result.

    Open Parquet in S3, GCS or Azure Blob.

  4. Recall tools

    The agent searches the record over MCP.

    search_sessionsfind_commandnext_actionsfetch_records
Search before you answer

At session start, the agent is told: search before you answer.

At session start, the plugin adds one line to the agent’s context: search the record before you answer about earlier work. Without that line, GPT-6 Luna made no recall call in 90% of runs. Hooks redact text that looks like a secret before upload, but the patterns are not a guarantee.

What your agents can ask

Four MCP tools read the record, and each reply stops at 12,000 characters.

  • search_sessions

    Find a word across sessions

    It finds a whole word in messages, commands and results, in current and past sessions. It returns 10 hits by default, 25 at most.

    search_sessions(term="refunds.py")

    You get: Hits with session, row number and a 300-character snippet.

  • find_command

    Find a command you ran before

    It returns every past tool call whose command contains your text, newest first. It returns 10 by default, 25 at most.

    find_command(command="pytest tests/refunds")

    You get: The total, then session, row and command for each match.

  • next_actions

    See what happened next

    It returns the result of one tool call, then the next three calls and their results. Text and thinking rows are skipped.

    next_actions(session_id="7f3a91c2", seq=41)

    You get: What the agent did after a failure, and whether it worked.

  • fetch_records

    Open the rows around a hit

    It returns the rows of a range in order. A range holds 50 rows at most, and each body is cut at 4,000 characters.

    fetch_records(session_id="7f3a91c2", seq_from=38, seq_to=42)

    You get: The exact rows, with the full length of any cut body.

Measured on real sessions

Four models, two families, asked at real compaction points.

Four engineers’ sessions, 100 detail questions per model family, with a one-line instruction to search.

Detail recall: summary only against the session store

Four models in two families, 100 detail questions per family, one run per question. The summary stays in context in both arms. The store arm also gets a one-line instruction to search.
Detail recall, correct answers (%)
ModelSummary onlySession store
Claude Haiku 5.523%85%
Claude Sonnet 5.522%89%
GPT-6 Luna29%81%
GPT-6.1 Sol35%94%
  • 37 to 63 ptsSmaller model with the store, against a larger model with only a summary or extracted memory. Detail recall.Haiku 5.5 with the store costs about 1/15 as much per question as Sonnet 5.5.
  • 70 to 72%Cross-session lookup with the store, small models. Summary only answered none.60 questions per family, no session named.
  • -2 to +6 ptsRecall change when the summary is dropped, with the store and the search instruction on. Each answer cost less.Compaction pauses a Claude Code session for a median of 61 s.

With the store on both sides, the larger model is level or ahead. Haiku 5.5 trails Sonnet 5.5 by 4 points, not significant. GPT-6 Luna trails GPT-6.1 Sol by 13.

The limit: four engineers at one company over six weeks, and a model judged the answers.

Search matches exact words. We did not test search by meaning.

See your team's sessions

Each engineer's sessions upload as rows you can search and query.

  • You see your own sessions by default. The sessions.read_all permission shows everyone’s.
  • Rows are open Parquet files in your S3, GCS or Azure Blob bucket.
  • Search stays fast as the record grows.
Median search time of CtrlB against grep over the files, 120 calls at each size.
Record sizeCtrlBgrep over files
1× (170k rows)147 ms450 ms
10× (1.7M rows)494 ms4.1 s
100× (17M rows)1.05 s165 to 408 s (9 of 120 calls finished)

At 100×, the files are larger than the test machine’s memory, and grep finished 9 of 120 calls. On those nine calls, CtrlB took 1.4 s and grep took 189 s.

Sample data
retry.pyShow: Top-level
Sample sessions table with four agent sessions
SessionUserHarnessLast activityTurnsTool callsErrors
Keep refund retries under 3.7f3a91c2 · billing-api · fix/retry-cappriya@acme.devClaude Code10:42461122
Add idempotency keys to the refund endpointc41e08b7 · billing-api · maindan@acme.devCodex10:1531740
Why does the invoice export time out?9b20d4ae · invoices · perf/exportpriya@acme.devClaude Code09:5818401
Write the migration for refund_attemptse83f5c10 · billing-api · fix/retry-capsam@acme.devClaude Code09:3122510
4 sessions

Works with your agents and Relay

The CtrlB plugin connects Claude Code and Codex.

  • Claude Code logoClaude Code
  • Codex logoCodex
AI Observability pricing

Start with the agents you run today.

Tracing, evaluations, investigations, and Guardrails in one plan.

  • Production traces and model cost tracking
  • Scheduled investigations and prompt comparisons
  • Tool policies with Guardrails
  • OpenTelemetry, your own bucket and your own model key

AI Observability

From $499 / month

Platform fee. Usage is quoted separately for your workload.

Discuss your workload

We agree usage costs before you start. Your providers bill model and bucket costs directly.

Need a larger deployment?Enterprise pricing
FAQ

Common questions

What does the session store keep?

It keeps one row for each message, tool call and tool result. Each row has the role, the shell command, the time and the session. Subagents are included. Nothing is updated or deleted.

How is it different from extracted memory?

Extracted memory decides what to keep when it writes. The session store keeps every row, and your agent decides what matters when it asks. With GPT-6 Luna on 100 detail questions, extracted memory scored 37% and the store scored 81%.

How is it different from compaction?

Compaction writes a summary and drops the rows. In our Claude Code sessions, 6% of exact answers were still in the context after compaction. Exact means a path, number, error line or command. The store keeps the rows, so the agent can find them.

Where does my data live?

Rows are open Parquet files in your S3, GCS or Azure Blob bucket, and SQL can query them. Hooks redact text that looks like a secret before upload. The redaction patterns match common key and token shapes and are not a guarantee.

Who can see whose sessions?

You see your own sessions by default. The sessions.read_all permission shows every user's sessions. The sessions.write permission lets your agents upload them.

What does it cost, and how fast is it?

At 100× the record, CtrlB search took a median of 1.05 s. Grep over the files finished 9 of 120 calls. Haiku 5.5 with the store costs about 1/15 as much per question as Sonnet 5.5. Pricing is on this page.

Do I need Relay?

No. The session store works on its own. Relay builds its runs from session store records, so agents in a Relay run need sessions.write.

Which agents does it work with?

Claude Code and Codex, through the CtrlB plugin and hooks. The hooks upload at the end of each turn, before compaction and at session end.

Live beta

See the Session Store with your agents

Live beta. From $499/month, plus usage.