AI 支援開発

セッションハンドオフがAIコーディングセッション間でコンテキストを維持する仕組み

AIコーディングエージェントは、セッションが終了するとすべてを忘れてしまいます。短い引き継ぎメモが、実行したこと、未完了の作業、そして次のステップを伝えます。

この記事は英語の原文をAIモデルが翻訳したものです。表現が原文と異なる場合があります。 英語の原文を読む

AIコーディングエージェントには有限のコンテキストウィンドウがあり、実際のタスクがその中に収まることはめったにありません。セッションがいっぱいになったり、その日の作業を終えたり、モデルの速度を維持するために新しい会話を始めたりします。そうなると、エージェントが作業について知っていたこと、つまり、何を変更したか、なぜ変更したか、何がまだ壊れているか、次に何をしようとしていたか、といったことはすべて失われます。解決策は古くからある退屈なものです。人間がシフトを引き継ぐとき、彼らはメモを残します。AIセッションも同じメモを残すべきであり、次のセッションは最初にそれを読むべきです。

AIセッションが文脈を見失う理由

コンテキストウィンドウは、エージェントのワーキングメモリ全体です。そこには、開いたファイル、議論を重ねて下した決定、すでに行き止まりだと判断したこと、そして頭の中にあっただけで書き留められなかった未完成の計画が保持されています。そのすべてが、1つの会話の中にのみ存在し、他のどこにも存在しません。

そのメモリは揮発性です。よくある3つの理由により、セッションが終了するとそのメモリは失われます。長いタスクではウィンドウがいっぱいになり、最も古いメッセージがスコープから外れてしまいます。ラップトップを閉じて、翌日戻ってくると、新しい会話から始まります。あるいは、肥大化したコンテキストによってモデルが遅くなり、焦点がぼやけやすくなるため、意図的にやり直すこともあります。どの場合でも、次のセッションは白紙の状態から始まり、同じ代償を支払うことになります。つまり、コードベースを再度説明し、目標を再度述べ、1時間前にすでに行った決定を再度導き出すのです。3つか4つのセッションにまたがるタスクでは、その再説明のほとんどは純粋な無駄です。

問題は、エージェントが忘れっぽいことではありません。問題は、そのメモリが永続的な場所に一切書き込まれなかったことです。このセッションであなたが言ったことは、何もディスク上にありません。それを修正すれば、セッションの境界はもはや崖ではなくなります。

メモリをディスクに外部化する

全体的なアイデアは1つの動きです。コンテキストウィンドウ内に存在していた状態を取り出し、ファイルに保存することです。引き継ぎメモがそのファイルです。それは、次のセッションの開始時に読み込めるように、あるセッションの最後に書かれる、作業の進捗状況に関する小さく永続的な記録です。

これは、人々がすでに行っている働き方を反映しています。シフト制の勤務者はログを残します。休暇に入る開発者は、チームメイトがチケットを引き継げるように、引き継ぎドキュメントを作成します。次の担当者が差分から3日分の思考過程を再構築することなど、誰も期待しません。そのメモが、ギャップを越えて思考過程を伝えます。AIセッションも同じ理由で同じものを必要としますが、そのギャップが2人の人間の間ではなく、同じツールとの2つの会話の間にあるという点が異なります。

状態がファイルに存在するようになれば、継続性はメモリに依存しなくなります。今日であろうと来週であろうと、どのセッションでもそのメモを読み込み、全体像を把握した上で再開できます。重要な部分が保存されているため、コンテキストウィンドウは使い捨てになります。

引き継ぎが実際に含むべき内容

良い引き継ぎは、4つの質問に答えるものであり、それ以外の何ものでもありません。それはステータスレポートであり、日記ではありません。ここでは長さが敵となります。なぜなら、長文は人にも、関連する行を拾い読みするモデルにも読まれないからです。

セクション 含まれる内容 目安
完了したこと このセッションで完了したこと、各項目1行で 箇条書き数点
主要な決定事項 コードを方向付ける選択とその理由 他の人が驚くであろうもの
未完了事項と次の作業 未完了なこと、そして次のセッションで避けるべき罠 最も重要なことを最初に
参照先 参照すべき場所:ファイル、コミット、チケット、ログ 曖昧なヒントではなく、正確なパス

最初のセクションは結果の要約です。これにより、次のセッションはどこまでカバーされているかを把握できます。2番目のセクションは、再構築にコストがかかる部分です。つまり、決定の背後にある理由、却下した選択肢とその理由、コードからは明らかでない制約などです。3番目のセクションは、継続性が実際に生まれる場所です。なぜなら、次のステップとそれに潜む地雷を明記するからです。4番目のセクションは、メモをインデックスに変えます。これにより、次のセッションは30個のファイルではなく3個のファイルを読めばよくなります。

内容は濃く、簡潔にしてください。曖昧な表現や繰り返しのある引き継ぎは、誰も最後まで読まない引き継ぎとなり、本末転倒です。

引き継ぎテンプレート

形式を固定すると、メモを素早く書け、内容の確認も速くなります。毎回見出しが同じだと、次のセッションで次のステップをどこで探すべきかが正確にわかります。以下に示すのは、長期のタスクでもうまく機能してきたテンプレートです。

# Handoff: <task name> (<date>)

## Done this session
- Wired the payment webhook to the new queue
- Added retry with backoff, capped at 5 attempts

## Key decisions
- Idempotency key is the provider event id, not our order id.
  The provider can resend an event, and order id is not unique per event.
- Chose an at-least-once queue over exactly-once. Handlers are already
  idempotent, so duplicates are safe and the setup is far simpler.

## Open / next
- NEXT: the dead-letter path is not wired yet. Failed events vanish
  after 5 retries. Start here.
- Trap: the staging webhook secret differs from prod. Do not copy the
  prod value into staging config.

## Pointers
- Handler: internal/payments/webhook.go
- Queue setup: internal/queue/consumer.go:42
- Failing test: TestWebhookRetry (currently skipped)
- Related commit: a1b9f30

2つの点が、これをうまく機能させています。次のステップが明記され、セクションの冒頭に記載されているため、作業を再開するセッションでは、それを探す手間なく対応できます。そして、罠は文章に埋もれさせるのではなく、罠として明記されます。なぜなら、引き継ぎの真価は、次のセッションが予見できない間違いを避けるよう警告することにあるからです。

引き継ぎの自動化

毎回手でメモを書くのは手間であり、手間はそれが実行されないことを意味します。より良い方法は自動化です。セッションが終了する合図を監視し、その瞬間に引き継ぎを生成または更新します。

その合図を捉えるのは簡単です。人が「ここで終わりにしましょう」、「今日はここまで」、または「新しいセッションを開始」のようなことをタイプします。ツールは、コンテキストウィンドウがその上限に近づいていることを検出できます。これらのいずれかがメモの作成をトリガーできます。内容は作業の状態に適応します。タスクが完了した場合、引き継ぎは短く、完了したこととその成果物がどこにあるかを伝える数行になります。作業が進行中の場合、メモは未完了のセクションと次のセクションに重点を置きます。なぜなら、それが次のセッションで最も必要とされるものだからです。

その利点は、規律を必要とせずにメモが最新の状態に保たれることです。メモを書くことを覚えておく必要も、更新することを覚えておく必要もありません。完了の合図を送った瞬間には、作業の状態はすでにディスク上にあり、次のセッションにはすでに読み込むべきものがあります。

引き継ぎが割に合わないとき

引き継ぎはオーバーヘッドであり、オーバーヘッドは何か見返りがある場合にのみ支払う価値があります。単一のセッション内で開始して終了する、短く一度きりのタスクの場合、それは何も生み出しません。変数の名前変更、タイポの修正、小さな関数を1つ書くことなど、埋めるべきギャップはないため、メモを書くことは純粋なコストです。やらないでください。

その価値は、2つの種類の作業で現れます。1つ目は、1回のセッションには大きすぎるタスクであり、その場合メモがあなた自身のセッションの境界を越えてコンテキストを伝えます。2つ目は、複数の人や複数のエージェントの間で渡される作業であり、その場合メモが彼らの間のインターフェースとなります。どちらの場合も、内容の濃い箇条書きをいくつか書くコストは、午後のコンテキストをゼロから再構築するコストに比べれば些細なものです。

正直なルールは、作業がセッションを越えて続く場合は引き継ぎを行い、そうでない場合は省略することです。安価な方向で推測を誤り、不要なメモを書いてしまった場合、かかるコストは1分です。高価な方向で推測を誤り、複数セッションにまたがるタスクでメモを省略してしまった場合、次のセッションで1時間のコストがかかります。

引き継ぎを誠実なものに保つ

引き継ぎには、まったくない場合よりも悪い失敗モードが1つあります。それは、陳腐化です。もしメモにデッドレターパスが接続されていないと書かれているのに、前回のセッションであなたがそれをこっそり接続してメモを更新しなかった場合、次のセッションは誤った情報を読み込むことになります。それは誤った全体像に基づいて作業し、地図が実情と一致しないことを発見するために時間を浪費します。間違った引き継ぎは、ない引き継ぎよりも危険です。なぜなら、メモがなければコンテキストがないことを承知の上でそれを再構築することになるのに対し、古いメモはすでに間違っているコンテキストを信用させてしまうからです。

これが、利便性を超えて自動化が重要である理由です。各セッションの終了時に更新されるメモは、現実を反映します。手で編集されて徐々にずれていくのではなく、毎回現在の状態から書き直されるからです。正式な引き継ぎファイルを1つだけ保持し、それを上書きしてください。読み手がどれが最新かを推測しなければならないような、日付の入ったメモの山を溜め込まないでください。

その仕組みは古くからあるもので、それが重要な点です。シフトというものが存在する限りずっと、人々はログを使ってシフトを引き継いできました。唯一新しい点は、次のシフトの同僚が同じツールの別のインスタンスであり、前のシフトの記憶がなく、あなたが残したメモ以外にそれを知る方法がない、ということです。メモを書いてください。簡潔にしてください。内容を正確に保ってください。次のセッションは、それを実行するのが誰であれ何であれ、あなたが中断したまさにその場所から再開するでしょう。