LangGraph Interrupts は「承認ボタン」ではなく停止と再開の契約を実装させる
このノートは原文の代替ではありません。読むべきポイントと実装上の意味を整理し、原典への入口を示します。
要点まとめ
- 人の確認を入れたいなら、確認画面を足す前に、途中で止まった仕事をどの状態からどう再開するかを決めないと危ない。
- LangGraph は `interrupt()`、checkpointer、`thread_id`、`Command(resume=...)` を組にして、停止と再開を durable state の問題として扱っている。
- 本当に重要なのは、再開時に node が先頭から再実行されることと、interrupt 前の副作用が idempotent でないと二重実行事故になることだ。
- 日本の社内承認フローでも、承認 UI の有無より、worker 再起動後に同じ run を安全に戻せるかが本番の停止線になる。
読み終えたら次へ
この1本で終わらせず、同じ目的・同じテーマ・近い原典へ進めます。
何が変わったのか
この page は human-in-the-loop を抽象論で終わらせず、停止点と再開契約を実装レベルへ落としています。`interrupt()` が止める場所、checkpointer が保存する state、`thread_id` がどの run を指すか、`Command(resume=...)` がどの値を node 内へ返すかが明示されています。 さらに、複数 interrupt を扱う時は割り込み ID ごとに resume 値を対応づけること、再開時には interrupt を含む node が最初から走り直すこと、`try/except` で interrupt を捕まえると停止自体が壊れることまで注意されています。
なぜ重要か
日本の業務導入では「最後は人が確認するから安全」という説明で止まりやすいですが、それでは実装の危険箇所を隠します。危ないのは承認 UI ではなく、承認の前後で run がどの state を持つか、再開時に何が再実行されるか、承認者と worker が別系統でも orphan にならないかです。 この page は、その曖昧さを残したまま本番へ出すと二重副作用や誤再開が起きると示しています。approval 機能を持つ agent framework を比較する時も、見た目の UI より durable state 契約を見るべきだと分かります。
技術的ポイント
- `interrupt()` は graph 実行をその場で止める仕組みで、payload は JSON 化できる値に限られる。
- 再開には durable な checkpointer と同じ `thread_id` が必要で、`thread_id` は永続カーソルとして扱うべきである。
- `Command(resume=...)` の値は node 内の `interrupt()` の返り値になるが、再開時には node の先頭から再実行される。
- この再実行特性のため、interrupt 前の副作用は idempotent でなければ危険であり、upsert 化や node 分離が必要になる。
- 複数 interrupt を 1 つの node に置く場合、resume 値は index 順で対応づくため、条件分岐で順序を崩すと誤対応が起きやすい。
英日キーワード
| 英語 | 日本語 | 補足 |
|---|---|---|
| interrupt | 実行中断 | agent 実行を途中で止め、外部入力を待つ仕組み。承認待ちや人手確認の停止線になる。 |
| checkpointer | チェックポイント保存機構 | thread 状態を途中保存する仕組み。会話継続のための state persistence を担う。 |
| thread_id | スレッドID | どの停止状態や会話状態を再開するかを指す識別子。session 見た目と混同すると誤再開しやすい。 |
| resume | ||
| idempotency | 冪等性 | 同じ操作を繰り返しても結果が余計に増えない性質。interrupt 再開や retry 前提の実装で特に重要。 |
| human-in-the-loop | 人間承認付き運用 | 実行前に人が確認する設計。approval fatigue が起きるため、単独の主防御にはしにくい。 |
試すなら
- 自分の agent で止めたい操作を 3 つだけ書き出し、その直前に何を保存し、誰が何を返せば再開できるかを決める。
- `thread_id` を UI セッション名ではなく durable run ID として扱い、承認画面と worker の両方から同じ ID を追えるようにする。
- interrupt 前にある DB 書き込み、送信予約、監査記録を棚卸しし、upsert 化するか別 node に逃がす。
- worker 再起動や二重 resume をわざと起こし、二重送信や state ずれが出ないか確認する。
注意点
- この page は LangGraph の設計であり、他 framework でも同じ API 名や挙動になるとは限らない。
- `InMemorySaver` の例は分かりやすさのためで、本番向けの永続保存を自動で保証するものではない。
- 承認 UI がきれいでも、`thread_id` の取り違えや non-idempotent な副作用が残っていれば本番事故は防げない。
この記事は役に立ちましたか
公益的に続けるため、役に立った点や読みづらかった点だけを短く送れます。メールアドレスは不要です。