MCP ツールの構造化エラーレスポンスは、CCA-F ドメイン2(Tool Design and MCP Integration、配点比率18%)のタスクステートメント2.2に位置する。Claude Certified Architect Foundations 試験全体でも特にレバレッジの高い章だ。カスタマーサポート解決・マルチエージェントリサーチ・Code Generation・CI/CD・構造化データ抽出・Developer Productivity のすべてのシナリオクラスターに、失敗しうるツールが少なくとも一つ含まれており、試験はそれらの失敗をフラットなテキスト文字列ではなく構造化されたエンベロープとして扱えない受験者を繰り返し失点させる。MCP ツールの構造化エラーレスポンスは、エージェントループが盲目的にリトライしたり、静かに諦めたり、何の是正措置も取らずにユーザーに謝罪したりするのではなく、インテリジェントにリカバリできるようにするための契約である。
本章では、CCA-F 受験者が内面化すべきMCP ツールの構造化エラーレスポンスの全体像を説明する。ツール呼び出しが成功しなかったことを Claude に伝える isError フラグ、失敗の理由を分類する errorCategory タクソノミー、リカバリの判断に情報を与える isRetryable ブール値、そしてエージェントが推論できる人間が読める content 本文。また、アクセス失敗(ツールが質問に答えられなかった)と有効な空の結果(ツールが正しく答えたが「何も一致しなかった」)の境界線を明確にする。この区別を無視するとカスタマーサポートエージェントが壊れる。最後の「練習アンカー」セクションでは、構造化エラーコンテキストがサブエージェントからコーディネーターまでクリーンに伝播しなければならないマルチエージェントリサーチシナリオに語彙を結びつける。
構造化エラーレスポンスが重要な理由 — 静かな失敗ではなくインテリジェントなリカバリを可能にする
MCP ツールを呼び出す Claude エージェントには三つの観察結果がある。ツールが成功して有用なコンテンツを返した、ツールが成功して有効な空の結果を返した、またはツールが失敗した。MCP ツールの構造化エラーレスポンスの役割は、三番目のケースをエージェントにとって解読可能にして、ループの次のイテレーションが適切な行動を取れるようにすることだ。
汎用的なエラー処理は二つの理由で失敗する。第一に、"Operation failed" のような均一な文字列では、Claude がリカバリパスを区別するシグナルが得られない。第二に、isError ブール値がなければ、モデルはプレーンなエラー文字列を有効なデータとして扱い、すべてが成功したかのように続行しかねない。これが、払い戻しツールが権限例外を発生させたにもかかわらず本番エージェントが「払い戻しが処理されました」とユーザーに伝えてしまう仕組みだ。
構造化エラーレスポンスは、Claude に三つの直交する軸を与えることで両方の失敗を修正する。失敗したか(isError)、どの種類の失敗か(errorCategory)、リトライすべきか(isRetryable)。CCA-F のMCP ツールの構造化エラーレスポンスに関するすべてのシナリオベースの問いは、表面の下では、コーディネーターエージェントが人間の介入なしにリカバリできる可能性を最大化する三つのフィールドの組み合わせを選べるかどうかを問うている。
試験はエラーが存在することを知っているかどうかをテストしているのではない。Claude が再試行・中断・ユーザーへの再質問・人間へのエスカレーション・別ツールの選択のどれを取るかを判断できるツールレスポンスエンベロープを設計できるかどうかをテストしている。エンベロープがプレーン文字列なら、これらの判断は一切できず、エージェントは永遠にループするか静かに断念するかのどちらかになる。 出典: https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/handle-tool-calls
MCP ツール結果エンベロープ — content・isError・errorCategory・isRetryable
すべての MCP ツールの呼び出しは、Claude が次のターンで消費するツール結果エンベロープを返す。Messages API ではこのエンベロープはユーザーロールメッセージに添付された tool_result コンテンツブロックであり、Claude Code ではエージェントループにフィードバックされる観察として現れる。MCP ツールの構造化エラーレスポンスにおいて重要な四つのフィールドがある。
content— 人間が読めるペイロード。成功ケースではツールが生成したデータ。エラーケースでは何が問題だったかの説明。isError— ブール値。trueはツール呼び出しが成功しなかったことを意味する。falseまたは省略は成功を意味する。errorCategory— 分類文字列(TRANSIENT・VALIDATION・PERMISSION・BUSINESS・NOT_FOUND・UNKNOWN)。isErrorがtrueの場合のみ使用する。isRetryable— ブール値。trueは即時リトライで成功する合理的な可能性があることを意味する。falseは介入なしのリトライが同じ失敗を生むことを意味する。
isError は MCP ツール結果エンベロープ上のブール値フラグで、ツールの実行が成功したかどうかを呼び出し元エージェントに伝える。isError: true の場合、Claude は content ペイロードをエラーの説明として扱い、その内容をデータとして扱わない。isError が省略または false の場合、Claude は content を成功したツール出力として扱う。このフィールドはリカバリ判断ツリー全体を駆動する主要シグナルであり、これがなければ Claude は正当な空の結果と静かな失敗を区別できない。
出典: https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/handle-tool-calls
content 本文は isError: true の場合でも省略できない。Claude が推論するためのテキストが必要だ。失敗の説明を何も返さずに失敗するツールはエージェントに推測を強いる。これが試験の引っかけ答えが「エージェントが謝罪して何の行動も取らずに会話を終える」という形になる理由だ。
isError フィールド — ツール実行が成功しなかったことを示すブールシグナル
isError はエンベロープの中で最も重要な1ビットだ。「これはデータだ」と「これは失敗の説明だ」の境界だ。適切に設計された MCP ツールは、呼び出し元が要求したセマンティックな答えを生成できなかった場合は常に isError: true を設定し、答えが空であっても成功した場合は false を設定(または省略)する。
isError: true と単に不成功な結果の区別は微妙で頻繁にテストされる。カスタマーサポートエージェントが lookup_order ツールに注文 #12345 を尋ね、その注文が存在しない場合、正しいレスポンスはコントラクトによって異なる。
- ツールのコントラクトが「注文を返すか何も一致しなかったことを知らせる」なら、正しいエンベロープは
isError: false・content: "No order found with ID 12345."だ。これは有効な空の結果だ。 - ツールのコントラクトが「注文を返す」で、データベースが到達不能なためルックアップが完了できない場合、正しいエンベロープは
isError: true・errorCategory: "TRANSIENT"・isRetryable: trueだ。これはアクセス失敗だ。
二つは素朴な HTTP の観点からは似ているが(どちらも404か5xxかもしれない)、エージェントの次のアクションに対して正反対の意味を持つ。この区別を見逃すと、エージェントはすでに正しく答えられたクエリをリトライしたり(トークンとレイテンシの無駄)、静かなデータベース障害を「データなし」として受け入れたりする(会話の中で偽陰性を生む)。
経験則として「ツールは仕事をしたか?」と問え。答えが「はい(結果セットが空でも)」なら isError: false を設定する。答えが「いいえ(ツールはそのコントラクトを果たせなかった)」なら isError: true を設定し、エージェントが次の行動を決定できるよう errorCategory と isRetryable を含める。
出典: https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/handle-tool-calls
errorCategory の値 — TRANSIENT・VALIDATION・PERMISSION・BUSINESS・NOT_FOUND・UNKNOWN
errorCategory は Claude に呼び出しが失敗した理由を伝えるタクソノミーだ。MCP ツールの構造化エラーレスポンスに関する CCA-F の問いは、与えられたシナリオに対して正しいカテゴリーを選べるかどうかに強く依存する。
TRANSIENT
リトライで解消する可能性のある一時的な状態:ネットワークタイムアウト・上流のレート制限・サービス利用不可・一時的なデータベースの競合。通常 isRetryable: true と組み合わせ、エージェントがバックオフを適用することを期待する。
VALIDATION
呼び出し元がツールのスキーマまたはドメイン制約に違反する入力を提供した:不正な日付・無効な通貨コード・最大長を超えるフィールド・意味論的妥当性に欠ける必須パラメーター。isRetryable: false と組み合わせ、エージェントが呼び出しを修正できるよう十分な情報を提供する(違反しているパラメーターとその理由を明示する)。同じ入力をリトライしても同じ結果になる。
PERMISSION
呼び出し元は認証されているが、その操作を実行する権限がない:異なる顧客に紐付いたレコードを読もうとするエージェント・ポリシーによってブロックされたツール呼び出し・必要なスコープを持たない API キー。isRetryable: false と組み合わせる。エージェントは人間にエスカレーションするか・より広いスコープを持つツールに切り替えるか・ユーザーに制限を説明する必要がある。
BUSINESS
入力が技術的に有効で呼び出し元が認証されているにもかかわらず、ドメインレベルのルールが操作を拒否する:払い戻しウィンドウポリシーに違反する払い戻し要求・日次上限を超える送金・フルフィルメントが始まったためキャンセルが不可能になった注文。isRetryable: false と人間が読めるポリシーの説明を組み合わせる。このカテゴリーは VALIDATION と最も混同されやすい。違いが重要なのは、エージェントのリカバリパスが根本的に異なるからだ——ビジネスエラーはポリシーを説明することを要求し、入力を修正することを要求しない。
NOT_FOUND
特定のリソースが要求されたが存在しない。多くのツール設計では NOT_FOUND を通常の空の結果(isError: false)として返すことを好むが、呼び出し元が確定的なシグナルを必要とする場合——例えば先行レコードを必要とする書き込み操作——では明示的な NOT_FOUND エラーの方が静かな空の成功より明確だ。リソースが再試行で現れる可能性がない限り isRetryable: false と組み合わせる。
UNKNOWN
ツールが分類できない失敗のための予備バケット。一時的+オペレーターの注意が必要として扱う:デフォルトで isRetryable: false を設定し、content に存在する診断詳細を含める。ツールが区別できる場合は常に精確なカテゴリーを優先する。UNKNOWN の多用は匂いだ。
errorCategory は構造化された MCP エラーレスポンス上の分類フィールドで、呼び出しが失敗した理由をエージェントに伝える。標準カテゴリーは TRANSIENT(一時的・リトライで解消の可能性あり)・VALIDATION(無効な入力・リトライ前に修正が必要)・PERMISSION(認証されていない・リトライは役に立たない)・BUSINESS(ポリシー違反・リトライや入力変更では修正できない)・NOT_FOUND(リソースが不在)・UNKNOWN(未分類)だ。各カテゴリーは異なるリカバリ戦略を意味するため、特に BUSINESS と VALIDATION を混同すると、永遠にリトライするか行動なしに謝罪するかのどちらかの壊れたエージェントループが生まれる。
出典: https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/handle-tool-calls
isRetryable フィールド — 即時リトライが有益かどうかをエージェントに伝える
isRetryable は「エージェントは再試行すべきか?」というポリシー判断を単一のブール値に落とし込む二次シグナルだ。このフィールドはリトライロジック(バックオフ・ジッター・最大試行回数)の説明ではない。基礎となる失敗が同一の再呼び出しで成功する可能性がある種類のものかどうかの宣言だ。
isRetryable: true が正しい場合
- ネットワークタイムアウト・接続リセット・DNS 障害。
- HTTP 429(レート制限)——レート制限ウィンドウがロールする。
- HTTP 503(サービス利用不可)——上流が回復する可能性がある。
- 一時的なデータベースデッドロック。
isRetryable: false が正しい場合
- あらゆる
VALIDATIONエラー——入力は同一で同一に拒否される。 - あらゆる
PERMISSIONエラー——呼び出し元のスコープは変わっていない。 - あらゆる
BUSINESSエラー——ポリシーエンジンは同じ判決を下す。 - ほとんどの
NOT_FOUNDエラー(リソースが出現する可能性がない限り)。
isRetryable が errorCategory から独立している理由
カテゴリーから再試行可能性への確定的なマッピングはない。上流のリトライ予算をすでに消費した TRANSIENT 失敗は、エージェントが叩き続けないよう isRetryable: false で返すべきだ。非同期に作成されるレコードの NOT_FOUND エラーは合理的にリトライ可能かもしれない。二つのフィールドは独立に保ち、両方を明示的に設定すること。
isRetryable は構造化された MCP エラーレスポンス上のブール値フィールドで、同一のリトライが成功する合理的な確率があるかどうかをエージェントに伝える。true は失敗が環境的(タイムアウト・レート制限・一時的な利用不可)で、バックオフ+リトライが有効なリカバリパスであることを知らせる。false は失敗が決定論的(無効な入力・権限不足・ポリシー違反)で、入力や呼び出し元の認証を変えずにリトライしても同じ結果になることを知らせる。このフィールドは errorCategory と直交する。一つのカテゴリーはコンテキストに応じてどちらの値も生じ得る。
出典: https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/handle-tool-calls
エラーメッセージのコンテンツ — content フィールドの人間が読める説明
構造化エラーエンベロープの content 本文が Claude が実際に読むテキストだ。エージェントが以下のことを行えるよう十分な詳細を提供すべきだ。
- 技術的でない言葉でエンドユーザーに失敗を説明する。
- 別のツール・パラメーターの調整・エスカレーションが必要かどうかを判断する。
- 事後デバッグ中に人間レビュアーが追える追跡記録を残す。
良いエラー content 文字列は、失敗した操作に名前を付け・該当する場合は問題のある入力を特定し・条件が一時的かどうかを述べ・ビジネスルールについてはカスタマーフレンドリーな言語でポリシーを要約する。悪いエラー content 文字列は「Error.」や生の Python スタックトレースだ。
カスタマー向けエージェントの BUSINESS エラーでは、テキストはエンドユーザー向けに明示的に書かれるべきだ。「払い戻しは購入から30日以内のみ対応しております。この注文は47日前でした」は「policy_engine_violation: rule_id=REFUND_WINDOW_EXCEEDED」より無限に役に立つ。
二つの読者原則:content フィールドはエージェント(レスポンスをルーティングしてリカバリアクションを選択できるよう)とエンドユーザー(エージェントがしばしばテキストをそのまま引用するため)の両方を満足させなければならない。十分な具体性を持つ平易な言葉で書き、そのまま引用しても役立つ返信になるようにする。
出典: https://www.anthropic.com/engineering/writing-tools-for-agents
リカバリ戦略マトリックス — isError + isRetryable + errorCategory → エージェントの判断
完全な判断空間は三フィールドのキューブだが、実際に試験シナリオに現れるのは少数の組み合わせだ。マッピングを記憶すること。
| isError | errorCategory | isRetryable | 標準エージェントレスポンス |
|---|---|---|---|
| false | (n/a) | (n/a) | 返された content をデータとして扱い進める(有効な空の結果を含む)。 |
| true | TRANSIENT | true | 指数バックオフを適用してリトライ。ループのリトライ予算で上限を設ける。 |
| true | TRANSIENT | false | リトライ予算が尽きた——人間に報告するか代替ツールにフォールバックする。 |
| true | VALIDATION | false | content のヒントを使って問題のあるパラメーターを修正し、修正された入力でリトライする。 |
| true | PERMISSION | false | より広いスコープを持つツールにエスカレーションするか、ユーザーに認証を求める。 |
| true | BUSINESS | false | content の言葉でユーザーにポリシーを説明する。リトライしない。 |
| true | NOT_FOUND | false | 正しい識別子をユーザーに再度尋ねるか、コントラクトが許す場合は空として扱う。 |
| true | UNKNOWN | false | ログに記録し、オペレーターに報告し、ユーザーにベストエフォートの説明を提供する。 |
このマトリックスの各行は CCA-F の引っかけ選択肢になり得る。試験の役割は、タイムアウト・ユーザー入力・ポリシールールについてのシナリオの手がかりが与えられたとき、あなたが正しい組み合わせを選べるかどうかを確認することだ。
一時的エラーの処理 — isRetryable: true によるトリガーの指数バックオフ
一時的な失敗は典型的なリトライケースだ。エージェントが isError: true・errorCategory: "TRANSIENT"・isRetryable: true を見た場合、正しいループ動作は:
- このツール呼び出しのリトライカウンターをインクリメントする。
- 指数スケジュールにジッターを加えた間隔でバックオフする(例:base × 2^attempt × random(0.5, 1.5))。
- 同一の入力でツールを再呼び出しする。
- リトライ予算が尽きたら、元のエラーを報告するかフォールバックに切り替える。
リトライポリシーはエージェントループに存在し、ツールの中には存在しない。ツールの役割は失敗にラベルを付けてエージェントが判断できるようにすることだけだ。内部でサイレントにリトライするツールはエージェントからの観察と区別できず、ループの観察可能性を壊す。
CCA-F 試験はリトライロジックがどこに存在するかを気にする。ツールは構造化エラーエンベロープを返す。エージェントがリトライポリシーを適用する。一時的な失敗を内部でループするツールはエージェントの観点からは成功した呼び出しと区別できず、エージェントがトークン・レイテンシ・ユーザーに見えるプログレスメッセージを予算管理できなくなる。 出典: https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/overview
バリデーションエラー — パラメーター修正ヒント付きの VALIDATION 返却
バリデーションエラーは呼び出し元がツールのスキーマまたはドメイン制約に違反したときに発生する。良いバリデーションエラーは二つのことをする。
- 問題のあるパラメーターに名前を付ける(例:
"end_date は start_date 以降でなければなりません。受信した end_date=2026-01-15、start_date=2026-02-01")。 - 制約を明示的に述べ、エージェントが準拠するリトライを生成できるようにする。
単に「Bad input.」を返すだけでは不十分だ。エージェントが有効な呼び出しに収束するためのループイテレーションの数は有限であり、実行可能なガイダンスのないイテレーションはすべて無駄になる。
バリデーションエラーはツールレベルでは常に isRetryable: false だ。同一のリトライは同一に失敗するからだ。エージェントはリトライの前に入力を変えることが期待されており、それは別の操作であり同じ呼び出しのリトライではない。
権限エラー — PERMISSION_DENIED はエスカレーションまたは代替パスを知らせる
権限エラーは呼び出し元が既知だが認証されていないことを意味する。一般的な形状:
- カスタマーサービスエージェントが別の顧客に属するレコードにアクセスしようとする。
- Developer Productivity エージェントがユーザーがコミット権限を持たないリポジトリに書き込もうとする。
- マルチエージェントリサーチのサブエージェントがツール許可リスト外の API を呼び出そうとする。
構造化レスポンスは欠けている権限を content で特定し、コーディネーターエージェントが修正策を選べるようにすべきだ。ユーザーに認証を再依頼する・人間にエスカレーションする・より適切なスコープを持つ別のツールに切り替える。isRetryable: false フラグは重要だ——同じ認証情報でのリトライは同一に失敗し、ループイテレーションを無駄にする。
CCA-F の引っかけ選択肢は「指数バックオフでリトライ」を権限エラーへの正しいレスポンスとして提示することが多い。それは決して正しくない。権限エラーは時間の経過で解消しない。isRetryable: false を設定し、タイマーではなく(別のツール・人間へのエスカレーション・ユーザーによる再認証という)分岐シグナルをエージェントに与えること。
出典: https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/handle-tool-calls
ビジネスエラー — ポリシー違反にはカスタマーフレンドリーな説明と retriable: false
ビジネスエラーはほとんどの本番エージェントが壊れる場所だ。「error: REFUND_WINDOW_EXCEEDED」以上の情報を含まない払い戻しツールはエージェントに二つの悪い選択肢しか残さない。リトライ(誤り——ポリシーは同一に拒否する)か汎用的な謝罪(誤り——ユーザーは具体的な説明に値する)だ。
正しい構造化レスポンスは:
{
"isError": true,
"errorCategory": "BUSINESS",
"isRetryable": false,
"content": "払い戻しは購入から30日以内のみ対応しております。この注文(#12345)は47日前であり、払い戻し期間を過ぎています。例外とお考えの場合は、スーパーバイザーへのエスカレーションをご依頼ください。"
}
エージェントは content 文字列をそのままカスタマーに引用でき、丁寧で具体的な説明として読まれる。isRetryable: false フラグは成功できないリトライへのイテレーションの無駄を防ぐ。errorCategory: "BUSINESS" によってコーディネーターが状況を技術的デバッグキューではなくエスカレーションキューにルーティングできる。
これは CCA-F 試験で最も価値の高い単一パターンだ。カスタマーサポート解決シナリオクラスターに明示的に現れ、ポリシーに触れるすべてのシナリオに暗示的に現れるからだ。コミュニティの合格報告はこのパターンを名指しで挙げている。「ビジネスルール違反に対して errorCategory/isRetryable とカスタマーフレンドリーな説明を含む構造化エラーレスポンスを使う。」
アクセス失敗 vs 有効な空の結果 — 最も試験に出る区別
失敗したツール呼び出しと何も返さなかった成功したツール呼び出しはワイヤー上では似ているが、反対のエージェント動作を必要とする。MCP ツールの構造化エラーレスポンスエンベロープがその線を引く。
アクセス失敗
ツールが仕事を完了できなかった:データベースが到達不能、上流 API がタイムアウト、認証が失敗、スキーマが入力を拒否。エージェントはリトライ/中断/エスカレーションを判断する必要がある。
エンベロープの形状:
{
"isError": true,
"errorCategory": "TRANSIENT",
"isRetryable": true,
"content": "注文データベースに到達できません(5秒後にタイムアウト)。"
}
有効な空の結果
ツールは仕事を完了し、答えは正当に「何もない」だった。顧客に未決の注文がない。検索がゼロ件を返した。このアカウントに未解決チケットがない。
エンベロープの形状:
{
"isError": false,
"content": "顧客 #8421 の注文は見つかりませんでした。"
}
二つの形状は反対の意味を持つ。最初のものは「私は質問に答えられなかった。何かしてほしい。」と言う。二番目のものは「私は質問に答えた。答えは空だった。その知識で進んでほしい。」と言う。
アクセス失敗は、ツールがそのコントラクトを果たせず、したがってセマンティックな答えを報告できない場合に発生する(タイムアウト・権限拒否・データベース到達不能・不正な入力)。isError: true に errorCategory と isRetryable シグナルを加えて表現し、エージェントがリトライ・再ルーティング・エスカレーションのどれをするかを判断できるようにする。有効な空の結果は、ツールがそのコントラクトを果たし、答えがたまたま空だった場合に発生する(一致するレコードなし・ゼロ件のリスト・省略可能な値の不在)。isError: false に説明的な content を加えて表現する。二つを混同することは CCA-F 試験で最も頻度の高いアーキテクチャ上の誤りの一つだ。エージェントがすでに正しく答えられたクエリをリトライするか、静かなインフラ障害を正当な「データなし」レスポンスとして受け入れてユーザーに自信を持って誤った答えを伝えることになるからだ。
出典: https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/handle-tool-calls
外部 API エラーのラッピング — HTTP ステータスコードを MCP フィールドに変換する
ほとんどの MCP ツールはサードパーティ API の薄いラッパーだ。ツールの役割は上流のエラー面を Claude が理解する構造化エンベロープに変換することだ。HTTP セマンティクスから MCP フィールドへのおおよそのマッピング:
| 上流シグナル | isError | errorCategory | isRetryable |
|---|---|---|---|
| 200 データあり | false | (n/a) | (n/a) |
| 200 空のリスト | false | (n/a) | (n/a) |
| 400(bad request) | true | VALIDATION | false |
| 401(unauthenticated) | true | PERMISSION | false |
| 403(forbidden) | true | PERMISSION | false |
| 404(not found) | true | NOT_FOUND | false(通常) |
| 409(conflict・policy) | true | BUSINESS | false |
| 422(unprocessable) | true | VALIDATION | false |
| 429(rate limited) | true | TRANSIENT | true |
| 500(server error) | true | TRANSIENT | true(有界) |
| 502/503/504(gateway) | true | TRANSIENT | true |
このマッピングはガイドラインであり、規則ではない。上流セマンティクスを理解するツール作者は再分類を厭わないべきだ。ビジネスルールの競合を表す 409 は BUSINESS に入る。リトライ+再読で解決できるバージョン不一致を表す 409 は TRANSIENT に入る。
やさしい解説: MCP ツールの構造化エラーレスポンス
抽象的なタクソノミーは身近なシステムに置き換えると定着する。三つの類比でMCP ツールの構造化エラーレスポンスの全体像を覆う。
類比1:病院のトリアージ受付
病院の救急外来に入る。トリアージナースは「何かが問題だ」と言うだけでなく、カードに三つの情報を書き留める。問題があるかどうか(isError)、どんな種類の問題か(errorCategory——心臓・整形外科・神経科・行政)、患者は後でまた来れるか今すぐ治療が必要か(isRetryable)。上流の医師はそのカードを読んで具体的な行動方針を選ぶ。入院・今すぐ治療・明日のスケジュール・別の専門医への紹介。
トリアージナースが「患者に問題があります」とだけ書いたなら、医師はすべての患者を一から再診断しなければならない。それが汎用エラー文字列が Claude エージェントに対してやることだ。MCP ツールの構造化エラーレスポンスは、エージェントが正しい緊急度と方向性で行動できるようにするトリアージカードだ。
類比はきれいに対応する:
isError= 「実際に問題があるか?」errorCategory= 「どんな種類の問題か?」(TRANSIENT = 軽症で解消する可能性あり、VALIDATION = 患者が間違った情報を提供した、PERMISSION = この治療に保険が適用されない、BUSINESS = ポリシーでカバーされない、NOT_FOUND = 記録が存在しない、UNKNOWN = さらなる検査が必要)isRetryable= 「患者は同じ情報で後日また来られるか?」content= カードに添付される次の臨床医がコンテキストを理解するための人間が読めるメモ。
類比2:郵便システム
配達員に渡された荷物には四つの運命がある。届く(isError: false、内容は配達されたデータ)。嵐で道が封鎖されて配達不能(TRANSIENT・isRetryable: true ——明日もう一度試みる)。住所が不正で配達不能(VALIDATION・isRetryable: false ——送り主は住所を修正しなければならない)。受取人が受け取りを拒否して配達不能(PERMISSION・isRetryable: false)。税関が品目を禁止して配達不能(BUSINESS・isRetryable: false ——送り主にポリシーを説明する)。
五番目のケースが微妙で重要だ:配達員は正常に配達するが、受取人には受け取るものがない——配達スロットが空、署名が免除された、在宅でドロップOKのアレンジメント。これは有効な空の結果(isError: false・content: "配達済み、署名不要")であり、まったく失敗ではない。「署名なし」を配達失敗として扱うと、すでに完了した配達を配達員がリトライしてしまう——これがアクセス失敗と有効な空の結果を混同したときにエージェントが壊れる仕組みだ。
類比3:厨房のチケットレール
繁忙な厨房はチケットで回る。各チケットは満たされる(isError: false)か、理由を付けてエクスペダイターに戻される。理由が重要だ:食材の在庫切れは TRANSIENT(シェフは明日仕入れる、後で試みる)、注文の誤り(VALIDATION——サーバーが客が「魚」と言ったのに「鶏肉」と書いた、チケットを修正)、客が注文後に断った(ハウスルール次第で PERMISSION/BUSINESS ——リトライ不可)、チケット上の料理がもうメニューにない(NOT_FOUND)。
エクスペダイター——コーディネーター——はリターンチケットのカテゴリーを使って判断する。ラインに戻すか・謝罪して客のテーブルまで持って行くか・マネージャーにルーティングするか。「問題あり」とだけ書かれたチケットはエクスペダイターが每回のリターンを個人的に調査することを強いる。それがスループットを壊す。構造化エラーレスポンスはラインを動かし続ける厨房の慣例だ。
どの類比を使うか
- ルーティングの判断(どのカテゴリーがどのエージェントブランチをトリガーするか)→ トリアージデスク。
- 再試行可能性とアクセス失敗 vs 空の結果の区別 → 郵便システム。
- サブエージェントがコーディネーターに報告するマルチエージェント伝播 → 厨房チケットレール。
試験頻出ワナ — 汎用エラー・再試行の混乱・空の結果の混同
CCA-F はMCP ツールの構造化エラーレスポンスに関する少数のワナパターンを繰り返し狙う。これらを認識すれば、ほとんどの受験者を引っかける3〜5問を拾い上げられる。
ワナ1:均一な「Operation Failed」テキスト
引っかけ選択肢は「Operation failed」や「An error occurred」のような単一エラー文字列を返すことを提案する。これらは安全で保守的に見える。しかし誤りだ。エージェントがリカバリするために必要な三つのシグナル(isError・errorCategory・isRetryable)を取り除くからだ。正しい答えは常に構造を含む。
ワナ2:isRetryable: false はループを終了する意味だ
受験者は isRetryable: false を読んでエージェントループ全体が中断しなければならないと結論づける。それはこのフィールドの意味ではない。isRetryable: false はこの特定の呼び出しと特定の入力が素朴なリトライでは成功しないことを意味する。エージェントはまだ入力を変えたり(VALIDATION の場合)・エスカレーションしたり(PERMISSION の場合)・ユーザーにポリシーを説明したり(BUSINESS の場合)・ツールを切り替えたりできる。ループは続く。防がれるのはリトライだ。
ワナ3:VALIDATION と BUSINESS の混同
期限切れで拒否された払い戻しは、要求が「悪い」ため VALIDATION とラベルしたくなる。そうではない。入力は構文的に有効で認証されている。ドメインポリシーがそれを拒否している。それが BUSINESS だ。BUSINESS のリカバリパスは「ポリシーを説明する」だ。VALIDATION のリカバリパスは「入力を修正してリトライする」だ。混同すると、エージェントが有効な要求を修正しようと永遠にループするか、ポリシーを引用せずに謝罪するかのどちらかになる。
ワナ4:有効な空の結果をエラーとして扱う
ゼロ件を返す検索は成功した呼び出しだ。isError: false・content: "No matches found."。CCA-F シナリオでは引っかけとして isError: true・errorCategory: "NOT_FOUND" を提示することがある。テストはツールが質問に答えたかを知っているかどうかだ。コントラクトが「ゼロ件以上の一致を返す」なら、ゼロは正当な答えだ。
ワナ5:ツール側のリトライがエージェントから失敗を隠す
引っかけは「ツールはエラーを返す前に内部で最大5回リトライする」と提案する。これはリトライ予算をエージェントループから隠し、観察可能性を壊す。リトライロジックはツールからの isRetryable シグナルに基づいてエージェントの中に存在すべきだ。ツールが内部でリトライするのは一つの論理呼び出しの中でのパフォーマンス最適化としてのみ許容される。構造化失敗レスポンスの代替として決してやってはならない。
タスク2.2での最も一般的な CCA-F の誤りは、すべての失敗に均一な「Operation failed」文字列を返すことだ。 ツールが失敗を正確に分類できなくても、エンベロープは isError: true・errorCategory(他に何も当てはまらなければ UNKNOWN)・isRetryable ブール値・エンドユーザーへの状況説明に十分な詳細を持つ content 本文を含めるべきだ。「すべてを汎用エラー文字列でラップする」を選択肢として提示するシナリオは常に誤りだ。三つの構造化フィールドを保持する選択肢を選ぶこと。
出典: https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/handle-tool-calls
練習アンカー — マルチエージェントリサーチシナリオ:コーディネーターリカバリのための構造化エラーコンテキスト
マルチエージェントリサーチシナリオはMCP ツールの構造化エラーレスポンスにとって最も豊かなテスト場だ。エラーがサブエージェントからコーディネーター経由でユーザー向け要約に至るまでクリーンに伝播しなければならないからだ。
典型的な設定
コーディネーターエージェントがリサーチタスクを三つのサブエージェントにファンアウトする。各サブエージェントは独自の MCP ツールセットを持つ。web_search・fetch_url・extract_citations・summarize_source。サブエージェントAの fetch_url がペイウォールにぶつかり isError: true・errorCategory: "PERMISSION"・isRetryable: false・content: "Source returned 403 — paywall requires institutional access." を返す。サブエージェントBの web_search が429にぶつかり isError: true・errorCategory: "TRANSIENT"・isRetryable: true・content: "Search rate limit exceeded, retry after 60s." を返す。サブエージェントCの extract_citations は isError: false・content: "[]" を返す——ソースに正式な引用がなかったため有効な空の結果だ。
コーディネーターが行うべきこと
- サブエージェントA:ペイウォール付きソースをスキップし、最終レポートに制限を記録し、リトライしない。
- サブエージェントB:バックオフを適用してリトライする。リトライ予算が尽きたら、カバレッジの部分性を記録する。
- サブエージェントC:空の引用リストを正当として受け入れて先に進む。サブエージェントに再依頼しない。空のリストを失敗として扱わない。
MCP ツールの構造化エラーレスポンスに関連するすべての CCA-F シナリオ問いは、究極的にはエンベロープが1〜2フィールドだけ異なるときに受験者がこれら三つの反応を区別できるかどうかを問うている。
練習問題テンプレートA — カテゴリー選択
カスタマーサポートエージェントが process_refund ツールを呼び出す。払い戻しは45日前に注文されたものに対してであり、会社のポリシーは30日以内に限定している。正しいエラーエンベロープはどれか?
- (A)
isError: true, errorCategory: VALIDATION, isRetryable: true - (B)
isError: true, errorCategory: BUSINESS, isRetryable: false, content: "払い戻しは購入から30日以内のみ対応しております。" - (C)
isError: true, errorCategory: UNKNOWN, isRetryable: false - (D)
isError: false, content: "Refund not applicable."
正解:(B)。入力は有効で認証されている。ドメインポリシーがそれを拒否している。BUSINESS に isRetryable: false とカスタマーフレンドリーな説明が正しい形状だ。
練習問題テンプレートB — アクセス失敗 vs 空の結果
リサーチサブエージェントが顧客 #4421 の list_open_tickets を呼び出す。顧客は既知で認証されており、オープンチケットがない。正しいエンベロープはどれか?
- (A)
isError: true, errorCategory: NOT_FOUND, isRetryable: false - (B)
isError: true, errorCategory: TRANSIENT, isRetryable: true - (C)
isError: false, content: "顧客 #4421 のオープンチケットは見つかりませんでした。" - (D)
isError: true, errorCategory: UNKNOWN, isRetryable: false
正解:(C)。ツールはそのコントラクトを果たした。答えは正当に空だ。これはアクセス失敗ではなく有効な空の結果だ。
練習問題テンプレートC — コーディネーター伝播
サブエージェントAが fetch_url の最初の試みの後に isError: true, errorCategory: TRANSIENT, isRetryable: true を返す。コーディネーターはサブエージェント呼び出しごとにリトライ予算3を持つ。コーディネーターは何をすべきか?
- (A)リサーチワークフロー全体を中断する。
- (B)失敗を報告する前に残りのリトライ予算までバックオフしつつ
fetch_urlを再呼び出しする。 - (C)バックオフなしで即時リトライする。
- (D)サブエージェントを落として静かにソースをスキップする。
正解:(B)。TRANSIENT + isRetryable: true はバックオフ付きの有界リトライを招く。リトライ予算はコーディネーターの中にあり、ツールの中にない。
MCP ツールの構造化エラーレスポンス よくある質問(FAQ)
MCP ツールレスポンスの isError と isRetryable の違いは?
isError はツール呼び出しがまったく成功したかどうかを Claude に伝えるブール値だ。isError: true の場合、content 本文はデータではなくエラーの説明として扱われる。isRetryable は、失敗した呼び出しの同一のリトライが成功する合理的な可能性があるかどうかを Claude に伝える別のブール値だ。二つは独立している。isError: true には明示的な isRetryable 値が伴う必要がある。カテゴリーだけでは再試行可能性は決まらないからだ(TRANSIENT 失敗は予算が尽きれば再試行不可になるかもしれない。NOT_FOUND はリソースが非同期に作成されていれば再試行可能かもしれない)。CCA-F では、三軸の判断空間を形成するフィールドとして直交して扱うこと。
errorCategory: VALIDATION と errorCategory: BUSINESS をどう使い分けるか?
入力が構文的に有効で呼び出し元が認証されているかどうかを問え。「いいえ、入力がスキーマまたはドメイン制約に違反している」(間違った型・必須フィールドの欠落・範囲外の値)ならカテゴリーは VALIDATION で、エージェントはリトライ前に入力を修正すべきだ。入力が有効で呼び出し元が認証されているがドメインポリシーが操作を拒否した(ウィンドウ外の払い戻し・日次上限を超える送金・フルフィルメント後のキャンセル)ならカテゴリーは BUSINESS で、エージェントはリトライを試みるのではなくユーザーにポリシーを説明すべきだ。混同するとエージェントが有効な要求を修正しようと永遠にループするか、実際のルールを引用せずに謝罪するかのどちらかになる。
ツールはエラーを返す前に内部でリトライすべきか?
いいえ——リトライポリシーはエージェントループの中にあり、ツールの中にない。内部でリトライするツールは Claude からリトライ予算を隠し、ループの観察可能性を壊す。エージェントはトークン・レイテンシ・ユーザーに見えるプログレスメッセージを予算管理できず、全体の時間予算が逼迫しているときにフォールバックに切り替えることもできない。正しいパターンは適切な isRetryable シグナルを含む構造化エンベロープで失敗を報告し、コーディネーターがバックオフしてリトライするかどうかを判断させることだ。内部リトライは一つの論理呼び出し内での単一の基礎となる HTTP リクエストの再試行のような単一の論理的操作内のパフォーマンス最適化として許容されるかもしれないが、全体の操作が成功できないときの構造化失敗レスポンスの返却の代替として決してやってはならない。
アクセス失敗と有効な空の結果をどう見分けるか?
ツールがそのコントラクトを果たしたかどうかを問え。コントラクトが「一致するレコードを返すか何も一致しなかったことを知らせる」で結果が「一致なし」なら、ツールは成功しており正しいエンベロープは説明的な content を含む isError: false(有効な空の結果)だ。コントラクトが「レコードを返す」で、タイムアウト・権限問題・上流障害のためにツールが完了できなかった場合、ツールは失敗しており正しいエンベロープは errorCategory と isRetryable シグナルを含む isError: true(アクセス失敗)だ。二つの形状はワイヤー上で似ているが反対のエージェント動作を意味する。空の結果はデータとして消費されループが進む。アクセス失敗はリカバリ判断ツリーをトリガーする。混同は CCA-F 試験で最も頻繁にテストされるアーキテクチャ上の誤りの一つだ。
isError: true の場合 content フィールドに何を入れるべきか?
エージェント(レスポンスをルーティングしてリカバリアクションを選択できるよう)とエンドユーザー(エージェントがしばしばカスタマー向けの返信でテキストを直接引用するため)の二つの読者を満足させる人間が読めるテキスト。TRANSIENT エラーには基礎となる状態と既知のリトライヒントを。VALIDATION には問題のあるパラメーターとそれが違反した制約を。PERMISSION には呼び出し元が認証されていないことを。BUSINESS には十分な具体性を持つ平易な言葉でポリシーを要約し、引用しても丁寧な返信になるようにする。生のスタックトレース・説明のない内部ルール ID・「Operation failed」のような汎用フレーズはすべて避ける。三つともシグナルを取り除き、エージェントに推測を強いるか汎用的に謝罪させることになる。
マルチエージェントシステムでの構造化エラー伝播はどう機能するか?
コーディネーター=サブエージェントアーキテクチャでは、各サブエージェントの MCP ツール呼び出しはサブエージェント自身に構造化エラーエンベロープを返す。サブエージェントは自身のファーストライン リカバリに責任を持つ——TRANSIENT リトライへのバックオフ適用・VALIDATION への入力修正など。サブエージェントが解決できないエラーはサブエージェント自身のコーディネーターへの結果の一部として上位に伝播する。理想的には errorCategory と isRetryable シグナルを保持し、コーディネーターが情報に基づいた判断(別のサブエージェントへのルーティング・ユーザーへの報告・ワークフローの中断)を下せるようにする。マルチエージェントリサーチシナリオはこの伝播を明示的にテストする。ペイウォールにぶつかったサブエージェントは PERMISSION を十分明確に報告し、コーディネーターがソースをスキップして最終レポートにギャップを記録できるようにしなければならない。クラッシュや静かな省略ではなく。
isRetryable: false はエージェントがループを終了する意味か?
いいえ。isRetryable: false はこの特定の呼び出しとこの特定の入力とこの特定の呼び出し元が素朴なリトライでは成功できないことを意味する。エージェントの選択肢が尽きたことを意味しない。VALIDATION エラーなら、エージェントは入力を修正してリトライすべきだ(別の呼び出し)。PERMISSION エラーなら、エージェントはエスカレーションするか・再認証するか・より広いスコープを持つツールに切り替えるべきだ。BUSINESS エラーなら、エージェントはユーザーにポリシーを説明し代替案を提示すべきだ。ループはすべての三つのケースで続く。防がれるのは同一の失敗した呼び出しの盲目的なリトライだ。CCA-F の引っかけは isRetryable: false へのレスポンスとして「ワークフローを中断する」を提示することが多い——その答えはほぼ常に誤りだ。
- エンベロープフィールド:
isError(bool)・errorCategory(string)・isRetryable(bool)・content(string)——ツールが失敗したとき四つすべて必須。contentはエラー時も必須。 - errorCategory タクソノミー — 6値:TRANSIENT(リトライ可)・VALIDATION(入力修正)・PERMISSION(エスカレーション/ツール切り替え)・BUSINESS(ポリシー説明)・NOT_FOUND(再確認または空として扱う)・UNKNOWN(ログ+オペレーターへの報告)。
- isRetryable マッピング:TRANSIENT →
true;VALIDATION / PERMISSION / BUSINESS → 常にfalse;NOT_FOUND → リソースが非同期に作成されている場合を除いてfalse。 - JSON-RPC エラー構造(JSON-RPC 2.0 上の MCP):エラーオブジェクトは
code(整数)・message(文字列)・data(省略可能)を持つ。MCP はこれをツール結果エンベロープにマッピングする。isErrorが構造ゲートで、errorCategoryがセマンティック分類を運ぶ。 - MCP 予約エラーコード(JSON-RPC 2.0 標準範囲):Parse error
−32700・Invalid request−32600・Method not found−32601・Invalid params−32602・Internal error−32603;サーバー定義エラーは−32099から−32000の範囲を使う。 - ツール呼び出しタイムアウトデフォルト:MCP SDK のデフォルトツール実行タイムアウトは 60秒。コーディネーターは呼び出しごとのデッドラインを設定し、デッドラインが発火したときに TRANSIENT エラーエンベロープを報告すべきだ。ツールが静かにハングするのを許してはならない。
- リトライセマンティクス:リトライロジックはエージェントループの中にあり、ツールの中にない。ツールは再試行可能性を知らせる。エージェントが指数バックオフ(base × 2^attempt × jitter)を適用する。ツール内の内部サイレントリトライはエージェントから予算を隠す。
- アクセス失敗 vs 有効な空の結果:
isError: true+カテゴリー = アクセス失敗(エージェントは行動しなければならない)。isError: false+空のコンテンツ = 有効な空の結果(ループは通常通り進む)。 - BUSINESS vs VALIDATION:BUSINESS → 入力は構文的に有効、呼び出し元は認証されている、ドメインポリシーが拒否。VALIDATION → 入力がスキーマまたはドメイン制約に違反。リカバリが異なる:BUSINESS = ポリシーを説明;VALIDATION = 入力修正後リトライ。
isRetryable: false≠ ループ中断:ループは続く。防がれるのは同一の失敗した呼び出しの盲目的なリトライのみ。
参考資料
- Anthropic Docs — Handle tool calls(tool_result フォーマットとエラーレスポンス):https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/handle-tool-calls
- Anthropic Docs — Tool use overview and the agentic loop:https://docs.anthropic.com/en/docs/agents-and-tools/tool-use/overview
- Model Context Protocol — Introduction:https://modelcontextprotocol.io/introduction
- Model Context Protocol — Build an MCP server:https://modelcontextprotocol.io/docs/develop/build-server
- Anthropic Engineering — Writing tools for agents:https://www.anthropic.com/engineering/writing-tools-for-agents
- Anthropic Docs — Subagents in the Agent SDK(error propagation patterns):https://docs.anthropic.com/en/docs/claude-code/sdk/subagents
- Anthropic Docs — Connect Claude Code to tools via MCP:https://docs.anthropic.com/en/docs/claude-code/mcp
関連 ExamLab 章:ツールインターフェース設計:明確な説明と境界、Claude Code と Agent ワークフローへの MCP サーバー統合、エージェント間のツール配布と tool choice 設定、マルチエージェントシステムにおけるエラー伝播戦略。