Skip to content

Storage models across Codex, OpenCode, and Pi

Storage models across Codex, OpenCode, and Pi

Section titled “Storage models across Codex, OpenCode, and Pi”

The shortest useful summary is this:

  • Codex gives you the cleanest external thread and sub-agent API shape.
  • OpenCode gives you the cleanest local event-sourced session architecture.
  • Pi gives you the cleanest branch-aware conversation tree architecture.

For your own Vercel AI SDK / Eve app, I would combine them rather than copy one directly.

Project Primary unit Storage style Best idea to steal
Codex Thread, turn, thread items Hosted API model, backend hidden Explicit fork and sub-agent thread relationships
OpenCode Session plus durable events plus projected messages SQLite plus event sourcing Separate write model from read model
Pi Session tree entries plus active leaf Append-only tree with JSONL or SQLite backends Make branching first-class

Codex: strong API contract, hidden backend

Section titled “Codex: strong API contract, hidden backend”

Codex is the best source for naming and API shape, but not for backend SQL.

What the inspected SDK models make clear:

  • A thread is the durable conversation container.
  • A turn is one agent execution inside that thread.
  • Forking is explicit through ThreadForkParams with threadId and optional lastTurnId.
  • Sub-agent relationships are explicit through models like ThreadSpawn.parent_thread_id, SubAgentActivityThreadItem.agent_thread_id, and CollabAgentToolCallThreadItem.sender_thread_id plus receiver_thread_ids.

Practical takeaway: if you want your app API to feel clean, expose thread, turn, fork, and child-agent concepts directly instead of hiding them inside one giant messages table.

OpenCode: event-sourced session architecture

Section titled “OpenCode: event-sourced session architecture”

OpenCode stores sessions in SQLite, but the important pattern is architectural, not just relational.

The key tables are:

  • session: metadata, lineage (parent_id), title, model, cost, token totals, archival state, revert state.
  • session_message: a projected timeline with type, seq, timestamps, and JSON data.
  • session_input: admitted or pending prompts, with durable sequence tracking.
  • session_context_epoch: a cached context boundary and snapshot.

The key idea is that durable events like session.next.prompted, session.next.step.started, session.next.tool.called, and session.next.compaction.ended are replayed into the message timeline.

Practical takeaway: keep an append-only write model, then derive a fast read model for your UI.

Pi treats thread history as a tree, not a plain list.

The key ideas are:

  • Every entry has id, parentId, timestamp, type, and a typed payload.
  • The live context is reconstructed from the current leaf back to root, or back to the latest compaction boundary.
  • Moving across branches is explicit through moveTo(entryId).
  • Compaction and branch summaries are new durable entries, not destructive rewrites.

Important entry types include:

  • message
  • thinking_level_change
  • model_change
  • active_tools_change
  • compaction
  • branch_summary
  • label
  • session_info
  • leaf

Practical takeaway: if branching matters, model it from day one.

If I were implementing this for an AI SDK / Eve stack, I would do this:

  1. A threads table for thread identity and parent-child lineage.
  2. A durable thread_events table for all write-side facts.
  3. A message_projection table for fast rendering.
  4. A thread_summaries table for compaction and replay boundaries.
  5. An agent_relationships table so sub-agents are separate threads with explicit links.

That gives you:

  • Codex-style thread and sub-agent semantics.
  • OpenCode-style durable replay and projection.
  • Pi-style branching and active-leaf navigation.

Answer these from memory before scrolling back:

  1. Which project is the best source for sub-agent thread relationships?
  2. Which project is the best source for event-sourced replay?
  3. Which project is the best source for active-leaf branch navigation?
  4. Why should compaction be append-only instead of destructive?

Use the reference page for the exact tables and the recommended schema:

Ask follow-up questions when you want to turn this into an exact Postgres schema for your app.