analysis_claude_code/docs/en/s03-todo-write.md
CrazyBoyM a9c71002d2 the model is the agent, the code is the harness
Comprehensive rewrite establishing the harness engineering narrative
across the entire repository.

README (EN/ZH/JA): added "The Model IS the Agent" manifesto with
historical proof (DQN, OpenAI Five, AlphaStar, Tencent Jueyu),
"What an Agent Is NOT" critique, harness engineer role definition,
"Why Claude Code" as masterclass in harness design, and universe
vision. Consistent framing: model = driver, harness = vehicle.

docs (36 files, 3 languages): injected one-line "Harness layer"
callout after the motto in every session document (s01-s12).

agents (13 Python files): added harness framing comment before
each module docstring.

skills/agent-philosophy.md: full rewrite aligned with harness
narrative.
2026-03-18 01:19:34 +08:00

3.2 KiB

s03: TodoWrite

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

"An agent without a plan drifts" -- list the steps first, then execute.

Harness layer: Planning -- keeping the model on course without scripting the route.

Problem

On multi-step tasks, the model loses track. It repeats work, skips steps, or wanders off. Long conversations make this worse -- the system prompt fades as tool results fill the context. A 10-step refactoring might complete steps 1-3, then the model starts improvising because it forgot steps 4-10.

Solution

+--------+      +-------+      +---------+
|  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

How It Works

  1. TodoManager stores items with statuses. Only one item can be in_progress at a time.
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. The todo tool goes into the dispatch map like any other tool.
TOOL_HANDLERS = {
    # ...base tools...
    "todo": lambda **kw: TODO.update(kw["items"]),
}
  1. A nag reminder injects a nudge if the model goes 3+ rounds without calling todo.
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>",
        })

The "one in_progress at a time" constraint forces sequential focus. The nag reminder creates accountability.

What Changed From s02

Component Before (s02) After (s03)
Tools 4 5 (+todo)
Planning None TodoManager with statuses
Nag injection None <reminder> after 3 rounds
Agent loop Simple dispatch + rounds_since_todo counter

Try It

cd learn-claude-code
python agents/s03_todo_write.py
  1. Refactor the file hello.py: add type hints, docstrings, and a main guard
  2. Create a Python package with __init__.py, utils.py, and tests/test_utils.py
  3. Review all Python files and fix any style issues