Lesson 03 · 計画

agent に自分の進捗を管理させる

「The agent can track its own progress — and I can see it.」モデル自身にリストを作らせ、小さな仕組みでそれを更新し続けさせる

⏱ 約 10 分 · 📝 3 つのインタラクティブ要素 · 🧑‍💻 出典 shareAI-lab · s03_todo_write.py

構造化された自己計画

Claude Code が作業するとき、多くの場合複数のステップが伴う:grep で参照箇所を探す → 複数ファイルを読む → コードを修正する → テストを実行する。「感覚で進めて」とモデルに任せると、最初の数ステップはうまくいくが、途中でやるべきことを忘れ始め、最終的に中途半端に終わる。

s03 の解決策はモデルにリストツールを与えることだ:モデル自身が todo ツールを呼んでタスク項目を追加し、TodoManager が構造の検証・永続化・現在のビュー返却を担う。これには2つのメリットがある:

  • モデルが「何をすべきか」を明示的に書き出すことを強制される——書くだけで頭が整理される。
  • 人間側からモデルの思考が見える。デバッグ体験が格段によくなる。
# 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")

厳しく見えるが、実はモデルを助けている。複数の「進行中」を同時に許可すると、あちこちに手を出して何一つ完了しない。単一タスクへの強制によって、モデルは一つを終えてから次に進むしかなくなる。

以下の 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 がターンごとに進化する

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 は最大1つ・合計数 ≤ 20。各 payload が通過か拒否かを判定しよう。

正解 0 / 5
Interactive

Widget 3 · Nag Counter · 3ターン連続で todo を更新しないと何が起きるか

Next Turn を押してカウンターが reminder を発火させるかを確認しよう。各ターンはランダムに「todo を呼ぶ」か「呼ばない」かが決まる——実際のモデルの挙動もこのように変動する。

rounds_since_todo: 0