Todo Read
Feature Definition
Section titled “Feature Definition”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.
Why Read Matters
Section titled “Why Read Matters”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.
See Also
Section titled “See Also”- 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 Implementation
Section titled “Aider Implementation”Aider at commit b9050e1d5faf8096eae7a46a9ecc05a86231384b has no model-callable todo-read tool.
No Dedicated Read Endpoint for Task Lists
Section titled “No Dedicated Read Endpoint for Task Lists”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.
What Exists Instead
Section titled “What Exists Instead”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
Practical Implication
Section titled “Practical Implication”Aider can discuss progress, but progress recall is prompt-memory dependent rather than state-query dependent.
Codex Implementation
Section titled “Codex Implementation”Codex at commit 4ab44e2c5cc54ed47e47a6729dfd8aa5a3dc2476 also has no dedicated model-callable todo-read function.
No todo_read Tool in Core Registry
Section titled “No todo_read Tool in Core Registry”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.
How Todo State Is Read Indirectly
Section titled “How Todo State Is Read Indirectly”Codex read path is event-driven:
- model emits
update_plan - runtime emits
EventMsg::PlanUpdate - 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 Is Different from Todo Read
Section titled “Plan Mode Is Different from Todo Read”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
Constraint Profile
Section titled “Constraint Profile”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 Implementation
Section titled “OpenCode Implementation”OpenCode at commit 7ed449974864361bad2c1f1405769fd2c2fcdf42 contains a dedicated todoread tool implementation, but current registry wiring is nuanced.
TodoReadTool Definition
Section titled “TodoReadTool Definition”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.
Current Registry Reality
Section titled “Current Registry Reality”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.
Session API Read Path
Section titled “Session API Read Path”Independent of tool exposure, OpenCode server exposes session-level todo read endpoint:
GET /session/:sessionID/todoinserver/routes/session.ts- response schema:
Todo.Info[]
So clients can fetch canonical todo state even when model tool registry omits todoread.
TUI Sync Path
Section titled “TUI Sync Path”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.
Pitfalls & Hard Lessons
Section titled “Pitfalls & Hard Lessons”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.
Read/Write Source Split Risks Divergence
Section titled “Read/Write Source Split Risks Divergence”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.
Over-Frequent Reads Waste Tokens
Section titled “Over-Frequent Reads Waste Tokens”Even with a read tool, calling it before every minor action can bloat context. Systems need guidance on when re-read is materially useful.
Concurrency Requires Versioning
Section titled “Concurrency Requires Versioning”Read-after-write races can show stale snapshots when multiple sessions/agents update state quickly. Versioned reads and monotonic update ids reduce confusion.
OpenOxide Blueprint
Section titled “OpenOxide Blueprint”First-Class todo_read Tool
Section titled “First-Class todo_read Tool”Expose todo_read as a stable model-call primitive with no parameters and typed response:
versionitems[](id,content,status,priority,updated_at)
Single Source of Truth
Section titled “Single Source of Truth”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.
Consistency Model
Section titled “Consistency Model”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
Exposure Policy
Section titled “Exposure Policy”Support registry-level gating, but surface availability clearly in model instructions so the agent does not attempt absent tools.
UI Semantics
Section titled “UI Semantics”Render todo snapshots and event deltas distinctly:
- snapshot read: authoritative full list
- delta events: incremental updates in timeline
Crates
Section titled “Crates”serde/schemarsfor read response schemasqlxorrusqlitefor storetokiochannels/event bus for sync
Key Design Decisions
Section titled “Key Design Decisions”- Keep read and write on the same canonical data path.
- Make tool availability explicit and introspectable.
- Add versioning early to avoid stale-read ambiguity.
- Optimize read frequency with prompt guidance, not hidden heuristics.