プロンプトチェーンでClaudeに自己修正させる3段構成
生成→レビュー→改善を3回のAPI呼び出しに分ける自己修正パターンの実装方法と、Opus 5が持つネイティブな自己修正との違いを示します。
Claudeに下書きを作らせ、その下書きをレビューさせ、レビュー結果を反映して直させる。この3段の流れは、1つのタスクを3回のAPI呼び出しに分けるだけで実装できます。各ステップを独立した呼び出しにすることで、途中の出力をログに残したり、レビューの合否で処理を分岐させたりできるようになります。Claude Opus 5が単体で持つ「自己修正」の挙動とは別物なので、両者を混同すると無駄な指示を重ねてコストを増やすだけになります。
プロンプトチェーンの自己修正パターンとは
プロンプトチェーンの自己修正パターンとは、1つの出力を「生成」「レビュー」「改善」という3回のAPI呼び出しに分けて作る設計です。まず下書きを生成させ、次にその下書きを評価基準に照らしてレビューさせ、最後にレビュー結果を反映して改善させます。この3ステップをそれぞれ別のAPI呼び出しにすることで、途中の出力を確認・ログ・分岐できるようになります。
1回の呼び出しに全部を詰め込む場合と違い、各ステップの出力が独立したレスポンスとして手元に残ります。レビューの結果だけを人が確認して承認するワークフローも、途中のどこかが失敗したときにそのステップだけ再実行する仕組みも、この分割があってはじめて作れます。
前提 — なぜ推論をモデルに任せず呼び出しを分けるのか
Claudeの最新モデルは、adaptive thinkingとサブエージェントのオーケストレーションによって、複数ステップの推論の大部分を内部で処理します。Extended thinkingとAdaptive thinkingの違いで扱ったとおり、思考の深さそのものはモデルが自律的に判断する設計に移っています。それでも、明示的なプロンプトチェーンには別の役割があります。中間の出力を検査したい場合や、特定のパイプライン構造を強制したい場合には、依然として有効です。
「モデルに任せれば済む推論」と「呼び出しを分けて強制したい構造」は別の問題です。前者はモデルの内部処理に委ねてよく、後者は呼び出しの数そのものを設計者が決める必要があります。3段の自己修正パターンが向くのは後者、つまりレビューのステップを独立したAPI呼び出しとして取り出し、その結果を外部から見える形にしたい場合です。
呼び出しを3回に分けることの代償も無視できません。draftの本文をreviewとrefineの呼び出しにそれぞれ埋め込むため、同じテキストを複数回の入力トークンとして送ることになります。1回の呼び出しで完結させる場合に比べ、入力トークンの合計は増えます。検査・分岐・再実行のどれも必要ないタスクにまで3段構成を適用すると、コストだけが増えて得られるものがない設計になります。
「自己修正」が指す2つの別物
ここで注意が必要なのは、「自己修正」という言葉が公式ドキュメント内で2つの別の現象を指していることです。
1つ目は、本記事のテーマであるプロンプトチェーンの自己修正パターン。生成・レビュー・改善を別々のAPI呼び出しに分ける明示的な設計です。
2つ目は、Claude Opus 5がモデル単体で持つ自己修正の挙動です。公式のOpus 5向けプロンプトガイドは、Claude Opus 5が指示されなくても自分の間違いをよく見つけて直すと説明しています。「もう一度確認して」「回答前に再検証して」といった指示は、モデルが既に行っている再確認と重複するだけでコストを増やすため避けるべきだとしています。
この2つを混同すると無駄なコストが発生します。1回のAPI呼び出しの中で「よく確認してから答えて」と念押しするのは、Opus 5では既にモデルがやっていることの重複にすぎません。本当に必要なのは、レビューを別の呼び出しとして取り出し、その結果を外から検査できる形にすることです。念を押すか、呼び出しを分けて検査可能にするかは、目的が違います。
もう1つの違いは、結果が手元に残るかどうかです。モデル単体の自己修正は応答の中で起きるため、外部からはその過程を見られません。プロンプトチェーンのレビューステップは、レビューの結果そのものが1つのAPIレスポンスとして返るので、ファイルに保存する、承認画面に表示する、次のステップに渡すといった扱いができます。品質を上げる手段としては両者は似ていますが、結果を後から扱えるかという点では別物です。
ステップ1: draftを生成する
最初の呼び出しは、通常のタスク実行と同じです。役割(role)を明示すると、レビュー基準との対応が取りやすくなります。
curl https://api.anthropic.com/v1/messages \
-H "x-api-key: $ANTHROPIC_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{
"model": "claude-sonnet-5",
"max_tokens": 4096,
"system": "You are a technical writer producing an internal migration guide for developers.",
"messages": [
{"role": "user", "content": "Write a short guide section explaining how to move a request from budget_tokens to adaptive thinking with the effort parameter."}
]
}'レスポンスのcontentをそのままdraft_textとして保持し、次のステップの入力にします。この時点では検証も修正も行いません。
ステップ2: reviewでdraftを評価基準に照らす
2回目の呼び出しでは、draftと評価基準を両方渡してレビューさせます。プロンプトが指示・コンテキスト・可変の入力を混在させるときは、それぞれをXMLタグで囲むと解釈のズレを減らせます。
review_prompt = f"""
<draft>
{draft_text}
</draft>
<criteria>
- 技術的に正確か(budget_tokensの仕様と矛盾しないか)
- 開発者がそのまま実行できる手順になっているか
- 結論が先に来ていて、冗長な前置きがないか
</criteria>
Review the draft against each criterion above. For each criterion, state pass or
fail and give a one-sentence reason.
"""レビューの呼び出しには、生成の呼び出しとは別のsystemを与えておくと、役割の切り替えがはっきりします。「You are a strict technical editor who evaluates against the given criteria and does not rewrite text.」のように書けば、同じモデルでも「文章を作る」役割から「評価するだけ」の役割へ明確に切り替わります。3ステップぶんの役割を1つのsystem文字列に詰め込む必要はありません。
レビューの合否をその後の処理で分岐条件に使いたい場合は、この呼び出しに構造化出力を組み合わせ、pass / failをJSONの決まった位置に固定します。実装のSDKごとの型定義の書き方はStructured outputsの型定義パターンで比較しています。生成(ステップ1)や改善(ステップ3)と違い、レビューは自由文を作る作業ではなく評価基準への当てはめなので、構造化出力と相性がよいステップです。
ステップ3: refineでレビュー結果を反映する
3回目の呼び出しでは、元のdraftとレビュー結果の両方を渡し、fail判定が付いた項目だけを直すよう指示します。
refine_prompt = f"""
<original_draft>
{draft_text}
</original_draft>
<review_feedback>
{review_result}
</review_feedback>
Revise the draft to address every criterion marked fail in the review feedback.
Leave sections that passed unchanged. Do not introduce new claims that were not
in the original draft or the feedback.
"""「passした項目には触れない」という指示を入れておくと、改善のたびに無関係な部分まで書き直される事態を避けられます。3回の呼び出しのmessages配列は互いに独立しているため、前のステップの会話履歴をそのまま引き継ぐ必要はありません。必要なテキスト(draftとレビュー結果)だけを次のプロンプトに埋め込めば十分です。
使い分け早見表 — 3段チェーンとネイティブな自己修正のどちらを使うか
| 状況 | 向いている設計 |
|---|---|
| 1回の応答の質を上げたいだけで、途中経過は見なくてよい | 向いている設計何もしないか、軽い指示に留める(モデルのネイティブな自己修正に任せる) |
| レビュー結果を人がログで確認したい、承認フローに乗せたい | 向いている設計本記事の3段プロンプトチェーン |
| レビューの合否を次の処理の分岐条件に使いたい | 向いている設計3段チェーン + レビューステップの構造化出力 |
| 生成・レビュー・改善のどこかだけを失敗時に再実行したい | 向いている設計3段チェーン(各ステップが独立した呼び出しなので再実行範囲を絞れる) |
| 「もう一度確認して」と念押ししたいだけ | 向いている設計何もしない(Opus 5では既にモデルが行っている再確認と重複する) |
よくあるつまずき
- レビュー基準を書かずにレビューさせる: 何を評価するかが伝わらず、改善ステップの入力として使えない曖昧なフィードバックが返ってきます。基準は
<criteria>のように箇条書きで明示します - レビューと改善を1回の呼び出しに戻してしまう: 3ステップに分けたのは検査・分岐したいからです。単に品質を上げたいだけなら、そもそも呼び出しを分ける必要はありません
- ループの終了条件を決めない: レビューが「まだ直すべき」と言い続ける限り改善を繰り返すと、ラウンド数が無制限に増えコストが膨らみます。最大ラウンド数を先に決めておきます
- 各ステップのeffortを揃えてしまう: draftとrefineは新しい文章を作るタスクで、reviewは評価基準への当てはめだけです。effortの使い分けに沿って、reviewだけ低いeffortに落とせる余地があります
- Opus 5に「よく確認して」という指示を毎ステップへ書き足す: モデルが既に行っている自己修正と重複するだけで、レビューステップが持つ「外部から検査できる」という本来の目的とは無関係です
ループ回数を制限する実装の骨格
MAX_ROUNDS = 2
def self_correct(task: str) -> str:
draft = generate(task)
for round_index in range(MAX_ROUNDS):
review = review_draft(draft)
if review["overall_verdict"] == "pass":
break
draft = refine(draft, review)
return draftreviewの判定に構造化出力を使っておくと、review["overall_verdict"]のような固定の位置をif文で見るだけでループを止められます。自由文のレビュー結果から「もう直す必要があるか」を毎回パースする実装より事故が起きにくくなります。
まとめ
プロンプトチェーンの自己修正パターンは、生成・レビュー・改善を3回の独立したAPI呼び出しに分けるだけで作れます。分けることで得られるのは、途中の出力を確認・ログ・分岐できることであり、逆に何もしなければ得られないものでもあります。品質そのものを上げたいだけなら、Claude Opus 5のようなモデルはすでに自分の間違いをよく見つけて直すため、念押しの指示を重ねるより何もしない方がコストを抑えられます。3段チェーンが要るのは、レビューの結果を外部のワークフローで使いたい場合に限られます。レビュー基準の明記、終了条件の設定、ステップごとのeffortの調整という3点を押さえておけば、実装そのものは3回のAPI呼び出しを順番につなぐだけで完成します。