| title |
aliases |
tags |
sources |
created |
updated |
| Todo Tracking in the Agent SDK |
| todo-lists |
| todo-tracking |
| sdk-todos |
|
| agent-sdk |
| todos |
| progress-tracking |
| typescript |
| workflow |
|
|
2026-04-17 |
2026-04-17 |
Todo Tracking in the Agent SDK
Built-in todo functionality for managing multi-step workflows and displaying task progress to users. Todos are surfaced as TodoWrite tool calls in the wiki/agent-sdk/agent-loop.
Todo Lifecycle
| State |
Meaning |
pending |
Task identified, not yet started |
in_progress |
Work actively underway |
completed |
Task finished successfully |
| (removed) |
Cleared when all tasks in a group are done |
When the SDK Creates Todos Automatically
- Complex multi-step tasks requiring 3+ distinct actions
- User-provided task lists (multiple items mentioned)
- Non-trivial operations that benefit from progress visibility
- Explicit user requests for todo organization
Monitoring Todo Changes
Todos appear in the message stream as tool_use blocks with name === "TodoWrite":
import { query } from "@anthropic-ai/claude-agent-sdk";
for await (const message of query({
prompt: "Optimize my React app performance and track progress with todos",
options: { maxTurns: 15 }
})) {
if (message.type === "assistant") {
for (const block of message.message.content) {
if (block.type === "tool_use" && block.name === "TodoWrite") {
const todos = block.input.todos;
todos.forEach((todo, index) => {
const status =
todo.status === "completed" ? "✅"
: todo.status === "in_progress" ? "🔧"
: "❌";
console.log(`${index + 1}. ${status} ${todo.content}`);
});
}
}
}
}
Real-time Progress Tracker (Class Pattern)
import { query } from "@anthropic-ai/claude-agent-sdk";
class TodoTracker {
private todos: any[] = [];
displayProgress() {
if (this.todos.length === 0) return;
const completed = this.todos.filter(t => t.status === "completed").length;
const inProgress = this.todos.filter(t => t.status === "in_progress").length;
const total = this.todos.length;
console.log(`\nProgress: ${completed}/${total} completed`);
console.log(`Currently working on: ${inProgress} task(s)\n`);
this.todos.forEach((todo, index) => {
const icon =
todo.status === "completed" ? "✅"
: todo.status === "in_progress" ? "🔧"
: "❌";
// in_progress todos expose an activeForm (present-tense description)
const text = todo.status === "in_progress" ? todo.activeForm : todo.content;
console.log(`${index + 1}. ${icon} ${text}`);
});
}
async trackQuery(prompt: string) {
for await (const message of query({ prompt, options: { maxTurns: 20 } })) {
if (message.type === "assistant") {
for (const block of message.message.content) {
if (block.type === "tool_use" && block.name === "TodoWrite") {
this.todos = block.input.todos;
this.displayProgress();
}
}
}
}
}
}
const tracker = new TodoTracker();
await tracker.trackQuery("Build a complete authentication system with todos");
Notable Todo Fields
| Field |
Notes |
content |
Task description (pending/completed) |
activeForm |
Present-tense description used when in_progress |
status |
"pending" | "in_progress" | "completed" |
Key Takeaways
- Todos surface as
TodoWrite tool_use blocks in the assistant message stream — intercept them the same way as any other tool call.
- The
activeForm field gives a present-tense verb phrase for the active task, useful for UIs.
- Todos are created automatically for 3+ step tasks; no special configuration needed.
- Tracking state is ephemeral per session — persist
this.todos externally if you need durable progress records.
- Pairs naturally with wiki/agent-sdk/streaming-output for live progress UIs and wiki/agent-sdk/sdk-hooks for side-effects on task transitions.
Related
Source: raw/Todo Lists.md — https://code.claude.com/docs/en/agent-sdk/todo-tracking