Zum Hauptinhalt springen
Die Todo-Verfolgung bietet eine strukturierte Möglichkeit, Aufgaben zu verwalten und Benutzer über den Aufgabenfortschritt zu informieren. Das Claude Agent SDK enthält integrierte Todo-Funktionalität, die dabei hilft, komplexe Arbeitsabläufe zu organisieren und Benutzer über die Aufgabenprogression zu informieren.
Ab TypeScript Agent SDK 0.3.142 und Claude Code v2.1.142 verwenden Sitzungen die strukturierten Task-Tools TaskCreate, TaskUpdate, TaskGet und TaskList anstelle von TodoWrite. Siehe Zu Task-Tools migrieren für Informationen darüber, wie sich der Überwachungscode ändert. Die Beispiele auf dieser Seite setzen CLAUDE_CODE_ENABLE_TASKS=0, um weiterhin TodoWrite für Sitzungen anzuzeigen, die noch nicht migriert wurden.

Todo-Lebenszyklus

Todos folgen einem vorhersehbaren Lebenszyklus:
  1. Erstellt als pending, wenn Aufgaben identifiziert werden
  2. Aktiviert zu in_progress, wenn die Arbeit beginnt
  3. Abgeschlossen, wenn die Aufgabe erfolgreich beendet wird
  4. Entfernt, wenn alle Aufgaben in einer Gruppe abgeschlossen sind

Wann Todos verwendet werden

Das SDK erstellt automatisch Todos für:
  • Komplexe mehrstufige Aufgaben, die 3 oder mehr unterschiedliche Aktionen erfordern
  • Von Benutzern bereitgestellte Aufgabenlisten, wenn mehrere Elemente erwähnt werden
  • Nicht triviale Operationen, die von der Fortschrittsverfolgung profitieren
  • Explizite Anfragen, wenn Benutzer um Todo-Organisation bitten

Beispiele

Überwachung von Todo-Änderungen

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",
  // Re-enable TodoWrite, which this example monitors. Without it, the SDK uses
  // Task tools instead and these tool_use blocks never appear.
  options: { maxTurns: 15, env: { ...process.env, CLAUDE_CODE_ENABLE_TASKS: "0" } }
})) {
  // Todo updates are reflected in the message stream
  if (message.type === "assistant") {
    for (const block of message.message.content) {
      if (block.type === "tool_use" && block.name === "TodoWrite") {
        const todos = block.input.todos;

        console.log("Todo Status Update:");
        todos.forEach((todo, index) => {
          const status =
            todo.status === "completed" ? "✅" : todo.status === "in_progress" ? "🔧" : "❌";
          console.log(`${index + 1}. ${status} ${todo.content}`);
        });
      }
    }
  }
}

Echtzeit-Fortschrittsanzeige

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" ? "🔧" : "❌";
      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,
      // Re-enable TodoWrite, which this tracker watches for.
      options: { maxTurns: 20, env: { ...process.env, CLAUDE_CODE_ENABLE_TASKS: "0" } }
    })) {
      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();
          }
        }
      }
    }
  }
}

// Usage
const tracker = new TodoTracker();
await tracker.trackQuery("Build a complete authentication system with todos");

Zu Task-Tools migrieren

Die Task-Tools teilen den einzelnen TodoWrite-Aufruf in TaskCreate für jedes neue Element und TaskUpdate für jede Statusänderung auf, wobei TaskList und TaskGet für das Modell verfügbar sind, um die aktuelle Liste zu lesen. Ihr Überwachungscode inspiziert weiterhin tool_use-Blöcke im Assistent-Stream, verwaltet aber eine Zuordnung mit Task-ID als Schlüssel, anstatt die gesamte Liste bei jedem Aufruf zu ersetzen. Die Task-Tools sind ab TypeScript Agent SDK 0.3.142 und Claude Code v2.1.142 die Standardeinstellung, daher ist keine Änderung von options.env erforderlich.
Mit TodoWriteMit Task-Tools
Ein Tool-Aufruf schreibt das gesamte todos-Array neuTaskCreate fügt ein Element hinzu, TaskUpdate patcht ein Element nach taskId
Abgleich block.name === "TodoWrite"Abgleich block.name === "TaskCreate" oder "TaskUpdate"
Element-Form: { content, status, activeForm }TaskCreate-Eingabe: { subject, description, activeForm?, metadata? }. TaskUpdate-Eingabe: { taskId, status?, subject?, description?, activeForm?, addBlocks?, addBlockedBy?, owner?, metadata? }. status ist "pending", "in_progress" oder "completed"; setzen Sie status: "deleted" zum Löschen
Rendern Sie block.input.todos direktSammeln Sie Elemente über Aufrufe hinweg, oder lesen Sie einen Snapshot aus einem TaskList-Tool-Ergebnis
Die zugewiesene Task-ID befindet sich nicht in der TaskCreate-Eingabe. Sie kommt im entsprechenden tool_result als { task: { id, subject } } zurück, daher erfassen Sie sie aus dem Ergebnis-Block, um Ihre Zuordnung zu schlüsseln. Das folgende Beispiel zeigt die minimale Änderung an der Überwachung von Todo-Änderungen-Schleife. Um eine vollständige Liste zu rendern, beobachten Sie ein TaskList-Tool-Ergebnis im Stream oder sammeln Sie TaskCreate-Ergebnisse und TaskUpdate-Eingaben in einer Zuordnung:
import { query } from "@anthropic-ai/claude-agent-sdk";

for await (const message of query({
  prompt: "Optimize my React app performance",
})) {
  if (message.type !== "assistant") continue;
  for (const block of message.message.content) {
    if (block.type !== "tool_use") continue;
    if (block.name === "TaskCreate") {
      const input = block.input as { subject: string };
      console.log(`+ ${input.subject}`);
    } else if (block.name === "TaskUpdate") {
      const input = block.input as { taskId: string; status?: string };
      if (input.status) console.log(`  ${input.taskId} -> ${input.status}`);
    }
  }
}

Zugehörige Dokumentation