obsidian/wiki/agent-sdk/todo-tracking.md
2026-04-17 13:18:19 +01:00

4.6 KiB

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
raw/Todo Lists.md
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.

Source: raw/Todo Lists.md — https://code.claude.com/docs/en/agent-sdk/todo-tracking