Lesson 03 · 계획

에이전트가 자체 진행 상황을 관리하도록 허용

「The agent can track its own progress — and I can see it.」让模型自己列清单,然后用一个小机制让它记得更新清单。

⏱ 약 10 분 · 📝 3 개 인터랙티브 컴포넌트 · 🧑‍💻 기반 shareAI-lab · s03_todo_write.py

结构化的 self-planning

Claude Code 干活时经常要做好几步:grep 找引用 → 读几个文件 → 改代码 → 跑测试。如果你让模型「凭感觉推进」,你会看到它头几步做得不错,中间就开始遗忘,最后半途而废。

s03 的解法是给它一个清单工具:模型自己调 todo 工具往里塞任务项,TodoManager 验证结构、持久化、返回当前视图。这样有两个好处:

  • 模型被迫把「要做什么」显式化出来——光写出来就已经帮它理清了思路。
  • 人类能看到它在想什么。调试体验好十倍。
# TODO 视图,每一项都是结构化的
[ ] #1: grep "TODO" across src/
[>] #2: read src/app.py and list comments     # 正在做
[ ] #3: generate summary markdown
[ ] #4: write to TODO_LIST.md

(0/4 completed)

一条硬规则:同一时刻只有一个 in_progress

TodoManager.update() 里有一条校验:

if in_progress_count > 1:
    raise ValueError("Only one task can be in_progress at a time")

看似苛刻,其实是在帮模型。如果允许同时有 3 个「在做」,它就会四处开战、哪个都没做完。强制单任务推进,它被迫每完成一个才开下一个。

下面这个 widget 让你扮演模型,提交各种 todo payload,看哪些通过验证、哪些被拒。

Nag reminder:连续 3 轮没更新?戳一下

即使给了 todo 工具,模型还是会偶尔「忘记」更新清单——干了一堆事,但 in_progress 还卡在第 2 条。s03 的招式是一个非常简单的计数器:

rounds_since_todo = 0
while True:
    response = LLM(messages, tools)
    ...
    used_todo = any(b.name == "todo" for b in tool_uses)
    rounds_since_todo = 0 if used_todo else rounds_since_todo + 1
    if rounds_since_todo >= 3:
        results.append({"type":"text", "text":"<reminder>Update your todos.</reminder>"})

计数到 3,在下一轮的 user message 里夹一条 reminder。模型看到会本能地去调 todo。这是用工程手段把软性约束(「请保持更新」)变成强制刺激

这种套路的名字叫什么?

在 agent 设计圈里,这叫 structured self-planning with soft nudges——给模型一个它必须写入的结构化状态,辅以时机性的 reminder。Claude Code 真实代码里用了类似模式,但更克制(频率低、措辞中性)。

为什么不直接把「每步都更新 todo」写进 system prompt?写是可以写,但模型对 system prompt 里的通用指令服从度会随对话变长而衰减。把指令拆成「不断重注入的 reminder」效果稳定得多。
Interactive

Widget 1 · Kanban · todo 按 turn 演化

点 Step,看模型如何把任务从 pending 推到 in_progress 再到 completed。注意每一轮 in_progress 永远只有一个。

[ ] pending
[>] in_progress
[x] completed
准备开始…
Interactive

Widget 2 · Validation · 5 个 todo payload 哪些通过?

模型调 todo 工具时传一个 items 数组。TodoManager 会跑一串校验:text 非空、status 合法、最多一个 in_progress、总数 ≤ 20。点击判断每个 payload 通过或被拒。

答对 0 / 5
Interactive

Widget 3 · Nag Counter · 连续 3 轮没更新 todo 会发生什么

点 Next Turn,看计数器是否触发 reminder 注入。每一轮随机选「调用 todo」或「不调用」——现实中模型的表现也这样波动。

rounds_since_todo: 0