Skip to content

Todo Read

A todo-read tool gives the model a direct way to retrieve current task state before deciding what to do next.

Write-only task systems degrade quickly. Without a read path, an agent must reconstruct state from memory or prior chat text, which is brittle under long sessions, compaction, and subagent delegation.

A strong read primitive enables:

  • re-synchronization after interruption/resume
  • explicit “what remains?” checks before starting new work
  • consistent status reporting to users and downstream clients
  • safer coordination between primary and delegated agents

The hard part is consistency: if read data comes from a different source than write events, divergence is inevitable.


  • Planning for proposal/approval workflows that are distinct from checklist reads.
  • Todo Write for the corresponding mutation path.
  • Session Resumption for why explicit read primitives matter after interruption.

Aider at commit b9050e1d5faf8096eae7a46a9ecc05a86231384b has no model-callable todo-read tool.

aider/commands.py provides chat-mode controls (ask, code, architect) but no todo-list read command/tool.

Aider runtime does not persist a structured checklist object, so there is no equivalent of Todo.get(session_id) for model access.

Task awareness is inferred from conversation history:

  • model remembers prior commitments from chat text
  • user can ask for recap and model responds narratively
  • no typed response with status/priority fields

Aider can discuss progress, but progress recall is prompt-memory dependent rather than state-query dependent.


Codex at commit 4ab44e2c5cc54ed47e47a6729dfd8aa5a3dc2476 also has no dedicated model-callable todo-read function.

Core tool registry (core/src/tools/spec.rs) includes update_plan but does not define a separate read tool for checklist state.

The model writes checklist state using update_plan; clients observe it via events.

Codex read path is event-driven:

  1. model emits update_plan
  2. runtime emits EventMsg::PlanUpdate
  3. exec/TUI/app-server consumers render current plan state

In headless JSONL mode, event processors synthesize todo_list items (started/updated/completed) that SDK consumers can read.

So “read” exists for clients, but not as a direct model tool call.

Plan mode streaming (<proposed_plan>, PlanDelta) is separate from checklist state and should not be treated as todo-read data.

Codex codebase explicitly separates these channels:

  • checklist updates: PlanUpdate
  • plan authoring stream: PlanDelta / plan item

Advantages:

  • fewer model-call surfaces
  • deterministic client rendering from event stream

Tradeoff:

  • model cannot explicitly ask runtime “show current todos now” as a tool action; it must rely on turn context/history.

OpenCode at commit 7ed449974864361bad2c1f1405769fd2c2fcdf42 contains a dedicated todoread tool implementation, but current registry wiring is nuanced.

packages/opencode/src/tool/todo.ts defines todoread:

  • params: empty object
  • permission check: todoread
  • read path: Todo.get(ctx.sessionID)
  • returns serialized todos in tool output and metadata

Todo.get (session/todo.ts) reads rows ordered by position from TodoTable.

packages/opencode/src/tool/registry.ts imports TodoReadTool but does not include it in active tool list (commented out next to TodoWriteTool).

That means:

  • read implementation exists
  • config has permission schema for todoread
  • but default tool exposure may omit model-call access

This is a key operational nuance: implementation parity and registry exposure are not the same thing.

Independent of tool exposure, OpenCode server exposes session-level todo read endpoint:

  • GET /session/:sessionID/todo in server/routes/session.ts
  • response schema: Todo.Info[]

So clients can fetch canonical todo state even when model tool registry omits todoread.

TUI state store (cli/cmd/tui/context/sync.tsx) listens for todo.updated events and also hydrates from sdk.client.session.todo(...), ensuring sidebar/task display reflects durable session state.


Defined-But-Disabled Tools Create Documentation Drift

Section titled “Defined-But-Disabled Tools Create Documentation Drift”

OpenCode’s todoread shows that code existence is not feature availability. Docs and UX must track registry-level gating, not only tool source files.

If tool reads from one source and UI from another, users see conflicting task states. A single canonical storage + event source is mandatory.

Missing Read Primitive Pushes Burden to Prompt Memory

Section titled “Missing Read Primitive Pushes Burden to Prompt Memory”

When no direct read tool exists (Aider, Codex model surface), long sessions rely on context retention and summarization, increasing drift risk.

Even with a read tool, calling it before every minor action can bloat context. Systems need guidance on when re-read is materially useful.

Read-after-write races can show stale snapshots when multiple sessions/agents update state quickly. Versioned reads and monotonic update ids reduce confusion.


Expose todo_read as a stable model-call primitive with no parameters and typed response:

  • version
  • items[] (id, content, status, priority, updated_at)

Both tool responses and UI components should read from the same session store and event log. Do not maintain parallel in-memory-only task lists.

Include snapshot version in read response and attach version to writes:

  • write with stale base version can be rejected or merged
  • read clients can detect if they are behind

Support registry-level gating, but surface availability clearly in model instructions so the agent does not attempt absent tools.

Render todo snapshots and event deltas distinctly:

  • snapshot read: authoritative full list
  • delta events: incremental updates in timeline
  • serde/schemars for read response schema
  • sqlx or rusqlite for store
  • tokio channels/event bus for sync
  1. Keep read and write on the same canonical data path.
  2. Make tool availability explicit and introspectable.
  3. Add versioning early to avoid stale-read ambiguity.
  4. Optimize read frequency with prompt guidance, not hidden heuristics.