← 戻る 閉じたループを形成する相互接続されたギアと配管の青写真線画、圧力計と排出弁付き。

Claude CodeのRalph LoopsにおけるVerifiers、Budgets、Stop Conditions

Ralph loopは3つの要素からなる:タスク、verifier、予算。これが全パターンだ。Geoffrey Huntleyはそれをシンプソンズのキャラクター(物が機能しているかどうかに関わらず進み続ける)にちなんで名付けた。このアナロジーは有効だ。リスクはClaudeが早く停止することではない。リスクは壊れた状態で成功を宣言し、トークン予算を浪費すること、またはその両方だ。この投稿は3つの要素を正確に定義する方法、状況に応じた正しい実装方法を選ぶ方法、条件が実際に満たされたときにループを安全に停止する方法について説明する。agentic development workflowは別の懸念事項であり、この投稿は条件が成立するまでの反復に厳密にスコープされている。

目標、Verifier、予算を定義する

単一のコマンドを書く前に、3つの文を書く。「完了」とはどのような状態か?それを機械的にどのように確認するか?反復にいくら支払う意思があるか?

目標は機械的に検証可能である必要がある。「コードは良い」は目標ではない。「npm testのすべてのテストが成功し、git statusがクリーン」は目標だ。違いは重要である。verifierが観察できることしか評価できないからだ。完了条件が人間が何かを見ることに依存する場合、verifierがない。レビューステップがあり、これら2つのものは同じループの内部にあるべきではない。

Verifierはnot Claude自身の意見だ。これはほとんどの人が間違える部分だ。あるHacker Newsのコメント提供者の言葉を借りれば、「AIが物が機能していると考えている場合、あなたがそれが完了していると考えていなくても、COMPLETEと言う」。モデルが生成したDONEはシグナルであって、verifierではない。本当のverifierは外部プロセスだ:テストランナー、リンター、期待されたステータスコードを返すライブエンドポイントに対するcurl。各反復後に実行され、決定的な真偽値を生成する。それを最初に構築する。

予算はセーフティバルブだ。実際に使う意思がある数字を選ぶ。frankbria/ralph-claude-code コミュニティ実装は、ヒューリスティック完了指標(2つ以上)とモデルのRALPH_STATUSブロック内の明示的なEXIT_SIGNAL: true の両方を終了前に要求する。この二重条件設計は、単一シグナルが信頼できないからだ。最初の実行では--max-iterationsは保守的にする。ループが実際にどこまで進むかを見た後に上げることができる。

率直に言えば、実行前のセットアップは以下に答える必要がある:

  • タスクが本当に完了したときだけ、終了コード0を返すshellコマンドは何か?
  • 許可する反復の最大数は何か?
  • 後で検査できるように、反復結果を記録するファイルまたはログは何か?

ループ実装を選択する

Claude Code 2.1は、プラグインなしでほとんどのRalphユースケースをカバーする3つの組み込みプリミティブを搭載している。Awesome Claude ガイドは3つすべてを記載している。

2つのパス(1つは開いており、もう1つは遮断弁付き)を持つフォークされた配管の青写真線画(ループ実装の選択肢を表す)。
  1. /goal は、条件が検証されるまでターン全体で作業を続ける。Ranjan Kumarの投稿によると、デフォルトではHaikuである小さいモデルを使用して、各ターン後にセッショントランスクリプトを読み、1つの質問に答える:目標は達成されたか?いいえの場合、Claudeは別のターンを取る。はいの場合、ループがクリアされる。
  2. /loop は、プロンプトを固定またはペースに合わせた間隔で再実行します。Esc で停止。ポーリングタスクに便利です。
  3. /batch は、1 つの大きな変更を 5~30 個の並列ワークツリーエージェントに分散させます。まったく別のもので、単一の限定的なタスクには向きません。

その次がプラグインパスと生の bash ループです。実際に仕事に影響を与える方法で異なります。

プラグイン(ralph-wiggum@claude-plugins-official またはコミュニティフォーク)は、停止フックを使用して単一セッション内で実行されます。Claude が終了しようとすると、フックが中断して再度プロンプトを入力します。コンテキストは反復を通じて蓄積されます。便利ですが、15 回目の反復までには、コンテキストウィンドウが以前のすべての試行の残骸を抱えていることになり、新しいターンの品質が低下する可能性があります。

生の bash アプローチでは、PROMPT.md while ループ内の claude -p にパイプすると、毎回まったく新しいプロセスが生成されます。Steve Kinney が指摘するように、「各 claude -p の呼び出しは、完全にクリーンなコンテキストウィンドウを取得します。これはコンテキストの劣化を避けるために意図的に新しく始めるという手法の全ポイントです」。トレードオフは、試みられたことの暗黙的な記憶を失うことなので、PROMPT.md とタスク状態ファイルが反復間ですべてのコンテキストを明示的に保持する必要があります。

どちらを選びますか?タスクが短い場合(10 回未満の反復が予想される)でコンテキストが管理可能であれば、ターンキャップ付きの /goal が最も摩擦が少ないオプションです。タスクが長いか、コンテキスト品質が懸念される場合は、フレッシュコンテキスト bash ループがより信頼性があります。tests and AI coding tools の記事では、テストスイートを構成して、検証者がどちらの方法でもクリーンに実行できるようにする方法が説明されています。

1 つのタスクを限定的な反復で実行する

/goal プリミティブを使用した限定的なタスクの例示的な設定です:

/goal npm test のすべてのテストが合格し、git status がクリーン、または 20 ターン後に停止

この 1 行で Claude に検証可能な終了条件とハードキャップを提供します。Haiku 評価者は各ターン後にトランスクリプトを読み、両方の条件をチェックします。or stop after 20 turns 句は予算のガードレールです。

bash ループアプローチの場合、Geocodio チームの構造は良いモデルです。彼らは JSON ファイル(単純な prd.json)を使用し、各タスクに「passes」: false フィールドがあります。各反復は passes: false の最優先度ストーリーを見つけ、実装し、検証者を実行し、成功時にフラグを true に切り替えます。すべてのストーリーが passes: true になると while ループは終了します。彼らの記事は受け入れ基準の構造だけで読む価値があります。

フレッシュコンテキスト bash ループの番号付きフローは次のようになります:

  1. 現在のタスク、検証者コマンド、パス/失敗ログパスを使用して PROMPT.md を記述します。
  2. while ループを開始し、PROMPT.md を claude -p にパイプします。
  3. Claude が指示を読み、1 つの作業単位を実行し、git にコミットします。
  4. 検証者が実行されます。終了コード 0 は合格、その他は不合格を意味します。
  5. 結果(反復番号、合格/不合格、利用可能な場合はトークンコスト)をファイルに記録します。
  6. すべてのタスクが合格した場合、停止シグナルを記述して中断します。そうでない場合は、ステップ 2 に戻ってループします。

各反復を 1 つの作業単位に保ちます。ループごとにやりすぎようとするのは、検証者がクリーンに評価できない半完成の状態に終わる方法です。

進捗なしと虚偽の完了を検出する

無限ループよりもはるかに一般的な 2 つの失敗モードがあります:ループが反復全体で進捗を示さず、モデルが破損した状態で成功を宣言します。

進捗の非検出にはイテレーションNとイテレーションN+1を通じて何か具体的なものを比較する必要があります。git diffが最もシンプルなシグナルです。検証器がパスしなかったイテレーション後にgit diff HEAD~1が空の場合、ループは空転しています。3回のイテレーションを費やして変化を期待するのではなく、すぐにそれを明らかにするべきです。

誤った完了はより複雑です。モデルはDONE、COMPLETE、またはEXIT_SIGNAL: trueを、実際の検証器が0以外の終了コードを返す状況で出力します。frankbriaの実装の二重条件チェック(複数のヒューリスティック指標と明示的なシグナル)は妥当な緩和策です。しかし、より鋭い修正はこうです:モデルの出力だけに基づいてループを終了させないこと。検証器スクリプトはモデルが何を言おうと関係なく実行され、検証器が失敗すればループは続行します、以上です。

関連する落とし穴に気をつけてください:検証器自体が誤検知を返すこと。テストスイートに基本的なバグが修正されていなくても時々パスするテストが含まれていると、モデルが原因でさえない誤った完了が発生します。それは次のセクションです。

不安定なテストと検証器の失敗に対処する

不安定なテストはあらゆる自動ループの敵です。80%の頻度でパスするテストは、最終的に20%でパスすべきでないときにループを終了させてしまいます。各イテレーションがトークンを消費するため、誤った終了とその後の再実行は費用がかかります。

緩和策は複雑ではありませんが、事前の作業が必要です:

  • 検証器コマンドを連続3回実行してからパスを信頼してください。3回中1回失敗したら、失敗として扱います。
  • 「仕事は完了したか」テストと「環境は機能しているか」テストを分離してください。ネットワーク依存テスト、タイミングに敏感なアサーション、外部状態を必要とするものはループ終了を制御する検証器に含めないでください。
  • すべての検証器実行とその出力をログに記録してください。ループが停止して何か問題に見えたら、最終イテレーションの完全な検証器出力が必要です。終了コードだけではありません。

検証器自体が失敗する場合(クラッシュ、タイムアウト、テスト失敗ではない予期しない終了コードを返す)は、ループの継続ではなくループの停止として扱ってください。壊れた検証器を通じてイテレーションを続けようとしても、評価できないイテレーションが生成されるだけです。

Claude Codeフックはセッションライフサイクルの特定の時点でスクリプトをアタッチできます。Claude Codeフックガイドはメカニズムについて詳しく説明しています。Ralphループの場合、関連するフックはClaudeが終了しようとするときに発火するものです:それを傍受し、検証器を実行し、検証器がパスした場合のみ終了を許可します。プラグインパスを使用している場合、これはすでに配線済みです。bashループを使用している場合、終了の決定はフックではなくシェルスクリプトで発生します。

コストを記録して安全に停止する

ループが終了する前に各イテレーションのコストを把握する必要があります。リアルタイムで正確な数字は不要ですが、イテレーション番号、検証器の結果、その後の支出を推定するのに十分なトークン情報を記録するログファイルが必要です。

Alibaba CloudのRalphループに関するコミュニティ投稿は、あらゆる実装に組み込む価値がある3つの停止条件を指摘しています:

  • 成功:検証器が0を返し、すべてのタスクがpasses: trueを持つ。
  • 進捗なし停止:git diffなしと検証器の改善なしの連続2回以上のイテレーション。
  • 予算枯渇:検証器の状態に関係なく、イテレーションカウンターが--max-iterationsに達する。

予算枯渇は失敗モードではなく、設計された停止です。トリガーされたら、ループはパスしたもの、パスしなかったもの、最後のイテレーションが試みたものの要約を書き込みます。これにより、マニュアルレビューまたは改定されたプロンプトでの新しいループへのクリーンなハンドオフが得られます。

明示的に構築すべき点:「ループは成功したため停止した」と「ループはキャップに達したため停止した」の区別。ターミナルに戻ってきて「ループはイテレーション20で停止した」と表示されたら、どちらなのかを知る必要があります。ログファイルの単一フラグ、STOP_REASON: BUDGET_EXHAUSTEDまたはSTOP_REASON: SUCCESSで十分です。

この種の作業を大規模に実施している、または手作りスクリプトではなくマネージドセットアップが必要な場合、エージェント工学の作業は適切な可観測性を備えた本番グレードループセットアップの外観をカバーしています。

FAQ

`/goal`は実際にはRalphループなのか、それとも別の何かなのか?

同じ原則(条件が成立するまで反復)を共有しますが、アーキテクチャは異なります。/goalは単一の永続的なセッション内で実行されます。古典的なRalph bashループは各イテレーションで新しいプロセスを生成します。Ranjan Kumarが文書化しているように、/goalは別のHaikuモデルを使用して各ターン後のトランスクリプトを評価します。bashループは何も評価しません。シェルスクリプトがチェックを実施します。どちらも有効です。コンテキスト蓄積がタスクに問題かどうかに基づいて選択してください。

モデルの`DONE`出力自体を検証器として使用できますか?

いいえ。モデルの出力は1つの入力として使用できるシグナルですが、それだけでは終了条件にはなりません。モデルはタスクが完了したと判断したときに完了マーカーを出力しますが、それは実際にシステムが完了したかどうかとは別です。モデルが生成したシグナルには、システムの実際の状態をチェックする外部コマンドを組み合わせてください。

Claude Code が実行中にコンテキストをコンパクト化したら、ループにどのような影響が出ますか?

永続セッションループ(プラグインまたは /goal)では、コンテキストが長くなると自動的にコンパクト化が行われ、そのコンパクト化の品質は一貫性がありません。あるHacker Newsのコメント者は「Claude Code のコンパクト化は品質が低いため、数ターンごとに履歴を完全にクリアするのと変わらない」と指摘しました。新規コンテキストのbashループはこれを完全に回避します。各イテレーションが新規に開始するからです。プラグインパスを使用していて長時間のジョブを実行する場合は、コンパクト化ポイント後の出力品質の低下に注意してください。

各イテレーションの作業単位はどの程度小さくするべきですか?

意味を持たせられる限り、できるだけ小さくしてください。1イテレーション1タスクが正しい考え方です。Geocodioのアプローチ(prd.jsonから1ストーリーあたり1ループ)とHacker Newsのコメント者の説明(「最も重要なタスクを選び出して完了させ、ループを終了する」)の両方が同じ答えを指しています。小さく検証可能なチャンクは、大きく野心的なイテレーションよりもはるかに信頼性が高いのです。

プラグインは本当に必要ですか?

ほとんどのタスクではいいえ。組み込みの /goal プリミティブと、ターン数の制限で一般的なユースケースをカバーできます。プラグイン(ralph-wiggum@claude-plugins-official または frankbria/ralph-claude-code)に手を出すのは、停止フック傍受の動作や、これらの実装が提供する二重条件終了ロジックが具体的に必要な場合だけです。チュートリアルで見たというだけでプラグインをインストールしないでください。

このパターン全体で最も重要な注意点:モデルが生成した完了シグナルは検証者ではありません。外部チェックを最初に、他のすべてのことより先に構築し、その他のすべての決定がそれに従うようにしてください。

← 戻る