How to Build an AI Agent
How to Build an AI Agent
s03

TodoWrite

Planung & Koordination

Plan Before You Act

176 LOC5 ToolsTodoManager + nag reminder
An agent without a plan drifts; list the steps first, then execute

s01 > s02 > [ s03 ] s04 > s05 > s06 | s07 > s08 > s09 > s10 > s11 > s12

"Ein Agent ohne Plan driftet" -- listen Sie zuerst die Schritte auf, dann führen Sie aus.

Problem

Bei mehrstufigen Aufgaben verliert das Modell den Überblick. Es wiederholt Arbeit, überspringt Schritte oder schweift ab. Lange Gespräche verschlimmern dies -- der System-Prompt verblasst, während Tool-Ergebnisse den Kontext füllen. Ein 10-Schritte-Refactoring könnte Schritte 1-3 abschließen, dann beginnt das Modell zu improvisieren, weil es die Schritte 4-10 vergessen hat.

Lösung

+--------+      +-------+      +---------+
|  User  | ---> |  LLM  | ---> | Tools   |
| prompt |      |       |      | + todo  |
+--------+      +---+---+      +----+----+
                    ^                |
                    |   tool_result  |
                    +----------------+
                          |
              +-----------+-----------+
              | TodoManager state     |
              | [ ] task A            |
              | [>] task B  <- doing  |
              | [x] task C            |
              +-----------------------+
                          |
              if rounds_since_todo >= 3:
                inject <reminder> into tool_result

Wie es funktioniert

  1. TodoManager speichert Elemente mit Status. Nur ein Element kann gleichzeitig in_progress sein.
class TodoManager:
    def update(self, items: list) -> str:
        validated, in_progress_count = [], 0
        for item in items:
            status = item.get("status", "pending")
            if status == "in_progress":
                in_progress_count += 1
            validated.append({"id": item["id"], "text": item["text"],
                              "status": status})
        if in_progress_count > 1:
            raise ValueError("Only one task can be in_progress")
        self.items = validated
        return self.render()
  1. Das todo Tool geht wie jedes andere Tool in die Dispatch-Map.
TOOL_HANDLERS = {
    # ...base tools...
    "todo": lambda **kw: TODO.update(kw["items"]),
}
  1. Ein Nörgel-Erinnerung injiziert einen Stoß, wenn das Modell 3+ Runden geht, ohne todo aufzurufen.
if rounds_since_todo >= 3 and messages:
    last = messages[-1]
    if last["role"] == "user" and isinstance(last.get("content"), list):
        last["content"].insert(0, {
            "type": "text",
            "text": "<reminder>Update your todos.</reminder>",
        })

Die "einer in_progress zu einem Zeitpunkt" Einschränkung erzwingt sequentielle Konzentration. Die Nörgel-Erinnerung schafft Verantwortlichkeit.

Was sich von s02 geändert hat

KomponenteVorher (s02)Nachher (s03)
Tools45 (+todo)
PlanungNoneTodoManager mit Status
Nörgel-InjektionNone<reminder> nach 3 Runden
Agent-SchleifeSimple dispatch+ rounds_since_todo Zähler

Ausprobieren

python agents/s03_todo_write.py
  1. Refaktorisieren Sie die Datei hello.py: fügen Sie Type Hints, Docstrings und einen Main Guard hinzu
  2. Erstellen Sie ein Python-Paket mit __init__.py, utils.py und tests/test_utils.py
  3. Überprüfen Sie alle Python-Dateien und beheben Sie alle Stilprobleme