2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

図解で解説!Claude Certified Architect (CCAR-F) 試験ガイド

2
Posted at

本記事について

Claude Certifi Architect – Foundations(CCA-F)の試験範囲について、筆者が個人的な学習の一環として理解を整理・共有することを目的に執筆したものです。

記載内容は、公開されている試験ガイド(Version 0.2 Last Updated: June 30 2026)や公式ドキュメントを参考に、筆者自身の解釈や経験を交えながら解説したものです。そのため、試験の出題内容やAnthropicの公式見解を保証するものではありません。

認定試験を受験される方は、必ず最新の公式ドキュメントや試験ガイドをご確認ください。また、本記事に誤りや改善点などがありましたら、コメント等でご指摘いただけると幸いです。

【補足】
普段はOpenAI API(GPT)を使ったサービスの開発を行なっており、ClaudeはCoworkを検証用に少し触った程度ですが、この学習用メモを何度も繰り返し復習し、合わせてAnthropicの公式のExam Guideの英文も繰り返して熟読することで(英語が苦手な筆者でも)無事一発合格(800点代前半)することができました。

Domain 1: Agentic Architecture & Orchestration


1.1 Design and implement agentic loops for autonomous task execution

Claude API を利用してエージェントを実装する場合、最も重要な考え方の一つが Agentic Loop(エージェントループ) です。

Agentic Loop とは、Claude が状況に応じてツールを呼び出し、その実行結果を踏まえて次の行動を自律的に判断しながらタスクを進める仕組みです。従来の「決められた順番でツールを実行するワークフロー」と異なり、Claude 自身が次に何をすべきかを推論する点が大きな特徴です。


Agentic Loop のライフサイクル

Agentic Loop は、次の流れで繰り返し実行されます。

ポイントは、Tool の実行結果を Conversation History に追加してから、Claude に再度リクエストを送ることです。Claude は会話履歴全体をコンテキストとして推論するため、新しく得られた Tool の実行結果を会話履歴へ追加しなければ、次の判断に利用できません。


stop_reason がループ制御の判断基準

Agentic Loop の終了条件は、Claude が返す stop_reason だけで判断します。

stop_reason 意味 次の処理
tool_use Tool の実行が必要 Tool を実行し、結果を Conversation History に追加してループ継続
end_turn Claude の処理が完了 ループ終了し、ユーザーへ回答を返す

つまり、stop_reason == "tool_use" ならループを続け、stop_reason == "end_turn"なら終了します。

その他、Stop_reasonには以下の5種類があります。

stop_reason 意味 対応
max_tokens 指定した max_tokens に達した max_tokens を増やすか、続きを生成する
stop_sequence 指定した stop_sequences に一致 停止したシーケンスを確認する
pause_turn サーバーツール(Web検索など)の反復上限に達した Assistant応答をそのまま送り返して続きを実行する
refusal Claudeが安全上の理由などで応答を拒否 stop_details を確認し、必要ならフォールバックする
model_context_window_exceeded モデルのコンテキストウィンドウ上限に達した コンテキストを削減・要約して再実行する

Tool 実行結果を Conversation History に追加する理由

例えば、ユーザーが、「今日の東京の天気を教えて」と質問し、Claude が Weather Toolを呼び出した時の実行結果が、

{
"temperature": 31,
"condition": "Sunny"
}

だった場合、この結果を Conversation History に追加してから、再度 Claude に渡すと、Claudeは 、「東京は現在31℃で晴れです。」と自然な文章を生成できます。もし Tool の実行結果を Conversation History に追加しなければ、Claude は Tool の結果を知らないため、適切な回答を生成できません。


モデル主導の意思決定とは

Agentic Loop の特徴は、Claude 自身が次の行動を判断すること です。

例えば、

住所を取得

郵便番号を取得

配送日を計算

という順番は、プログラム側で固定するのではありません。

Claude が、

  • 必要な Tool
  • 呼び出す順番
  • 必要なら追加の Tool

を状況に応じて決定します。つまり、開発者は「ループ」を実装し、Claude は「意思決定」を担当 します。


避けるべきアンチパターン

Agentic Loop では、ループ終了の判断を stop_reason 以外に依存してはいけません。

アンチパターン 問題点 推奨方法
「I've completed the task」など自然言語を解析して終了判定する モデルの表現は毎回変わるため誤判定する可能性がある stop_reason を利用する
Assistant の返答内容を見て終了と判断する Tool 呼び出し前に完了らしい文章を返す場合がある stop_reason を利用する
最大ループ回数を主要な終了条件にする 正常な処理でも途中で終了してしまう stop_reason を利用し、最大回数は安全装置としてのみ利用する
あらかじめ Tool の実行順序を固定する Claude の推論能力を活かせない Claude に Tool の選択を任せる

1.1章のまとめ

ポイントは以下のとおりです。

  • Agentic Loop は Claude → Tool → Claude を繰り返す制御構造である
  • ループの継続・終了は stop_reason だけで判断する
  • Tool の実行結果は Conversation History に追加してから、Claude に再度渡す
  • Claude は会話履歴全体を利用して次の行動を推論する
  • 開発者はループ制御を実装し、Claude は次に実行すべき Tool を自律的に判断する
  • 自然言語の解析や固定的な終了条件に依存する実装はアンチパターンである

Agentic Loop を正しく実装することで、Claude はツールの実行結果を踏まえながら自律的に推論を続け、柔軟で拡張性の高い AI エージェントを実現できます。

1.2 Orchestrate multi-agent systems with coordinator-subagent patterns

大規模な調査や複雑なタスクでは、1つのエージェントだけですべてを処理するよりも、複数のエージェントが役割を分担した方が効率的です。Claude Code や Agent SDK では、このような構成を、 Coordinator-Subagent Pattern(コーディネーター・サブエージェントパターン) と呼びます。


Hub-and-Spoke アーキテクチャ

マルチエージェントでは、Coordinator(コーディネーター) が中心となり、すべてのサブエージェントを管理します。

重要なのは、サブエージェント同士は直接通信しないという点です。すべての通信は Coordinator を経由します。Coordinator は、

  • タスク分解
  • エージェント選択
  • 結果集約
  • エラーハンドリング
  • 情報ルーティング

を担当します。


サブエージェントは独立したコンテキストで動作する

サブエージェントは、Coordinator の Conversation History を自動的には引き継ぎません。つまり、各サブエージェントは、独立したコンテキスト(Isolated Context) で実行されます。

そのため、Coordinator は、必要な情報だけをサブエージェントへ渡し、返ってきた結果を再度統合する役割を持ちます。


Coordinator は必要なサブエージェントだけを起動する

良い Coordinator は、毎回すべてのサブエージェントを呼び出しません。例えば、

東京都のAI活用事例を調査してください

なら

  • Search Agent
  • Summarization Agent

だけで十分かもしれません。一方、

このPythonコードの設計を改善してください

なら

  • Code Agent

だけを起動すれば十分です。つまり、Coordinator は、問い合わせ内容を分析し、必要なサブエージェントだけを動的に選択 します。


調査範囲を適切に分担する

複数の Search Agent を利用する場合でも、全員に

OpenAIについて調査してください

と依頼すると、ほぼ同じ結果になります。良い設計では、役割を分けます。

Agent 担当
Search Agent A 公式ドキュメント
Search Agent B Academic Paper
Search Agent C GitHub
Search Agent D News

このようにすることで、重複を減らし、網羅性を高められます。


Iterative Refinement Loop(反復改善ループ)

Coordinator は、サブエージェントの結果をまとめて終わりではありません。結果を評価し、不足している情報があれば、追加調査を指示します。

この反復改善ループによって、より品質の高い回答が得られます。


Coordinator を経由する理由

すべてのコミュニケーションを Coordinator 経由にすることで、次のメリットがあります。

メリット 内容
可観測性(Observability) すべてのコミュニケーション履歴を追跡できる
エラーハンドリング エラー処理を一元管理できる
情報管理 サブエージェント間の不要な情報共有を防げる
セキュリティ 必要最小限の情報だけを各エージェントへ渡せる
制御性 Coordinator が全体の実行フローを管理できる

過度なタスク分解に注意する

Coordinator は、タスクを細かく分割しすぎてもいけません。例えば、

AI市場について調査

を、

  • OpenAI
  • Anthropic
  • Google
  • Microsoft
  • NVIDIA
  • AWS
  • Azure

のように細かく分割しすぎると、市場全体の俯瞰が失われ、重要な情報を見落とす可能性があります。タスク分解は、網羅性と効率のバランスが重要です。


1.2章のまとめ

ポイントは以下の通りです。

  • Coordinator が Hub となる Hub-and-Spoke アーキテクチャを採用する
  • サブエージェントは独立したコンテキストで動作し、Conversation History は自動共有されない
  • Coordinator は問い合わせ内容を分析し、必要なサブエージェントだけを動的に起動する
  • 調査範囲を適切に分担し、重複を最小限に抑える
  • Coordinator は結果を統合するだけでなく、不足情報を評価し、必要に応じて反復改善ループを実行する
  • すべての通信を Coordinator 経由にすることで、可観測性・エラーハンドリング・情報管理・制御性を実現できる

Coordinator-Subagent パターンは、Claude Code や Agent SDK における代表的なマルチエージェント構成です。Coordinator が全体を制御し、各サブエージェントが専門分野に集中することで、高品質かつ拡張性の高い AI エージェントシステムを構築できます。

1.3 Configure subagent invocation, context passing, and spawning

前章1.2では、Coordinator と SubAgent によるマルチエージェント構成について説明でした。本章では、実際にサブエージェントをどのように起動し、必要な情報を渡すのか について説明しています。
Claude Code や Agent SDK を利用する上で最も重要なノウハウの一つです。


Task Tool がサブエージェントを起動する

Claude Code では、サブエージェントは Task Tool によって生成(Spawn)されます。また、Coordinator がサブエージェントを起動するには、 allowedToolsTask を含める必要があります。

Task Tool が利用できなければ、Coordinator は SubAgent を起動できません。


AgentDefinition の設定

各サブエージェントは、AgentDefinition によって定義されます。代表的な設定項目は次のとおりです。

項目 説明
Description エージェントの役割
System Prompt 行動方針
allowedTools 使用できる Tool

例えば、Search Agent は、

AgentDefinition

Description:
  Search official documentation

System Prompt:
  Search only trusted sources.

allowedTools:
  - WebSearch

Analysis Agent は、

AgentDefinition

Description:
  Analyze collected documents

System Prompt:
  Extract key findings objectively.

allowedTools:
  - Read

のように、役割ごとに設定を分けます。


サブエージェントは親のコンテキストを引き継がない

重要なのは、サブエージェントは Coordinator の Conversation History を自動では共有しないという点です。

必要な情報は、毎回プロンプトに含めて渡す 必要があります。


前段エージェントの結果はそのまま渡す

例えば、Search Agent が

  • Web検索
  • PDF解析

を実施したとします。

その結果を、Coordinator が Synthesis Agent に渡します。

このとき、単に 「要約してください」ではなく、検索結果や分析結果を、そのままプロンプトへ含める ことが推奨されています。


構造化データでコンテンツとメタデータを分離する

Agent 間で情報を渡す場合は、文章だけを渡すのではなく構造化データを利用 します。

例:

{
  "content":
    "Claude Code supports Task Tool.",

  "metadata": {
      "source":
        "https://...",
      "document":
        "Agent SDK Guide",
      "page": 42
  }
}

こうすることで、

  • 出典
  • URL
  • ページ番号

などの Attribution(出典情報)を維持できます。


サブエージェントは並列起動する

Coordinator は、複数ターンに分けて Task を実行するのではなく、1回のレスポンスで複数の Task Tool を返します。

これにより、並列実行が可能となり、処理時間を短縮できます。


Coordinator は「手順」ではなく「目的」を伝える

悪い例として、

①検索してください
②分析してください
③要約してください

のように、細かく手順を書いてしまうことです。

一方で良い例は、

目的:
OpenAI API の最新仕様を整理してください。
 
品質基準:
 
・公式情報を優先
 
・重複を除去
 
・出典を保持
 
・重要な変更点を抽出

ように、調査目標と品質基準 だけを指定します。このようにすると、サブエージェントは、状況に応じて最適な方法を判断できます。


Forkベースのセッション管理

Fork は、現在の分析結果を基準として、別のアプローチを試す仕組みです。

flowchart TD
Base[Current Analysis]
 
Base --> A[Approach A]
Base --> B[Approach B]
Base --> C[Approach C]

例えば、ある設計について、

  • 性能重視
  • 保守性重視
  • セキュリティ重視

という3つの方向性を、同じ分析結果から並列に検討できます。Fork により、元のセッションを壊すことなく、複数の案を比較できます。


1.3章のまとめ

ポイントは次の通りです。

  • サブエージェントは Task Tool によって起動される
  • Coordinator がサブエージェントを起動するには allowedToolsTask が必要である
  • AgentDefinition には Description・System Prompt・allowedTools を定義する
  • サブエージェントは親エージェントの Conversation History を共有しないため、必要な情報は毎回プロンプトへ明示的に渡す
  • Agent 間では構造化データを利用し、コンテンツとメタデータ(URL・文書名・ページ番号など)を分離することで出典情報を維持できる
  • Coordinator は 1 回のレスポンスで複数の Task Tool を返し、サブエージェントを並列起動する
  • Coordinator は細かな手順ではなく、調査目標と品質基準を指示することで、サブエージェントの自律性を活かせる
  • Fork ベースのセッション管理を利用することで、同じ分析結果から複数のアプローチを安全に比較・検討できる

Task Tool、AgentDefinition、Context Passing は、Claude Code のマルチエージェント設計の中核となる考え方です。これらを正しく理解することで、柔軟かつ拡張性の高いマルチエージェントシステムを構築できます。

1.4 Implement multi-step workflows with enforcement and handoff patterns

AIエージェントは柔軟に推論できるが、 「必ず守らなければならない手順」まで LLM の判断に任せるべきではありません。

例えば、

  • 本人確認が終わる前に返金してはいけない
  • 権限確認前に個人情報を表示してはいけない
  • 承認前に送金してはいけない

このような処理は、 プログラム側で必ず保証(Enforcement)する必要があります。

本章では、マルチステップワークフローにおける Enforcement と Human Handoff の設計について説明しています。


Prompt による指示と Programmatic Enforcement の違い

LLM に「本人確認を行ってから返金してください」と指示することはできます。しかし、LLM は確率的に動作するため、 プロンプトだけでは、失敗する可能性をゼロにすることはできません。一方、Programmatic Enforcement では、アプリケーション側で必ず条件を満たしていることを確認します。

重要なのは、 ワークフローの制御はプログラムが担当し、Claude は推論を担当する、という役割分担です。


Prerequisite Gate(前提条件チェック)

例えば、返金処理で、

get_customer

本人確認

process_refund

という順番を守る必要があるとします。これを Claude の判断だけに任せるのではなく、プログラム側で制御します。

例えば、

customer = get_customer()

if not customer.verified:
    raise PermissionError()

process_refund(customer.id)

のように、後続処理を実行する前に、必ず前提条件を確認します。このような仕組みを Prerequisite Gate と呼びます。


複数の問い合わせは並列に調査する

ユーザーから、「注文が届かず、請求金額もおかしいので返金してください。」という問い合わせがあったとします。これは、

  1. 配送状況(Shipping)
  2. 請求内容(Billing)
  3. 返金条件(Refund)

という、複数の問題を含んでいます。Coordinator は、これらを個別に調査します。

それぞれを並列に調査した後に、Coordinator が統合した回答を作成します。


Human Handoff(人への引き継ぎ)

すべての問題を LLM が解決できるとは限りません。例えば、

  • 法的判断
  • 特別な返金
  • クレーム対応

などは、人へ引き継ぐ必要があります。その際、担当者は LLM の会話履歴を見られないこともあります。そのため、LLM は 構造化された引き継ぎ情報 を作成します。

引き継ぎ内容には、次のような情報を含めます。

項目 内容
Customer ID 顧客ID
Root Cause 根本原因
Refund Amount 返金額
Recommended Action 推奨対応
{
  "customer_id": "12345",
  "root_cause": "Duplicate charge",
  "refund_amount": 12000,
  "recommended_action":
    "Approve refund"
}

このような構造化データにすることで、人間の担当者は会話履歴を見なくても状況を理解できます。


なぜ構造化データが重要なのか

自然言語だけでは、重要な情報が抜けたり、担当者によって解釈が変わる可能性もあります。一方、構造化データなら、

  • 必要項目の漏れを防止
  • システム間連携
  • チケットシステムへの登録
  • CRM との連携

などが容易になります。そのため、Human Handoff では、構造化データ形式が推奨されています。


1.4章のまとめ

ポイントは次の通りです。

  • Prompt による指示だけでは、必ず守るべき処理順序を保証できない
  • 人確認や権限確認などの前提条件は、Programmatic Enforcement(プログラムによる強制実行)で保証する
  • Prerequisite Gate により、前提条件を満たすまで後続処理を実行させない
  • 複数の問い合わせは個別に分解し、共有コンテキストを利用して並列に調査した後、Coordinator が統合する
  • 人へエスカレーションする際は、Customer ID・Root Cause・Refund Amount・Recommended Action などを含む構造化された Handoff Summary を作成する

AI エージェントの柔軟な推論能力は非常に強力ですが、金融・医療・行政など高い信頼性が求められるシステムでは、 「LLMに任せる部分」と「プログラムで必ず保証する部分」を適切に分離することが、安全で信頼性の高いワークフロー設計の鍵となります。

1.5 Apply Agent SDK hooks for tool call interception and data normalization

AIエージェントでは、ClaudeがToolを選択し、外部システムから情報を取得したり、業務処理を実行したりします。しかし、実務では次のような制御が必要になります。

  • 500ドルを超える返金を自動実行させない
  • 異なるMCP Toolから返される日時形式を統一する
  • 数値のステータスコードを意味の分かる文字列に変換する
  • Toolの実行結果から不要な情報や機密情報を除去する

このような処理を実現する仕組みが Hooks です。Claude CodeのHooksは、Claude Codeのライフサイクル上の特定のタイミングで自動実行される、ユーザー定義のコマンドやHTTPエンドポイントなどです。LLMが自主的にルールを守ることへ依存せず、決められた処理を確実に実行するために利用できます。


Hooksとは

Hookは、Claude Codeの処理途中に割り込み、Toolの入力や出力を検査・変換する仕組みです。特に重要なのは、次の2種類です。

Hook 実行タイミング 主な用途
PreToolUse Toolが実行される前 Tool呼び出しの許可・拒否・入力変更
PostToolUse Toolが正常終了した直後 Tool実行結果の検査・変換・正規化

Exam Guideにある tool call interception hooks は、Claude Codeでは主に PreToolUse に相当します


Tool呼び出し前に制御する PreToolUse

PreToolUse は、ClaudeがToolの引数を生成した後、実際にToolが実行される前に呼び出されます。Toolの名前や入力値を検査し、次のような処理を実施できます。

  • 許可する
  • 拒否する
  • ユーザーへ確認する
  • Toolの入力値を変更する
  • 非対話モードでTool呼び出しを一時保留する

公式リファレンスでは、PreToolUse はTool実行前に呼び出され、allowdenyaskdeferなどの判断を返せると説明されています。

PreToolUse の処理フロー

PreToolUse は、実行前に処理を止められるため、返金、送金、データ削除など、実行後に取り消すことが難しい処理の制御に適しています。

500ドルを超える返金をブロックする例

例えば、Claudeが次のToolを呼び出すシステムを考えます。

{
  "tool_name": "mcp__billing__process_refund",
  "tool_input": {
    "customer_id": "CUST-12345",
    "amount": 750,
    "currency": "USD"
  }
}

ここで、業務ルールが次のように定められているとします。

500ドルを超える返金はAIエージェントが自動実行せず、人間の担当者へ引き継ぐ。

このルールはプロンプトだけで指示するのではなく、PreToolUse Hookで強制します。

.claude/settings.json の定義例

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "mcp__billing__process_refund",
        "hooks": [
          {
            "type": "command",
            "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/check_refund.py"
          }
        ]
      }
    ]
  }
}

ここで、matcher は、どのToolに対してHookを実行するかを絞り込むために使用します。

Claude CodeのHookは、ユーザー設定の ~/.claude/settings.json、プロジェクト設定の .claude/settings.json、ローカル設定の .claude/settings.local.json などに定義できます。設定されたHooksは /hooks コマンドで確認できます。

check_refund.py

#!/usr/bin/env python3

import json
import sys
from typing import Any


REFUND_LIMIT_USD = 500.0


def deny(reason: str) -> None:
    result = {
        "hookSpecificOutput": {
            "hookEventName": "PreToolUse",
            "permissionDecision": "deny",
            "permissionDecisionReason": reason,
            "additionalContext": (
                "Create a structured handoff summary for a human agent. "
                "Include the customer ID, requested amount, reason, and "
                "recommended action."
            ),
        }
    }
    print(json.dumps(result, ensure_ascii=False))


def main() -> None:
    event: dict[str, Any] = json.load(sys.stdin)
    tool_input = event.get("tool_input", {})

    try:
        amount = float(tool_input.get("amount", 0))
    except (TypeError, ValueError):
        deny("Refund amount is invalid and requires human review.")
        return

    currency = tool_input.get("currency", "USD")

    if currency == "USD" and amount > REFUND_LIMIT_USD:
        deny(
            f"Refunds above ${REFUND_LIMIT_USD:.0f} require human approval. "
            f"Requested amount: ${amount:.2f}."
        )
        return

    # JSONを出力せず正常終了すると、通常の権限処理へ進む
    sys.exit(0)


if __name__ == "__main__":
    main()

PreToolUse の構造化された判断は、hookSpecificOutput 内の permissionDecision として返します。現在の公式形式では allowdenyaskdefer が使用され、以前のトップレベルの decisionreasonPreToolUse では非推奨です。


拒否後に代替ワークフローへ誘導する

単にToolを拒否するだけでは、ユーザーの問題は解決しません。返金をブロックした後は、Claudeにたとえば次の行動を取らせます。

  1. 返金Toolの実行を拒否する
  2. 拒否理由をClaudeへ伝える
  3. 人への引き継ぎ情報を作成する
  4. Handoff Toolやチケット作成Toolを呼び出す

この設計例では、Hookが業務ルールを強制し、Claudeが代替手段を判断します。つまり、役割分担は次のようになります。

担当 役割
Hook 500ドル超の返金を確実にブロックする
Claude 拒否理由を理解し、代替ワークフローを選択する
Human Agent 例外的な返金を承認・処理する

Tool実行後に処理する PostToolUse

PostToolUse は、Toolが正常終了した直後に呼び出されます。Hookには、次の情報が渡されます。

  • tool_name
  • tool_input
  • tool_response
  • tool_use_id
  • セッション情報

公式リファレンスでは、PostToolUse の入力に、Toolへ渡された引数である tool_input と、Toolが返した結果である tool_response の両方が含まれると説明されています。

PostToolUse の処理フロー

重要なのは、 ClaudeがTool結果を推論に使用する前に、データ形式を揃えられる ことです。


異なるMCP Toolのデータ形式を正規化する

複数のMCP Toolを利用すると、同じ意味のデータでも形式が異なることがあります。例えば、注文日時が次のように返される可能性があります。

●Tool A
 {
 "created_at": 1784341800
 }
 
●Tool B
 {
 "created_at": "2026-07-18T10:30:00+09:00"
 }
 
●Tool C
 {
 "created_date": "2026/07/18 10:30:00"
 }

さらに、ステータスもToolによって異なる場合があります。

{
"status": 2
}
 
{
"status": "completed"
}

このままClaudeへ渡すと、毎回異なる形式を解釈しなければなりません。PostToolUse Hookを使用すると、例えば次の形式へ統一できます。

{
"created_at": "2026-07-18T10:30:00+09:00",
"status": "completed"
}


PostToolUse の設定例

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "mcp__orders__.*",
        "hooks": [
          {
            "type": "command",
            "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/normalize_order.py"
          }
        ]
      }
    ]
  }
}

Pythonによるデータ正規化例

#!/usr/bin/env python3

import json
import sys
from datetime import datetime, timezone
from typing import Any


STATUS_MAP = {
    0: "pending",
    1: "processing",
    2: "completed",
    3: "cancelled",
}


def normalize_datetime(value: Any) -> Any:
    if isinstance(value, int | float):
        return datetime.fromtimestamp(
            value,
            tz=timezone.utc,
        ).isoformat()

    if isinstance(value, str):
        normalized = value.replace("/", "-").replace(" ", "T")

        try:
            return datetime.fromisoformat(normalized).isoformat()
        except ValueError:
            return value

    return value


def normalize_status(value: Any) -> str:
    if isinstance(value, int):
        return STATUS_MAP.get(value, f"unknown:{value}")

    return str(value).lower()


def main() -> None:
    event: dict[str, Any] = json.load(sys.stdin)
    response = event.get("tool_response", {})

    if not isinstance(response, dict):
        sys.exit(0)

    normalized = dict(response)

    timestamp = response.get("created_at", response.get("created_date"))
    if timestamp is not None:
        normalized["created_at"] = normalize_datetime(timestamp)
        normalized.pop("created_date", None)

    if "status" in response:
        normalized["status"] = normalize_status(response["status"])

    result = {
        "hookSpecificOutput": {
            "hookEventName": "PostToolUse",
            "updatedToolOutput": normalized,
        }
    }

    print(json.dumps(result, ensure_ascii=False))


if __name__ == "__main__":
    main()

PostToolUse では、updatedToolOutput を返すことで、Claudeが受け取るTool結果を置き換えられます。ただし、Toolはすでに実行済みであり、置き換わるのはClaudeに見える結果だけです。ファイル書き込み、コマンド実行、ネットワーク送信などの副作用を取り消すことはできません。


additionalContextupdatedToolOutput の違い

PostToolUse では、Tool結果への補足情報をClaudeへ渡す方法が複数あります。

出力 用途
additionalContext 元のTool結果を残し、補足説明を追加する
updatedToolOutput Claudeが受け取るTool結果そのものを置き換える
decision: "block" Tool実行後に問題点をClaudeへ伝える

データ形式の正規化には、基本的に updatedToolOutput が適しています。
一方で、「このステータスは暫定値であり、確定情報ではない」 のような注意事項を追加するだけなら、additionalContext が適しています。


PreToolUseとPostToolUseの違い

観点 PreToolUse PostToolUse
実行時点 Tool実行前 Tool正常終了後
主な対象 Tool入力 Tool出力
Toolを止められるか 可能 不可能
入力を変更できるか 可能 対象外
出力を正規化できるか 対象外 可能
主な用途 ポリシー強制、権限確認 正規化、検証、補足情報追加

PromptとHookの使い分け

Claudeへ「500ドルを超える返金は実行せず、人へ引き継いでください。」ような、指示することはできます。しかし、プロンプトによる制御は、モデルの判断に依存します。
一方、Hookでは金額をプログラムで判定し、条件に一致したTool呼び出しを確実に拒否できます。公式ガイドでも、HooksはLLMが処理を選択することへ依存せず、特定のアクションを常に実行するための決定論的な制御として説明されています。

要件 Prompt Hook
推奨手順を伝える 適している 通常は不要
柔軟な判断を求める 適している 単純なHookでは不向き
返金上限を必ず守る 不十分 適している
特定コマンドを必ず禁止する 不十分 適している
日時形式を必ず統一する 不安定 適している
ビジネスルールを保証する 不十分 適している

基本的な判断基準は、守ることが望ましいルールはPrompt、必ず守る必要があるルールはHookで実装する です。


Hookの定義場所

Hookをどこに定義するかによって、適用範囲が変わります。

定義場所 主な用途
~/.claude/settings.json ユーザー共通の設定
.claude/settings.json プロジェクトで共有する設定
.claude/settings.local.json 個人用のローカル設定
Pluginの設定 複数プロジェクトへ配布するHook

定義済みのHookは、Claude Code上で次のスラッシュコマンドを使用して確認できます。

/hooks

/hooks では、イベント、matcher、Hookの種類、設定元、コマンドなどを確認できます。


Hookの実装時の注意点

標準入力からJSONを受け取る

Command Hookでは、イベント情報が標準入力へJSON形式で渡されます。

event = json.load(sys.stdin)

標準出力にはJSONだけを出す

構造化された判断を返す場合、標準出力へログなどを混ぜるとJSON解析に失敗する可能性があります。ログを出力する場合は、標準エラーを使用します。

print("Checking refund policy", file=sys.stderr)

PostToolUse では実行済みの処理を取り消せない

PostToolUse が呼び出される時点ではToolはすでに実行されています。そのため、次のような処理を止める目的では使用できません。

  • ファイル削除
  • 返金
  • 送金
  • メール送信
  • 外部APIへの登録

これらは PreToolUse で制御します。

非同期Hookはブロック用途に使えない

Command Hookは非同期実行も可能ですが、非同期Hookが完了する時点では元の処理が進んでいるため、Tool呼び出しの拒否には使用できません。


1.5章のまとめ

ポイントは次の通りです。

  • Hooksは、Claude Codeのライフサイクルへプログラムによる制御を追加する仕組みである
  • Tool呼び出し前のインターセプトには PreToolUse を使用する
  • PreToolUse では、Tool呼び出しの許可、拒否、確認、入力変更ができる
  • Tool実行後のデータ変換には PostToolUse を使用する
  • PostToolUseupdatedToolOutput により、Claudeが受け取るTool結果を正規化できる
  • Unixタイムスタンプ、ISO 8601、数値ステータスなど、異なるMCP Toolの出力形式を統一できる
  • 返金上限や権限制御など、必ず守らなければならない業務ルールはPromptではなくHookで保証する
  • PostToolUse はTool実行後に呼ばれるため、副作用のある処理を止める用途には使用できない
  • ポリシー違反のTool呼び出しは PreToolUse で拒否し、人へのエスカレーションなどの代替ワークフローへ誘導する

Claudeには柔軟な判断を任せ、Hookには確実なルールの強制を任せることが、安全で信頼性の高いエージェントシステムを設計する基本です。

1.6 Design task decomposition strategies for complex workflows

AIエージェントへ複雑なタスクを依頼する場合、重要なのは どのようにタスクを分解するか、 です。

例えば、次のような依頼を考えてみます。

  • このコードベースをレビューしてください
  • セキュリティ上の問題を調査してください
  • レガシーシステムに包括的なテストを追加してください

これらは一見似たような依頼に見えますが、最適な進め方は大きく異なります。タスク分解方法として主に次の2つのパターンを使い分けています。

  • Prompt Chaining(固定シーケンス型)
  • Dynamic Adaptive Decomposition(動的適応型タスク分解)

Toolの実行イベント(Write、Edit、Bashなど)をトリガーとして、LintやFormat、PRチェックなどの処理を自動実行する場合は Hooks を利用します。

一方、Toolの実行イベントには依存せず、LLMの推論によって処理手順を決定する場合は、Prompt Chaining や Dynamic Adaptive Decomposition を利用します。


Prompt Chainingとは

Prompt Chainingとは、最初から処理の順番が決まっているワークフローです。

例えばコードレビューでは、

  1. 各ファイルをレビューする
  2. ファイル横断で整合性を確認する
  3. 最終レポートを作成する

という順番は最初から決まっています。

途中でレビュー対象が変わったり、新しい調査フェーズが追加されたりすることはありません。このように、あらかじめ決められたパイプラインで処理を進める方法が Prompt Chaining です。


Prompt Chainingが向いているケース

Prompt Chainingは、レビュー項目や実施手順が明確な場合(途中で計画を変更する必要がない仕事)に適しています。

タスク 理由
コードレビュー 各ファイルを順番に確認できる
ドキュメントレビュー チェック項目が決まっている
コードフォーマット 実施内容が一定
ライセンス確認 確認手順が固定されている

Cross-file Integration Passとは

大規模なコードレビューでは、各ファイルをレビューしただけでは不十分です。例えば、user.py では問題がなくても、service.py との組み合わせで不具合が発生するかもしれません。
この対処として、 Cross-file Integration Pass という方法で、各ファイルを独立してレビューした後に、ファイル間の整合性を確認します。

この方法には、次のようなメリットがあります。

  • 各レビューに集中できる
  • コンテキストが小さい
  • 全体レビューでは関係性だけを確認できる

結果として、レビュー品質の向上に役立ちます。


Attention Dilution(注意の希釈)を防ぐ

もし最初から、「100ファイル全部レビューしてください」と依頼した場合、LLMは非常に多くの情報を一度に扱うこととなるため、重要な問題を見落としたり、後半になるほどレビュー精度が低下したりする可能性があります。これを、Attention Dilution(注意の希釈)と呼びます。

一方、Prompt Chainingでは、レビュー対象を小さく分割します。

これにより、各レビューでは限られた範囲だけに集中できるため、Attention Dilutionを大幅に抑えられます。


Dynamic Adaptive Decompositionとは

一方、すべてのタスクで手順が最初から決まっているわけではありません。例えば、「このレガシーシステムへ包括的なテストを追加してください。」と言われても、最初は以下のようなことは分かりません。

  • システム構成
  • モジュール構成
  • 依存関係
  • 重要な機能
  • 高リスクな部分

つまり、最初からタスクを決めることができません。そこで、まず調査を行い、調査結果によって次のタスクを動的に決定します。これが、Dynamic Adaptive Decompositionです。


Dynamic Adaptive Decompositionの基本フロー

Prompt Chainingとの最大の違いは、途中で新しいタスクが追加されることです。

つまり、最初にすべてのタスクを決めるのではなく、調査結果に応じて計画そのものを更新していくという考え方です。


Prompt ChainingとAdaptive Decompositionの比較

両者の違いを整理すると、次のようになります。

項目 Prompt Chaining Dynamic Adaptive Decomposition
手順 最初から決まっている 調査結果で変化する
タスク数 固定 動的に増減する
調査内容 予測可能 未知・探索的
主な用途 コードレビュー、文書レビュー バグ調査、セキュリティ監査、レガシー解析
メリット シンプルで安定したワークフロー 未知の問題に柔軟に対応できる

レガシーコードベースへ包括的なテストを追加する

Exam Guideでは、Adaptive Decompositionの例として、add comprehensive tests to a legacy codebase があげられています。一見すると、「すべてのソースコードに対してテストを書けばよい」と思えるかもしれませんが、実際にはこのような進め方は非効率です。レガシーシステムでは、

  • どのモジュールが重要なのか
  • どこが最も壊れやすいのか
  • どこに依存関係が集中しているのか

が分からない状態からスタートします。そのため、最初からすべてのテストを書くのではなく、「調査しながら優先順位を決める」ことが重要になります。


Step1 コードベース全体を把握する

最初に行うのは、コードを書くことではありません。まず、システム全体を理解します。例えば、

プロジェクト全体の構造を調査してください。

・主要ディレクトリ
・エントリポイント
・主要サービス
・依存関係

を整理してください。

この段階では、まだテストは作成しません。まず「何が存在するのか」を理解します。


Step2 高影響モジュールを見つける

構造を理解したら、次は High-impact Areas を探します。例えば、

  • API Gateway
  • Authentication
  • Payment
  • Database Access

などです。

例えば、

最も依存されているモジュールを抽出してください。

変更時の影響範囲が大きい順に並べてください。

のように依頼すると、

Authentication

Order Service

Repository

Utility

のような、重要度が分かります。


Step3 優先順位を付ける

重要モジュールが見つかったら、次はテストを書く順番を決めます。すべて同じ優先度ではありません。例えば、下記にように業務影響が大きいものから着手します。

モジュール 優先度
Authentication ★★★★★
Payment ★★★★★
Order Service ★★★★☆
Notification ★★☆☆☆
Utility ★☆☆☆☆

Step4 テストを書く

ここで初めてテストを書き始めます。Claude Codeへ、

Authenticationモジュールの既存機能を壊さないよう、
正常系
異常系
境界値
を含むpytestを作成してください。

という依頼になります。ここで重要なのは、最初から全体を書くのではなく、高優先度から進めることです。


Step5 結果を見て計画を更新する

Adaptive Decompositionでは、ここが最も重要です。例えば、Authenticationを調査した結果、新たに Session Manager という重要コンポーネントが見つかったとします。
この場合、計画を変更します。

つまり、途中で新しいタスクが増えるのです。これが Adaptive と言われる理由です。


全体フロー

Adaptive Decompositionでは、次のサイクルを繰り返します。

このように、途中で依存関係重要モジュール、新しいリスクが見つかれば、再び調査へ戻ります。


Claude Codeではどのように依頼するか

Adaptive Decompositionでは、最初から「全部テストを書いてください」とは依頼しません。代わりに、段階的に依頼します。

【最初】
プロジェクト全体を解析してください。
主要モジュール
依存関係
エントリポイント
を整理してください。

最も影響範囲が大きいモジュールを抽出してください。

Authenticationからテストを追加してください。

追加調査が必要なモジュールはありますか?

優先順位を更新してください。

このように、途中で調査結果を反映しながら、計画を更新していきます。


Prompt Chainingとの比較

Prompt Chainingなら、最初から

File A
↓
File B
↓
File C
↓
Report

と決まっています。
一方、Adaptive Decompositionでは、途中で

Authentication
↓
Session Manager発見
↓
Session Manager追加
↓
Token Service発見
↓
Token Service追加

のように、新しい調査対象が増えていきます。

つまり、Prompt Chainingは一本道です。Adaptive Decompositionは、木構造のように途中で枝分かれします。


Claude Codeで特に有効な理由

Claude Codeは、

  • Grep
  • Glob
  • Read
  • Task

などを組み合わせながら、調査を進められます。例えば、

1.Grepで依存関係を検索

2.Readで重要ファイルを解析

3.Taskで個別調査

4.Coordinatorが結果を統合

という流れを繰り返すことで、巨大なコードベースでも効率よく解析できます。このような「調査 → 発見 → 再計画」というサイクルは、Claude Codeのエージェント型ワークフローと非常に相性が良いアプローチです。


1.6章のまとめ

ポイントは以下の通りです。

  • Prompt Chaining は、手順があらかじめ決まっているワークフローに適しています
  • Dynamic Adaptive Decomposition は、調査結果に応じてタスクや優先順位を動的に変更するアプローチです
    *「レガシーコードベースへ包括的なテストを追加する」とは、最初からすべてのテストを書くことではなく、構造把握 → 依存関係解析 → 高影響モジュールの特定 → 優先順位付け → テスト追加 → 再評価というサイクルを繰り返しながら、段階的に品質を高めていくことを意味します
  • Claude Codeでは、Grep・Read・Task を組み合わせることで、このAdaptive Decompositionを効率よく実践できます。
    *「固定手順なら Prompt Chaining、未知の探索なら Adaptive Decomposition」
  • 大規模なコードレビューでは、各ファイルを個別にレビューした後、Cross-file Integration Pass を実施することで、ファイル間の整合性を確認できます
  • レビュー対象を適切に分割することで、Attention Dilution(注意の希釈) を防ぎ、レビュー品質を向上できます

1.7 Manage session state, resumption, and forking

これまでの章では、

  • Taskによるサブエージェント
  • Forkによる並列調査
  • Adaptive Decomposition

について説明されています。本章では、それらを実際の開発でどのように継続利用するか、セッション管理 について整理しています。


セッションを再開する

Claude Codeでは、作業途中のセッションを保存し、後から続きを実行できます。
例えば、

claude --resume security-review

のように実行すると、以前の

security-review

セッションを再開できます。

これは、長期間にわたる調査や、数日に分けて行うレビューで役立ちます。


Session Resumeの流れ

Resumeでは、以前の会話履歴やコンテキストを利用しながら、その続きを実行できます。


fork_sessionによる並列検討

以前の章でも紹介しましたが、Forkは、分析結果をコピーして別ルートを試す ための仕組みです。例えば、リファクタリング案を2つ比較する場合、

どちらも共通の分析結果から開始できます。最初から調査をやり直す必要はありません。


Resumeするときの注意点

Resumeには注意点があります。前回分析した後に、コードが変更されている可能性があります。
例えば、

user.py
service.py

が修正されたにもかかわらず、以前の分析結果をそのまま利用すると、誤った結論になる可能性があります。そのため、Resume後は、変更内容をClaudeへ伝えます。

例えば、

前回のレビュー後、
user.py
service.py
を修正しました。
これらだけを再分析してください。

と依頼します。これにより、必要な箇所だけを再解析できます。


Targeted Re-analysis

再解析は、すべてをやり直す必要はありません。変更されたファイルだけを対象にできます。

これを Targeted Re-analysis と呼びます。コードベース全体を再解析するよりも、高速かつ効率的です。


Resumeより新しいセッションがよい場合

Exam Guideでは、Resumeよりも 新しいセッション を推奨するケースについても説明されています。例えば、

  • 数週間経過している
  • Tool実行結果が古い
  • データベースが更新されている
  • 外部APIの結果が変わっている

このような場合は、以前のTool結果を信用するよりも、新しいセッションを開始した方が安全です。


Structured Summaryを利用する

新しいセッションを開始するときは、過去の内容をStructured Summaryとして渡します。

例えば、

前回の調査結果
・Authenticationは正常
・Paymentに課題あり
・Repositoryはレビュー済み
 
今回の対象
・Payment
・Notification

このように、要約だけを渡すことで、古いTool結果に依存せず、必要な情報だけを引き継げます。


ResumeとNew Sessionの使い分け

状況 推奨方法
数時間後に続きから作業する Resume
コード変更が少ない Resume
Tool結果が古い New Session
外部情報が更新されている New Session
大規模リファクタリング後 New Session + Structured Summary

1.7章のまとめ

ポイントは以下の通りです。

  • --resume を使用すると、以前のセッションを再開できます
  • fork_session を使用すると、共通の分析結果から複数のアプローチを並列に検討できます
  • Resume後は、変更されたファイルをClaudeへ伝え、Targeted Re-analysis によって必要な箇所だけを再分析することが重要です
  • Tool実行結果が古くなっている場合は、Resumeではなく、Structured Summaryを渡して新しいセッションを開始する方が信頼性が高い場合があります

Task Statement 1.7で理解すべきポイントは、「Resume」「Fork」「New Session」を状況に応じて適切に使い分けることです。これまで学んだTaskやAdaptive Decompositionと組み合わせることで、大規模な調査や長期間にわたる開発でも効率よくコンテキストを維持できます。

Domain 2: Tool Design & MCP Integration


2.1 Design effective tool interfaces with clear descriptions and boundaries

LLM が適切なツールを選択できるように、ツールの説明(Tool Description)をどのように設計すべきかについて説明しています。
Claude はツール名だけで判断しているのではなく、ツールの説明文(Description)を重視してツールを選択します。このため、曖昧な説明や役割が重複したツールは、誤ったツール選択(Misrouting)の原因になります。


Tool Description を具体的に書く

ツールの説明には、少なくとも次の内容を含めることが推奨されています。

  • ツールの目的
  • 入力形式
  • 出力形式
  • 利用例
  • 利用すべきケース
  • 利用すべきではないケース(境界)

たとえば、「Analyze a document.」では用途が分かりません。一方、

Extract structured information from web search results.

Input:
- HTML
- Markdown

Output:
- title
- url
- summary

Use only for processing web search results.
Do not use for PDF or Office documents.

のように、対象・入力・出力・利用範囲を明確にすると、Claude が適切なツールを選択しやすくなります。


機能が重複するツールは避ける

例えば、

analyze_content
analyze_document

のように、役割の似たツールが存在すると、どちらを選択すべきか判断しづらくなります。この場合は、

  • extract_web_results
  • summarize_document
  • verify_claim_against_source

など、役割が分かる名前へ変更することが推奨されています。


汎用ツールより目的別ツールを作る

1つのツールで何でも処理しようとすると、期待しない使われ方をする可能性があります。

例えば、

  • analyze_document

よりも、

  • extract_data_points
  • summarize_content
  • verify_claim_against_source

のように、1つの目的に特化したツールに分割した方が、ツール選択の精度が向上します。


システムプロンプトにも注意する

ツールの説明を適切に書いていても、システムプロンプトの記述によっては、Claude が意図しないツールを選択することがあります。

例えば、

When the user mentions "document",
always use analyze_document.

のようなキーワードベースの指示を書くと、

  • PDF
  • Word
  • Webページ

など、本来は別ツールを利用すべきケースでも analyze_document が選択される可能性があります。システムプロンプトは、ツール説明と矛盾しないように設計することが重要です。


2.1章のまとめ

ポイントは次の通りです。

  • ツールの説明には、目的・入力・出力・利用範囲を明確に記述する
  • 役割が重複するツールは避け、用途が分かる名前へ変更する
  • 汎用ツールより、目的別に分割したツールの方が適切に選択されやすい
  • システムプロンプトのキーワードによって、意図しないツール選択が起きないよう注意する

Tool Interface の品質は、LLM が正しいツールを選択できるかどうかを左右します。「何をするツールなのか」「いつ使うべきなのか」を明確に記述することが、誤ったツール選択を防ぐポイントです。

2.2 Implement structured error responses for MCP tools

MCP(Model Context Protocol)のツールがエラーを返す際のベストプラクティスについて説明しています。

重要なのは、「エラーが発生した」という事実だけではなく、「どのような種類のエラーなのか」を構造化して返すこと です。これにより、Claude(エージェント)は適切なリカバリやユーザーへの案内を行えるようになります。


isError を利用する

MCPで、ツールの実行が失敗した場合、

{
  "isError": true
}

を返します。これにより、Claude は、

  • 正常な実行結果なのか
  • エラーなのか

を明確に判断できます。


エラーの種類を区別する

すべてのエラーを、「Operation failed」等の汎用的な文言で返すことは推奨されません。

エラーには様々な種類があり、それぞれ対応方法が異なります。

エラー種別 内容 再試行
Transient タイムアウト、一時的なサービス停止、ネットワーク障害
Validation 入力値が不正 ×
Business ビジネスルール違反(契約・ポリシーなど) ×
Permission 権限不足、認証エラー 場合による

エラーの種類を返すことで、Claude は、

  • 再試行する
  • ユーザーへ修正を依頼する
  • 権限不足を案内する

など、適切な対応を選択できます。


構造化されたエラー情報を返す

推奨されるエラー情報には、次のような項目を含めます。

{
  "isError": true,
  "errorCategory": "validation",
  "isRetryable": false,
  "message": "メールアドレスの形式が正しくありません。"
}

主な項目は次のとおりです。

項目 説明
isError エラーであることを示す
errorCategory エラーの種類
isRetryable 再試行可能かどうか
message 人が理解できる説明

このような構造化データを返すことで、エージェントはエラー内容を正しく解釈できます。


ビジネスエラーは再試行しない

例えば、

  • 契約上利用できない
  • 年齢制限
  • 利用回数超過
  • ポリシー違反

などは、何度再試行しても成功しません。そのため、

{
  "errorCategory": "business",
  "isRetryable": false
}

を返します。Claude は不要な再試行を行わず、ユーザーへ適切な説明を返せます。


サブエージェントは可能な限り自己回復する

サブエージェントでは、一時的なエラーなら、

  • 再接続
  • 再試行
  • キャッシュ利用

などを行い、ローカルで回復できるものは回復することが推奨されています。それでも解決できなかった場合のみ、

  • 発生したエラー
  • 試した内容
  • 取得できた部分結果

を Coordinator(親エージェント)へ返します。


Empty Result はエラーではない

検索結果が存在しない場合は、エラーではありません。例えば、「顧客は存在しませんでした。」は、検索自体は成功しています。これは、

{
  "customers": []
}

のような正常結果として返すべきです。一方、「データベースへ接続できませんでした。」は、検索そのものが失敗しているためエラーになります。この2つは明確に区別する必要があります。


2.2章のまとめ

ポイントは次の通りです。

  • isError を利用し、正常結果とエラーを明確に区別する
  • エラー種別(errorCategory)と再試行可否(isRetryable)を返し、適切なリカバリを可能にする
  • ビジネスルール違反など再試行しても解決しないエラーには isRetryable: false を設定する
  • 一時的な障害はサブエージェント内で自己回復を試み、解決できない場合のみ上位エージェントへ伝達する
  • 「検索結果が0件だった」ことはエラーではなく、正常な空結果(Empty Result)として返す

構造化されたエラーレスポンスは、単に失敗を伝えるためではなく、エージェントが「次に何をすべきか」を判断するための重要な情報です。

2.3 Distribute tools appropriately across agents and configure tool choice

マルチエージェント環境におけるツールの適切な分配方法と、tool_choice を利用したツール選択の制御について説明しています。

重要なのは、「すべてのエージェントにすべてのツールを与えないこと」です。役割ごとに必要なツールだけを提供することで、ツール選択の精度が向上し、誤ったツール呼び出しを防ぐことができます。


エージェントにツールを与えすぎない

エージェントに多くのツールを渡すほど、どのツールを使うべきかの判断が複雑になります。例えば、

  • 4〜5個のツール
  • 18個のツール

では、後者の方が誤ったツールを選択する可能性が高くなります。そのため、それぞれのエージェントには、役割に必要なツールのみを提供することが推奨されています。


専門外のツールは誤用されやすい

例えば、

  • Web検索担当エージェント
  • 要約・統合担当エージェント

がある場合、要約担当エージェントに Web検索ツールを与えると、本来コーディネーターへ依頼すべき処理まで自分で実行しようとする可能性があります。役割ごとに利用できるツールを限定することで、このような誤用を防げます。


スコープを限定したツールアクセス

エージェントには、担当業務に応じたツールだけを割り当てます。

エージェント 利用できるツール
Web検索 search_webfetch_page
要約・統合 summarizeverify_fact
データ抽出 extract_metadataextract_entities

ただし、高頻度で利用する機能については、役割をまたいで利用できるツールを用意することもあります。例えば、

  • verify_fact

は要約エージェントから利用しても問題ありません。一方で、複雑な処理はコーディネーターへ委譲することが推奨されています。


汎用ツールより専用ツールを利用する

汎用的なツールは、意図しない入力を受け付けてしまう可能性があります。例えば、あらゆるURLを取得できる fetch_url のような汎用ツールよりも、用途を限定した load_document のような専用ツールを用意する方が、安全かつ予測可能な動作になります。専用ツールでは、例えば次のような制約を設けることができます。

  • ドキュメントURLのみ受け付ける
  • URL形式を検証する
  • 必要に応じて許可されたドメインのみアクセスを許可する

tool_choice の設定

tool_choice を利用すると、モデルがどのようにツールを利用するかを制御できます。

設定 動作
auto モデルが必要に応じてツールを利用するか判断する
any 必ず何らかのツールを呼び出す
Forced Tool 指定したツールを必ず最初に実行する

tool_choice: "auto"

通常の設定です。モデルが、

  • ツールを利用する
  • 会話だけで回答する

のどちらかを自律的に判断します。


tool_choice: "any"

{
  "tool_choice": "any"
}

この設定では、必ず何らかのツールが呼び出されます。会話だけで終了することはありません。


強制ツール選択

例えば、

{
  "tool_choice": {
    "type": "tool",
    "name": "extract_metadata"
  }
}

とすると、最初に必ず「extract_metadata」が実行されます。その後、

  • データ補完
  • 分析
  • 要約

などの後続処理は、次のターンで実施します。これは、「必ず最初にメタデータを取得する」といった処理順序を保証したい場合に有効です。


2.3章のまとめ

ポイントは以下の通りです。

  • 各エージェントには、役割に必要なツールのみを提供する
  • 専門外のツールへのアクセスを制限し、誤ったツール利用を防ぐ
  • 汎用ツールよりも、用途を限定した専用ツールの方が安全で予測可能な動作になる
  • tool_choice を利用することで、ツール利用を制御できる
  • tool_choice: "any" は必ずツールを呼び出し、強制ツール選択は特定のツールを最初に実行させるために利用す

マルチエージェント設計では、「どのエージェントにどのツールを持たせるか」がシステム全体の品質に大きく影響します。役割に応じたツールの分配と、tool_choice の適切な利用が、安定したエージェントシステムを構築する重要なポイントです。

2.4 Integrate MCP servers into Claude Code and agent workflows

Claude Code で MCP(Model Context Protocol)サーバーを利用する際の構成方法と、MCP Resources を活用した効率的なエージェント設計について説明になります。MCP サーバーを適切に構成することで、Claude は外部サービスや社内システムと連携しながら、より高度なタスクを実行できます。


MCP サーバーの設定スコープ

MCP サーバーは、用途に応じて設定場所を使い分けます。

設定ファイル 用途
.mcp.json プロジェクト全体で共有する MCP サーバー
~/.claude.json 個人用・実験用の MCP サーバー

チーム全体で利用するサーバーは .mcp.json に定義し、開発者個人だけが利用する実験的なサーバーは ~/.claude.json に定義することが推奨されています。


環境変数を利用して認証情報を管理する

認証トークンを設定ファイルへ直接記述することは推奨されません。代わりに、

${GITHUB_TOKEN}

のような環境変数を利用します。これにより、

  • GitHubへ秘密情報をコミットしない
  • 開発環境ごとに異なる認証情報を利用できる
  • セキュリティを向上できる

といったメリットがあります。


接続するとすべての MCP ツールが利用可能になる

Claude Code が起動すると、設定されたすべての MCP サーバーへ接続し、それぞれのツールを取得します。この結果、

  • GitHub
  • Jira
  • Database
  • 社内システム

など複数の MCP サーバーが提供するツールを、エージェントは同時に利用できます。


MCP Resources を活用する

MCP Resources は、ツールではなく、利用可能な情報を一覧として公開する仕組みです。

例えば、

MCP Resource の例
Issue 一覧
ドキュメント階層
データベーススキーマ
API カタログ

通常であれば、

  • 「どのデータが存在するか」
  • 「どのドキュメントを見るべきか」

を調べるために複数回ツールを呼び出す必要がありますが、MCP Resources を利用すると、Claude は最初から利用可能な情報を把握できるため、探索目的のツール呼び出しを減らせます。


MCP ツールの説明を充実させる

MCP ツールの説明が不十分だと、Claude は組み込みツールを優先してしまう場合があります。

例えば、「Search repository.」だけでは、Claude は

  • Grep
  • Find

などの組み込みツールを選択する可能性があります。一方、

Search GitHub Issues, Pull Requests and repository metadata.
Returns structured GitHub objects including labels,
assignees and milestones.

のように具体的な説明を書くことで、Claude は MCP ツールの方が適切であると判断しやすくなります。


Community MCP Server を優先する

一般的なサービスとの連携では、独自実装よりも、既存の Community MCP Server の利用が推奨されています。例えば、

サービス 推奨
Jira Community MCP Server
GitHub Community MCP Server
Slack Community MCP Server

一方、

  • 社内システム
  • 独自ワークフロー
  • 自社専用データベース

などは、独自の MCP サーバーを実装する方が適しています。


2.4章のまとめ

ポイントは以下の通りです。

  • チーム共有の MCP サーバーは .mcp.json、個人用・実験用は ~/.claude.json に設定する
  • 認証情報は環境変数(例:${GITHUB_TOKEN})を利用し、ソースコードへ秘密情報を含めない
  • 接続時に、設定されたすべての MCP サーバーのツールがエージェントから利用可能になる
  • MCP Resources を利用すると、エージェントは利用可能な情報を事前に把握でき、探索目的のツール呼び出しを減らせる
  • 標準的な外部サービスとの連携では Community MCP Server を優先し、独自実装はチーム固有のワークフローに限定する
  • MCP ツールの説明を充実させることで、Claude が組み込みツールではなく、より適切な MCP ツールを選択しやすくなる

MCP サーバーは単にツールを追加する仕組みではありません。適切なスコープ管理、認証情報の安全な取り扱い、MCP Resources の活用、そして分かりやすいツール説明を組み合わせることで、Claude Code の能力を最大限に引き出すことができます。

2.5 Select and apply built-in tools (Read, Write, Edit, Bash, Grep,Glob) effectively

Claude Code に標準搭載されている Read、Write、Edit、Bash、Grep、Glob の使い分けについて説明しています。
重要なのは、目的に応じて適切なツールを選択し、コードベースを段階的に理解することです。


Grep と Glob の違い

GrepGlob は似ていますが、検索対象が異なります。

ツール 用途
Grep ファイル内容を検索する 関数名、エラーメッセージ、import 文を検索
Glob ファイル名・パスを検索する **/*.test.tsx**/*.py

例えば、find all callers of get_user のような場合は Grep を使用します。一方、
find all test files なら Glob が適しています。


Read・Write・Edit の使い分け

それぞれの役割は次のとおりです。

ツール 用途
Read ファイル全体を読み込む
Write ファイル全体を書き換える
Edit 特定箇所だけを修正する

通常は Edit を利用しますが、修正対象となる文字列が複数存在する場合、Editでは変更箇所を一意に特定できず失敗することがあります。このような場合は、

  1. Read
  2. 内容を修正
  3. Write

という流れで確実に更新することが推奨されています。


コードベースは段階的に理解する

Claude Code のベストプラクティスは、最初からすべてのファイルを読むことではありません。代わりに、

  1. Grep でエントリーポイントを探す
  2. Read で必要なファイルだけ読む
  3. import や関数呼び出しを追跡する
  4. 必要になったファイルだけ追加で読む

という流れでコードベースを理解します。この方法は、大規模なプロジェクトでも効率的に処理の流れを把握できます。


Wrapper Module はコード解析での難しいケースの代表例

「Tracing function usage across wrapper modules」として、Wrapper Module は、コード解析が難しくなる代表例として挙げています。

例えば、 TypeScript では、

// index.ts

export { getUser } from "./user";
export { createUser } from "./user";

このようなモジュールは、関数の実装を持たず、他のモジュールを 再公開(re-export) するだけです。このため、単純に index.ts を読んでも処理内容は分かりません。Claude Code では、

  1. export されている関数名を取得する
  2. その関数名を Grep でコードベース全体から検索する
  3. 呼び出し元と実装を順番に Read する

という手順で解析することを推奨しています。

Python では TypeScript の index.ts の代わりに、__init__.py が公開 API をまとめる役割を担うことがあります。例えば、

# api/__init__.py

from .user import get_user
from .user import create_user

利用側は、

from api import get_user

と記述できます。この場合、Claude Code では、まず __init__.py を確認し、公開されている API、「get_user、create_user」を特定します。その後、それぞれについて Grep を実行し、どこから呼び出されているかを追跡します。 このように、Python でも 公開 API を起点に利用箇所をたどる という考え方は TypeScript と共通です。


Claude Code への指示例

コード解析では、単に、「Where is get_user used?」と質問するよりも、解析手順まで指示した方が効果的です。例えば、

Analyze how the user authentication feature works.

Start from the public entry points (__init__.py, routers, exported APIs).

Use Grep to identify where the public APIs are referenced.

Follow imports and function calls step by step.

Do not read the entire codebase up front.
Only read files that are relevant to the execution flow.

Finally, summarize the request flow and describe the responsibility of each module.

このように指示すると、

Claude Code は

  • Grep
  • Read
  • Grep
  • Read

を繰り返しながら、必要なファイルだけを読み、効率よくコードベース全体を解析できます。


2.5章のまとめ

ポイントは以下の通りです。

  • Grep はファイル内容、Glob はファイル名・パスを検索する
  • Edit が一意に修正できない場合は、Read → Write を利用する
  • コードベースは最初からすべて読まず、Grep と Read を組み合わせて段階的に理解する
  • Wrapper Module はコード解析での難しいケースの代表例であり、まず公開 API を特定してから利用箇所を追跡する
  • Python でも __init__.py を起点に公開 API を調べ、その後 Grep で利用箇所を追跡するという考え方は同じである

Claude Code の強みは、コードベース全体を一度に読むことではなく、必要な情報だけを段階的に収集しながら処理の流れを理解できる点にあります。適切なツールを選択し、効率的な解析手順を指示することが、正確なコード理解につながります。

Domain 3: Claude Code Configuration & Workflows


3.1 Claude Code Configuration & Workflows


Claude Code における CLAUDE.md の適切な配置方法と、プロジェクトが大規模になった場合のモジュール化について説明しています。

ポイントは次の4つです。

  1. CLAUDE.md には 階層(Hierarchy) がある
  2. ユーザー設定とプロジェクト設定は用途が異なる
  3. @import を利用して外部ドキュメントを参照できる
  4. 巨大な CLAUDE.md は .claude/rules/ へ分割して管理できる

CLAUDE.md の階層

Claude Code は、複数の CLAUDE.md を階層的に読み込みます。

User Level

~/.claude/CLAUDE.md

自分だけに適用されます。例えば

  • コーディングスタイル
  • よく使うコマンド
  • 個人的な開発ルール

などを書きます。Gitでは共有されません。


Project Level

project/

├── .claude/
│   └── CLAUDE.md

または

project/

└── CLAUDE.md

プロジェクト全体へ適用されます。Git管理するため、チーム全員へ共有されます。例えば

  • API設計方針
  • 命名規約
  • テスト方針
  • アーキテクチャのルール

などを書きます。


Directory Level

さらに

src/backend/

└── CLAUDE.md

のようにサブディレクトリにも配置できます。この場合は、そのディレクトリ以下だけへ適用されます。例えば、

src/

├── backend/
│     CLAUDE.md
│
└── frontend/
      CLAUDE.md

なら、バックエンドとフロントエンドで異なるルールを適用できます。


設定が共有されない原因

例えば、~/.claude/CLAUDE.md へ「必ず pytest を利用すること」と書いたとします。新しいメンバーは ~/.claude/ を持っていないため、そのルールは読み込まれません。

つまり、チームで共有したいルールは Project Level に配置する必要があります。


@import による外部ドキュメント参照

@import は、既存のドキュメントを CLAUDE.md から参照するための仕組みです。例えば、

CLAUDE.md

@README.md

@docs/deployment.md

@AGENTS.md

のように記述できます。

これにより、

  • README
  • 設計書
  • 運用手順書
  • AGENTS.md

などを重複して CLAUDE.md へ記載する必要がなくなります。


CLAUDE.md が巨大になったら?

プロジェクトが大きくなると、CLAUDE.mdがたとえば1000行以上になることがあります。

すると

  • 保守しにくい
  • 検索しにくい
  • 更新しにくい

という問題が発生します。この場合、.claude/rules/にルールを分割します。

.claude/

 rules/

    testing.md

    api-conventions.md

    deployment.md

    security.md

    database.md

Claude Codeでは、.claude/rules/ に配置したルールファイルは自動的に読み込まれます。 また、Frontmatter の pathsを利用することで、特定ディレクトリだけへ適用することもできます。

このように、ルールをトピックごとに管理できるようになります。


ディレクトリ構成例

project/

├── .claude/
│
│   ├── CLAUDE.md
│   │
│   └── rules/
│        ├── testing.md
│        ├── api-conventions.md
│        ├── deployment.md
│        ├── security.md
│        └── database.md
│
├── backend/
│     └── CLAUDE.md
│
└── frontend/
      └── CLAUDE.md

/memory コマンド

Claude Codeでは、/memory を実行すると、現在読み込まれている、

  • User Level
  • Project Level
  • Directory Level
  • Rule Files

を確認できます。これにより、「なぜこのルールが適用されないのか?」といった設定ミスを調査できます。


3.1章のまとめ

ポイントは以下の通りです。

  • CLAUDE.md には User・Project・Directory の3階層がある
  • チームで共有するルールは User Level ではなく Project Level に配置する
  • @import は README や設計書、AGENTS.md など既存ドキュメントを参照するために利用する
  • 大規模プロジェクトでは、ルールを .claude/rules/ へ分割して管理する
  • .claude/rules/ に配置したルールは自動的に読み込まれ、paths により適用範囲を限定できる
  • /memory コマンドを利用すると、現在読み込まれている設定を確認できる

プロジェクトが大規模になるほど、ルールは .claude/rules/ へ分割して管理し、READMEや設計書など既存ドキュメントを参照したい場合は @import を利用することが推奨されます。

3.2 Create and configure custom slash commands and skills

Claude Code の Slash CommandSkills の違い、および Frontmatter の主要な設定について説明しています。

ポイントは次の5つです。

  1. Slash Command と Skills は用途が異なる
  2. Project Scope と User Scope を使い分ける
  3. Frontmatter で Skill の動作を制御できる
  4. context: fork を利用するとサブエージェントで実行できる
  5. CLAUDE.md と Skills は役割が異なる

Slash Command と Skills の違い

Claude Codeには、大きく分けて2種類の拡張方法があります。

機能 用途
Slash Command 開発者が /review/deploy のように明示的に実行するコマンド
Skill Claude が必要と判断して利用する、またはユーザーが明示的に呼び出すタスク

つまり、

  • Slash Command は「操作」
  • Skill は「能力」

というイメージです。


Project Scope と User Scope

Slash Command は、

  • チーム共有
  • 個人専用

の2種類があります。

Project Scope

.claude/

 commands/

Git管理されるため、チーム全員が利用できます。

例えば

/review

/deploy

/create-test

などです。


User Scope

~/.claude/

 commands/

自分だけが利用できます。例えば、

/my-review

/my-template

など、個人的なコマンドを配置できます。


Skills

Skillsは

.claude/

 skills/

へ配置します。例えば、

.claude/

 skills/

    architecture-review/

        SKILL.md

    security-review/

        SKILL.md

のようになります。


Frontmatter

Skillは、SKILL.md の先頭で Frontmatterを設定できます。

---
name: architecture-review

description: Review architecture consistency.

context: fork

allowed-tools:
  - Read
  - Grep
  - Glob

argument-hint: "[directory]"

---

# Architecture Review

プロジェクト全体のアーキテクチャをレビューしてください。

主な設定項目は次のとおりです。

項目 役割
name Skill名
description Skillの説明
context 実行コンテキスト
allowed-tools 利用可能なTool
argument-hint 引数のヒント表示

context: fork

本章で最も重要なのが、

context: fork

です。

これを指定すると、Skillは、独立したサブエージェントとして実行されます。

つまり、大量の解析結果や思考過程がメインの会話へ混在しません。例えば、

  • コードベース全体の解析
  • 大量ファイルのレビュー
  • ブレインストーミング

などで有効です。


allowed-tools

Skillごとに利用できるToolを制限できます。例えば、

allowed-tools:

  - Read

  - Glob

  - Grep

なら読み取りだけが許可されます。逆に、

allowed-tools:

  - Write

なら、書き込みだけを許可できます。

これにより、誤って削除や実行を行うリスクを抑えられます。


argument-hint

argument-hint: "[directory]"

は、SkillやSlash Commandを手動で実行する際に、期待される引数をオートコンプリート上へ表示するヒントです。例えば、/architecture-reviewと入力すると、

/architecture-review [directory]

のように表示されます。

補足

argument-hintClaudeが不足した引数を推論して補完する機能ではありません。
また、LLMが「引数を入力してください」と対話的に質問する機能でもありません。
あくまで、ユーザーが手動で Skill や Slash Command を実行するときの入力補助(オートコンプリート用ヒント)です。


Personal Skills

Skillは、

~/.claude/

 skills/

へ配置できます。

チームへ影響を与えず、自分専用のSkillを作成できます。例えば、「review-v2」のように、別名で管理することが推奨されています。


Skills と CLAUDE.md の違い

CLAUDE.md Skills
常に読み込まれる 必要なときだけ利用される
プロジェクト共通ルール タスク固有のワークフロー
コーディング規約 レビュー・分析・生成処理

3.2章のまとめ

ポイントは以下の通りです。

  • Slash Command はユーザーが実行するコマンド、Skill はClaudeが必要に応じて利用する(またはユーザーが呼び出す)機能である
  • Project Scope はGitで共有され、User Scope は個人専用となる
  • context: fork を利用すると、Skillを独立したサブエージェントとして実行できる
  • allowed-tools を利用すると、Skillごとに利用できるツールを制限できる
  • argument-hint は、手動実行時に期待する引数をオートコンプリートへ表示するためのヒントであり、Claudeが引数を自動補完する機能ではない
  • CLAUDE.md は常に読み込まれる共通ルール、Skills は必要なときだけ利用するタスク固有のワークフローである

CLAUDE.md は「常に適用されるルール」、Skills は「必要なときだけ利用する能力」、Slash Command は「開発者が明示的に実行する操作」と考えると、それぞれの役割を整理しやすくなります。

3.3 Apply path-specific rules for conditional convention loading

.claude/rules/paths を利用し、対象ファイルに応じてルールを自動的に切り替える方法について説明しています。

3.1章の .claude/rules/ の応用編であり、ポイントは次の3つです。

  1. paths に Glob パターンを指定すると、対象ファイルを編集するときだけルールが読み込まれる
  2. 不要なルールを読み込まないため、コンテキスト量とトークン消費を削減できる
  3. 複数ディレクトリに分散した同種のファイルには、ディレクトリ単位の CLAUDE.md より paths を持つ Rule の方が適している

paths の設定例

例えば、Terraform ファイルだけにルールを適用したい場合は、Rule ファイルの Frontmatter に次のように記述します。

---
paths:
  - "terraform/**/*"
---

# Terraform Rules

- terraform fmt を実行すること
- resource 名は snake_case を使用すること

Terraform ファイルを編集するときだけ、この Rule が自動的に読み込まれます。


Glob パターンの利用

paths には Glob パターンを指定できます。例えば、

paths:
  - "**/*.test.tsx"

と指定すると、

src/components/Button.test.tsx
src/pages/Login.test.tsx
packages/admin/UserList.test.tsx

のように、ディレクトリに関係なく、すべてのテストファイルへ同じルールが適用されます。これは、各ディレクトリへ個別に CLAUDE.md を配置するよりも管理しやすくなります。


3.3章のまとめ

ポイントは次の通りです。

  • .claude/rules/paths を利用すると、対象ファイルに応じてルールを自動的に切り替えられる
  • Glob パターンを利用することで、ディレクトリを横断して同じ種類のファイルへルールを適用できる
  • 複数ディレクトリに分散したファイルへ共通ルールを適用する場合は、サブディレクトリごとの CLAUDE.md より paths を持つ Rule を利用する方が適している

ディレクトリ単位ではなく、「ファイルの種類」でルールを適用したい場合は、.claude/rules/paths を利用するのが最適です。

3.4 Determine when to use plan mode vs direct execution

Plan Mode と Direct Execution をどのような場面で使い分けるべきかについて説明しています。

結論は非常にシンプルです。

  • 複雑で設計が必要なタスク → Plan Mode
  • 単純で変更範囲が明確なタスク → Direct Execution

Plan Mode を使うケース

Plan Mode は、実装する前に設計・調査・比較検討を行うモードです。

例えば、次のようなケースで利用します。

  • マイクロサービスへの再構成
  • 大規模なライブラリ移行
  • 複数の実装方法を比較したい
  • 多数のファイルへ影響する変更
  • アーキテクチャの見直し

このようなタスクでは、まずコードベースを調査し、実装方針を決めてから変更することで、手戻りを防ぐことができます。


Direct Execution を使うケース

Direct Execution は、変更内容が明確で、そのまま実装して問題ないタスクに適しています。

例えば、

  • 単一ファイルのバグ修正
  • Nullチェックの追加
  • 日付バリデーションの追加
  • 既存関数への小さな修正

などです。


Explore Subagent の役割

調査フェーズでは、大量の検索結果や解析結果が出力されることがあります。このような場合は Explore Subagent を利用することで、

  • 詳細な調査はサブエージェント側で実施
  • メインスレッドには要約のみ返却

となり、コンテキストウィンドウを節約できます。


Plan と Direct を組み合わせる

実際の開発では、Plan Mode と Direct Execution を組み合わせて利用することが推奨されています。例えば、

  1. Plan Mode でライブラリ移行の影響範囲を調査する
  2. 実装方針を決定する
  3. Direct Execution で実際にコードを変更する

という流れです。つまり、Plan は「考える」、Direct は「実装する」ためのモードです。


3.4章のまとめ

Plan Mode Direct Execution
設計・調査が必要 変更内容が明確
複数案を比較する そのまま実装できる
多数のファイルへ影響 単一ファイル中心
アーキテクチャ変更 小規模な修正
手戻りを防ぐ 素早く修正する

ポイントは次の通りです。

  • 複雑な変更や設計判断が必要な場合は Plan Mode を利用する
  • 単純で変更範囲が明確な場合は Direct Execution を利用する
  • 調査フェーズでは Explore Subagent を利用し、コンテキスト消費を抑える
  • 実務では「Plan Mode で調査 → Direct Execution で実装」の組み合わせが推奨される

迷ったら、「まず設計や調査が必要か?」を判断基準にします。設計が必要なら Plan Mode、実装内容が明確なら Direct Execution を選択します。

3.5 Apply iterative refinement techniques for progressive improvement

Claudeとのやり取りを繰り返し改善しながら、期待する結果へ近づける方法について説明しています。
重要なのは、一度で完璧な指示を書くことではなく、テスト・具体例・対話を通じて段階的に品質を高めることです。


入出力例を提示する

自然言語だけでは解釈が曖昧になる場合があります。このような場合は、2〜3件の具体的な入力例・出力例を提示すると、期待する変換内容を正確に伝えられます。


テスト駆動で改善する

実装前にテストケースを作成し、その後、

  • テスト失敗
  • エラー内容
  • 期待値との差分

を Claude に共有しながら改善していく方法です。期待される動作だけでなく、

  • エッジケース
  • パフォーマンス要件

も最初にテストへ含めることが推奨されています。


Interview Pattern を活用する

実装を始める前に、Claude に質問をしてもらう方法です。例えば、

  • キャッシュ戦略はどうするか
  • 障害発生時の動作はどうするか
  • データの整合性はどう保つか

など、開発者が見落としていた設計上の考慮点を洗い出すことができます。


問題の伝え方を使い分ける

複数の問題がある場合は、状況に応じて指示方法を変えます。

状況 推奨方法
問題同士が関連している まとめて1回で伝える
独立した問題 1つずつ順番に修正する

関連する問題を個別に修正すると、後から別の修正で影響を受ける場合があるためです。


3.5章のまとめ

本章のポイントは次のとおりです。

  • 曖昧な要件は、具体的な入力例・出力例で示す
  • テストを先に作成し、失敗結果を共有しながら反復的に改善する
  • Interview Pattern を利用して、実装前に設計上の考慮事項を洗い出す
    *問題が相互に影響する場合はまとめて修正し、独立した問題は順番に修正する

Iterative Refinement の本質は、「一度で完成を目指す」のではなく、具体例・テスト・対話を繰り返しながら品質を高めていくことです。

3.6 Integrate Claude Code into CI/CD pipelines

Claude Code を CI/CD パイプラインへ組み込み、自動レビューやテスト生成を行う方法について説明しています。CI で利用する場合は、人との対話ではなく、自動実行・構造化出力・プロジェクトルールの共有が重要になります。


非対話モードで実行する

CIではユーザー入力を待つことができないため、

claude -p

または

claude --print

を使用し、非対話モードで実行します。これにより、CIジョブが入力待ちで停止することを防げます。


JSON形式で結果を出力する

レビュー結果を GitHub の PR コメントへ自動投稿する場合は、

claude \
  -p \
  --output-format json \
  --json-schema review-schema.json

のように実行します。--output-format jsonJSON形式で出力し、--json-schema は、「どのようなJSON構造で出力するか」をClaudeへ指定する」ためのものです。例えばレビュー結果なら、

{
  "issues": [
    {
      "file": "src/user.ts",
      "line": 42,
      "severity": "warning",
      "message": "Nullチェックが不足しています"
    }
  ]
}

のような構造を強制できます。これにより、GitHub Actions や Azure DevOps、Jenkins などがそのまま解析できます。


Machine-parseable Structured Findings

これは、「人向け文章」ではなく、プログラムがそのまま解析できるレビュー結果」を意味します。例えば、「user.ts に Null チェックが不足しています。」ではなく、

{
  "file": "src/user.ts",
  "line": 42,
  "severity": "warning",
  "rule": "null-check",
  "message": "Missing null validation."
}

のような形式です。このようにすると、

  • GitHub PRコメント
  • ダッシュボード
  • 品質レポート
  • Slack通知

などへ自動連携できます。


CLAUDE.md にテストルールを書く

CIから実行される Claude Code は、人から毎回説明を受けることができません。そのため、

  • テスト方針
  • 命名規則
  • Fixture(テストで毎回使用する共通の入力データやテスト環境)
  • Mock(外部システムやAPIの代わりに動作を模擬する仕組み)

などを CLAUDE.md に記載しておきます。例えば、

# Testing Standards

- Arrange-Act-Assert を使用する
- テスト名は should で始める
- Mock を優先する
- Integration Test は別ディレクトリ

# Fixtures

- fixtures/users.json
- fixtures/products.json
- fixtures/orders.json

などです。これにより、

  • 既存 Fixture を利用する
  • 重複テストを作らない
  • プロジェクトのテスト規約に従う

ようになります。


レビューは別セッションで行う

コードを書いた Claude セッションと、レビューする Claude セッションは分けることが推奨されています。

同じセッションでは、「自分が書いたコード」というコンテキストを持っているため、レビューが甘くなる可能性があります。独立したセッションでレビューすることで、より客観的な指摘が期待できます。


再レビューでは差分だけを見る

新しいコミットが追加された場合は、前回のレビュー結果も Claude に渡し、「新しく発生した問題」と「未修正の問題だけ報告してください」と、指示します。

これにより、同じ指摘が何度も PR に投稿されることを防げます。


3.6章のまとめ

ポイントは以下の通りです。

  • CIでは -p--print)を利用し、非対話モードで実行する
  • --output-format json--json-schema を利用して、機械可読なレビュー結果を生成する
  • CLAUDE.md にテスト基準や Fixture を記載し、生成品質を向上させる
  • レビューはコード生成とは別セッションで実施し、客観性を高める
  • 再レビューでは前回結果を共有し、新規または未修正の問題のみ報告する

CI/CD における Claude Code の活用では、「自動実行」「構造化出力」「プロジェクトルールの共有」の3つが品質向上の鍵となります。

Domain 4: Prompt Engineering & Structured Output


4.1 Design prompts with explicit criteria to improve precision and reduce false positives

LLMによるコードレビューでは、モデルの性能よりも、プロンプトにどのような判定基準(Criteria)を書くかがレビュー品質を大きく左右します。例えば、「コメントが正しいか確認してください」という曖昧な指示では、LLMは何を「誤り」と判断すべきか分からず、不要な指摘(False Positive)が増えてしまいます。

一方で、「コメントの説明が、実際のコードの動作と矛盾している場合のみ指摘してください」のように、報告条件を具体的に定義すると、レビュー結果の精度(Precision)が向上し、False Positiveを減らすことができます。

また、「保守的にレビューしてください」、「高い確信がある場合のみ報告してください」といった抽象的な指示だけでは、レビュー品質はあまり改善されません。重要なのは、モデルの信頼度ではなく、具体的な判定基準(Criteria)を定義することです。

さらに、False Positiveが多いカテゴリがあると、開発者はレビュー全体を信用しなくなってしまいます。そのため、精度が改善するまで一時的にそのカテゴリのレビューを停止し、プロンプトを改善してから再度有効化することも、有効な運用方法です。

曖昧な指示と明確なCriteriaの違い

曖昧な指示
「コメントが正しいか確認してください」
     ▼
判断基準が曖昧
     ▼
False Positive が増える
     ▼
開発者の信頼が低下

明確なCriteria
「コメントがコードの実際の動作と矛盾する場合のみ報告」
     ▼
判断基準が明確
     ▼
Precision 向上、False Positive 減少
     ▼
開発者の信頼が向上

False Positiveが多いレビューカテゴリは、無理に有効化し続けるのではなく、一時的にレビュー対象から外し、プロンプトや判定基準を改善してから再度有効化することも重要な運用方法です。

4.2 Apply few-shot prompting to improve output consistency and quality

詳細なルールを追加するよりも、2〜4件の質の高い Few-shot Examples を示す方が、出力形式の統一、曖昧なケースの判断、ハルシネーションの低減、未知のパターンへの一般化において高い効果を発揮します。

  • 出力形式の統一
  • 曖昧なケースにおける判断の安定
  • ハルシネーションの低減
  • 未知のパターンへの一般化

このため、試験や実務では、単にルールを書くのではなく、「入力例」と「期待する出力例」をセットにしたFew-shot Examplesをプロンプトへ組み込むことを推奨しています。

Few-shot Examplesは、AIに対する説明というより、AIに見せるお手本です。


例1:コードレビューの出力形式を統一する

ルールだけを記載したプロンプト

あなたはコードレビューAIです。

以下の問題を検出してください。

- バグ
- セキュリティ上の問題

以下の内容は指摘しないでください。

- コーディングスタイル
- 変数名
- フォーマット

次の形式で出力してください。

Location:
Issue:
Severity:
Suggested Fix:

ルールだけでも出力形式は指定できますが、実際には次のような問題が発生することがあります。

  • Severityが省略される
  • 項目の順番が変わる
  • 「重大な問題があります」のような文章だけが出力される
  • 問題がない場合の形式が統一されない

そこで、期待する入力と出力の例を追加します。

Few-shot Examplesを追加したプロンプト

あなたはコードレビューAIです。

バグまたはセキュリティ上の問題のみを報告してください。

コーディングスタイル、変数名、フォーマットに関する軽微な問題は報告しないでください。

問題がある場合は、必ず次の形式で出力してください。

Location:
Issue:
Severity:
Suggested Fix:

問題がない場合は、次の形式で出力してください。

Result:
問題なし

Reason:
問題ではないと判断した理由

以下の例を参考にしてください。

【例1:セキュリティ上の問題】

入力:

password = "admin123"

出力:

Location:
main.py:10

Issue:
パスワードがソースコードにハードコードされています。

Severity:
High

Suggested Fix:
パスワードを環境変数またはSecret Managerから取得するように変更してください。

---

【例2:許容されるコード】

入力:

logger.info(userId)

出力:

Result:
問題なし

Reason:
ユーザーIDのログ出力は、現在のコーディングガイドラインで許可されているためです。

---

ここからが実際のレビュー対象です。

入力:

{{レビュー対象のコード}}

このように、問題がある例だけでなく、問題がない例も示すことで、偽陽性を減らしやすくなります。


例2:コメントとコードの不一致を判断する

「コメントが正確か確認してください」という指示だけでは、表現が少し古いだけのコメントや、実害のないコメントまで大量に指摘される可能性があります。Few-shot Examplesを使い、どのような場合だけ報告するのかを示します。

あなたはコードレビューAIです。

コメントに記載された動作と、実際のコードの動作が明確に矛盾する場合のみ報告してください。

コメントの表現が簡潔である、詳細が省略されている、または文体が統一されていないという理由だけでは報告しないでください。

以下の例を参考にしてください。

【例1:コメントとコードが一致している】

入力:

// データを昇順に並べ替える
sortAscending();

出力:

Result:
問題なし

Reason:
コメントに記載された動作と、実際のコードの動作が一致しています。

---

【例2:コメントとコードが矛盾している】

入力:

// データを昇順に並べ替える
sortDescending();

出力:

Location:
sort.py:20

Issue:
コメントには昇順に並べ替えると記載されていますが、実際のコードは降順に並べ替えています。

Severity:
Medium

Suggested Fix:
コメントまたはコードのいずれかを、意図した動作に合わせて修正してください。

---

ここからが実際のレビュー対象です。

入力:

{{レビュー対象のコード}}

この例によって、LLMは単にコメントを確認するのではなく、コメントと実装が明確に矛盾している場合だけ報告するという判断基準を学びます。


例3:表現が異なる文書から同じ項目を抽出する

契約書から契約金額を抽出する場合、文書によって表現が異なります。例えば、契約金額が次のように記載されることがあります。

  • 契約金額
  • 本契約の対価
  • 委託料
  • 業務の報酬

単に「契約金額を抽出してください」と指示するだけでは、該当項目が見つからず、nullが出力されることがあります。

あなたは契約書から必要な情報を抽出するAIです。

文書から契約金額を抽出してください。

「契約金額」という項目名が存在しない場合でも、対価、委託料、報酬など、契約に基づいて支払われる金額を表す記載を確認してください。

金額が文書に記載されていない場合は、推測せずにnullを出力してください。

以下の例を参考にしてください。

【例1】

入力:

契約金額は100万円です。

出力:

契約金額:
100万円

---

【例2】

入力:

本契約の対価は、金100万円(税込)とする。

出力:

契約金額:
100万円(税込)

---

【例3】

入力:

本業務の委託料は100万円とする。

出力:

契約金額:
100万円

---

【例4:金額が記載されていない】

入力:

委託料については、甲乙協議の上、別途決定する。

出力:

契約金額:
null

---

ここからが実際の抽出対象です。

入力:

{{契約書本文}}

このプロンプトでは、表現の違いを吸収する例に加えて、情報が存在しない場合は推測しない例も示しています。これにより、空欄やnullの誤判定だけでなく、ハルシネーションの抑制にもつながります。


例4:異なる文書構造から調査手法を抽出する

調査手法は、必ずしもMethodologyや「調査方法」という独立した見出しの下に書かれているとは限りません。本文や調査概要の中に埋め込まれている場合もあります。

あなたは調査レポートから調査手法を抽出するAIです。

次の項目を抽出してください。

- Methodology:調査手法
- Sample Size:調査対象数
- Collection Period:データ収集期間

独立した「調査方法」セクションが存在しない場合は、本文、脚注、調査概要なども確認してください。

文書に記載されていない項目は、推測せずにnullを出力してください。

以下の例を参考にしてください。

【例1:独立したMethodologyセクションがある】

入力:

Methodology

2026年4月に、国内企業100社を対象としてアンケートを実施した。

出力:

Methodology:
アンケート調査

Sample Size:
100社

Collection Period:
2026年4月

---

【例2:調査方法が本文に埋め込まれている】

入力:

本レポートは、2026年1月から3月までに実施した、国内のIT担当者500名へのWebアンケート結果に基づいている。

出力:

Methodology:
Webアンケート調査

Sample Size:
500名

Collection Period:
2026年1月から2026年3月

---

【例3:複数の調査方法が使用されている】

入力:

企業50社へのインタビューと、公開されている財務資料の分析を実施した。調査は2025年10月から12月に行った。

出力:

Methodology:
- インタビュー調査
- 公開資料分析

Sample Size:
50社

Collection Period:
2025年10月から2025年12月

---

【例4:対象数が記載されていない】

入力:

関係者へのインタビューと公開資料の分析に基づき、市場動向を整理した。

出力:

Methodology:
- インタビュー調査
- 公開資料分析

Sample Size:
null

Collection Period:
null

---

ここからが実際の抽出対象です。

入力:

{{調査レポート本文}}

この例によって、モデルは特定の見出しだけを検索するのではなく、異なる文書構造から必要な情報を見つける判断を一般化しやすくなります。


Few-shot Examplesを作成する際のポイント

Few-shot Examplesは、単に似た例を複数並べるのではなく、モデルに学ばせたい判断の違いが分かるように設計します。例えば、次のような組み合わせが有効です。

例の種類 目的
明確に問題がある例 報告すべき条件を示す
問題がない例 偽陽性を減らす
曖昧な例 判断基準を示す
情報が存在しない例 推測やハルシネーションを防ぐ
文書構造が異なる例 未知の形式への一般化を促す

Few-shot Examplesは、通常2〜4件程度に絞り、実際に発生しやすい失敗パターンを対象にすることが重要です。

<thinking><answer> タグを用いた Few-shot のベストプラクティス
Anthropicでは、Few-shotプロンプトを記述する際に、XMLタグを用いて例を構造化することが推奨されています。
特に、推論を伴うタスクでは、Few-shotの例の中で<thinking><answer>を分けて記述することで、Claudeに推論の進め方と最終回答の形式を示すことができます。

Few-shotの例

<examples>
  <example>
    <question>
      15%引きの商品が8,500円でした。元の価格はいくらですか?
    </question>

    <thinking>
      8,500円は元の価格の85%なので、
      元の価格 = 8,500 ÷ 0.85 = 10,000円
    </thinking>

    <answer>
      元の価格は10,000円です。
    </answer>
  </example>

  <example>
    <question>
      消費税10%込みで11,000円です。本体価格はいくらですか?
    </question>

    <thinking>
      本体価格 × 1.1 = 11,000円なので、
      本体価格 = 11,000 ÷ 1.1 = 10,000円
    </thinking>

    <answer>
      本体価格は10,000円です。
    </answer>
  </example>
</examples>

このように、<examples><example><thinking><answer> を用いてプロンプトを構造化することで、Claudeは各Few-shotの例をより正確に理解できます。
また、AnthropicではXMLタグ名は固定ではありません。<thinking><answer> は代表例であり、意味が明確で一貫性のあるタグ名であれば、日本語のタグ(例:<考察><回答>)を使用することも可能です。

補足

  • Anthropicでは、Few-shotの例の中に<thinking>タグを使用して推論パターンを示すと、Claudeがそのスタイルを自身のExtended Thinkingブロックへ一般化すると説明しています
  • XMLタグは、Few-shotだけでなく、入力、出力、制約、コンテキストなど、プロンプト内の異なる要素を区別する目的にも利用できます

4.2章まとめ

Few-shot Examplesの基本構造は、次のとおりです。

タスクの説明
    ↓
出力ルール
    ↓
入力例1
    ↓
期待する出力例1
    ↓
入力例2
    ↓
期待する出力例2
    ↓
実際の入力

単に「慎重に判断してください」「正確に抽出してください」と指示するのではなく、期待する判断と出力を具体例として示します。

Few-shot Examplesは、AIへの説明ではなく、AIに見せるお手本です。ルールを増やすよりも、期待する入力と期待する出力の組み合わせを2〜4件示す方が、一貫した高品質な結果を得やすくなります。

4.3 Enforce structured output using tool use and JSON schemas

LLMに対して単に「JSON形式で出力してください」と指示するのではなく、Tool UseとJSON Schemaを利用して、定義済みの構造に従った出力を強制することが重要です。

通常のテキスト生成では、モデルがJSONの前後に説明文を追加したり、カンマや括弧を欠落させたりする可能性があります。

以下が抽出結果です。

{
  "invoice_number": "INV-001",
  "amount": 10000
}

このような出力は、人には読めても、アプリケーションでそのままJSONとして処理できない場合があります。一方、Tool Useでは、モデルにツールの引数を生成させます。ツールの引数はJSON Schemaで定義されているため、モデルはその構造に従った値を返します。

{
  "invoice_number": "INV-001",
  "amount": 10000
}

つまり、次の違いがあります。

方法 モデルが生成するもの 主な問題
プロンプトでJSON出力を依頼 自由形式のテキスト 説明文の混入、JSON構文エラー
Tool UseとJSON Schema スキーマに従ったツール引数 構文は安定するが、値の正しさは別途検証が必要

Tool Useによる構造化出力の流れ

例えば、請求書抽出ツールでは、次のような項目を定義します。

{
  "type": "object",
  "properties": {
    "invoice_number": {
      "type": ["string", "null"]
    },
    "issue_date": {
      "type": ["string", "null"]
    },
    "total_amount": {
      "type": ["number", "null"]
    }
  },
  "required": [
    "invoice_number",
    "issue_date",
    "total_amount"
  ]
}

この場合、各フィールド自体は必須ですが、文書に値が存在しない場合はnullを許可しています。
これは、値が見つからないときに、モデルが必須項目を埋めるために架空の値を生成することを防ぐためです。


tool_choiceの違い

Tool Useでは、tool_choiceによってモデルにどの程度ツール利用を強制するかを指定します。

auto

モデルがツールを使うか、通常のテキストを返すかを選択します。

{
  "tool_choice": {
    "type": "auto"
  }
}

この設定では、モデルがツールを呼び出さず、通常の文章で回答する可能性があります。


any

モデルは必ずいずれかのツールを呼び出しますが、どのツールを使うかはモデルが選択します。

{
  "tool_choice": {
    "type": "any"
  }
}

例えば、請求書、契約書、領収書の抽出ツールが用意されていて、入力文書の種類が事前に分からない場合に利用できます。


特定ツールの強制指定

特定のツールを必ず呼び出させる場合は、ツール名を指定します。

{
  "tool_choice": {
    "type": "tool",
    "name": "extract_metadata"
  }
}

例えば、情報の補完や外部検索を行う前に、必ず文書のメタデータを抽出したい場合に使用します。


JSON Schemaで防げるものと防げないもの

Tool UseとJSON Schemaを使うことで、次のような構文上の問題を防ぎやすくなります。

  • JSONの括弧が閉じていない
  • カンマが不足している
  • フィールド名が毎回変わる
  • 数値フィールドに説明文が入る
  • 必須フィールドが構造上欠落する

ただし、JSON Schemaが保証するのは、主に構造と型です。値の意味的な正しさまでは保証しません。例えば、次のJSONは構文上もスキーマ上も正しい可能性があります。

{
  "subtotal": 10000,
  "tax": 1000,
  "total": 15000
}

しかし、実際には次の計算と一致していません。

10,000 + 1,000 = 11,000

このような問題は、「意味的なエラー(semantic error)」です。

そのため、構造化出力を取得した後に、アプリケーション側で次のような検証を行う必要があります。

  • 明細の合計と総額が一致しているか
  • 日付が有効な形式か
  • 金額が誤ったフィールドに入っていないか
  • 税率と税額が整合しているか
  • 文書中に存在しない値を生成していないか

Optional、Nullable、Requiredの設計

元文書に必ず存在する情報だけを、単純な必須項目として扱います。一方、文書によって存在しない可能性がある項目は、次のいずれかで設計します。

  • フィールド自体を任意にする
  • フィールドは必須にし、値としてnullを許可する

例えば、担当者名が記載されていない可能性がある場合、次のようにします。

{
  "contact_name": {
    "type": ["string", "null"]
  }
}

これにより、モデルへ次のような判断をさせられます。

{
  "contact_name": null
}

情報が存在しないにもかかわらず、必須の文字列として定義すると、モデルが値を推測して埋める可能性があります。


enumunclearotherを追加する

カテゴリをenumで固定すると、出力の揺れを減らせます。

{
  "document_type": {
    "type": "string",
    "enum": [
      "invoice",
      "contract",
      "receipt",
      "unclear",
      "other"
    ]
  }
}

unclearは、どのカテゴリか判断できない場合に使用します。otherは、定義済みカテゴリには該当しないが、別のカテゴリとして説明できる場合に使用します。この場合は、詳細フィールドも用意します。

{
  "document_type": "other",
  "document_type_detail": "納品確認書"
}

データ構造としては、次のようになります。


フォーマット正規化ルールも必要

JSON Schemaは出力構造を制約できますが、値の表記までは自動的に統一されるとは限りません。例えば、同じ日付でも文書上では次のように記載されます。

2026年7月16日
2026/07/16
令和8年7月16日
July 16, 2026

スキーマが単なる文字列型の場合、これらはすべて有効な文字列です。

{
  "issue_date": {
    "type": ["string", "null"]
  }
}

そのため、プロンプト側で正規化ルールを指定します。

日付は、元文書の表記にかかわらずYYYY-MM-DD形式へ正規化してください。

例:
2026年7月16日 → 2026-07-16
2026/07/16 → 2026-07-16
令和8年7月16日 → 2026-07-16

金額は、通貨記号と桁区切りを除き、数値として出力してください。

例:
10,000円 → 10000
¥10,000 → 10000

つまり、役割は次のように分かれます。

制御対象 主な方法
フィールド名 JSON Schema
データ型 JSON Schema
必須・任意 JSON Schema
許容カテゴリ enum
日付の表記統一 プロンプトの正規化ルール
金額の表記統一 プロンプトの正規化ルール
値の整合性 アプリケーション側の検証

Strict Tool Use によるツール入力の信頼性向上

Tool Useの信頼性を高めるために Strict Tool Use が提供されています。

Tool定義では、strict: true を指定することで、Claudeが input_schema に厳密に従ってTool Inputを生成するようになります。

{
  "name": "extract_metadata",
  "description": "Extract metadata from a document.",
  "strict": true,
  "input_schema": {
    "type": "object",
    "properties": {
      "title": {
        "type": "string"
      },
      "author": {
        "type": "string"
      }
    },
    "required": [
      "title",
      "author"
    ],
    "additionalProperties": false
  }
}

また、input_schemaadditionalProperties: false を指定することで、Schemaで定義されていないプロパティの生成を禁止できます。例えば、titleauthor のみを定義したSchemaであれば、memonote といった存在しないフィールドをClaudeが勝手に生成することを防止できます。
Anthropicのベストプラクティスでは、構造化出力やTool Callにおけるハルシネーション(存在しないプロパティの生成)は、additionalProperties: false などを用いた厳密なJSON Schemaと、明確なTool Descriptionを組み合わせることで軽減できると説明されています。

strict: true は「Schemaを厳密に適用する」ための設定、additionalProperties: false は「Schemaに存在しないフィールドを禁止する」ためのJSON Schemaの設定であり、両者を組み合わせることで、より堅牢なTool Useを実現できます。


4.3章のまとめ

ポイントは以下の通りです。

  • Tool UseとJSON Schemaを利用して、構造化された出力を強制する
  • tool_choiceを使い分け、ツール呼び出しの有無や対象を制御する
  • 元文書に存在しない可能性がある項目は、OptionalまたはNullableにする
  • 曖昧な場合に備えて、unclearを用意する
  • 拡張可能なカテゴリには、otherと詳細フィールドを用意する
  • 日付や金額などの表記揺れは、プロンプトの正規化ルールで統一する
  • JSON Schemaでは意味的な誤りまでは防げないため、後続の検証処理を追加する

Tool UseとJSON Schemaの目的は、モデルにきれいなJSON文字列を書かせることではなく、アプリケーションが安定して利用できる構造化データを、定義済みのインターフェースに従って生成させることです。

4.4 Implement validation, retry, and feedback loops for extraction quality

一度抽出して終わりではなく、抽出結果を検証(Validation)し、修正可能な場合はLLMへフィードバックして再抽出(Retry)を行い、その結果を継続的に改善(Feedback Loop)する仕組みを構築することを推奨しています。


全体像

ポイントは、

抽出 → 検証 → 必要なら再抽出

というループを作ることです。


Validationとは

Validationでは、

  • JSON構造
  • 値の整合性
  • フィールド間の関係

をチェックします。例えば請求書なら、

小計:10,000円
消費税:1,000円
合計:15,000円

となっていた場合

10,000 + 1,000 ≠ 15,000

なので、Validation Errorになります。


Semantic ErrorとSchema Error

Schema ErrorはTool Useでほぼ防げます。例えば、

{
 "amount":10000

括弧が閉じていない。これはSchema Errorです。一方で、

{
 "subtotal":10000,
 "tax":1000,
 "total":15000
}

JSONとしては正しいですが、

10000 + 1000 ≠ 15000

なので、Semantic Errorです。


Retry with Error Feedback

Validationでエラーになった場合、単純に「もう一回」と言うのではなく、Validation結果をLLMへ返します。


プロンプト例

次の抽出結果にはValidation Errorがあります。

Validation Error

- subtotal + tax が total と一致しません。

元文書を再確認し、
正しい値を抽出してください。

元文書

{{Document}}

前回の抽出結果

{{Previous JSON}}

これが、Retry with Error Feedbackです。


Retryが有効なケース

例えば、「契約金額 100万円」なのに、「contract_amount=null」だったら、Retryで改善できます。一方で、「契約書に契約日が書かれていない」ならRetryしても「契約日」は出てきません。この場合は、「null」が正解です。


Retryが無効なケース

「請求書には担当者名が書かれていない」にもかかわらず、もう一度抽出してくださいを何回繰り返しても担当者名は出てきません。つまり、「情報が存在しない ⇨ Retryしても改善しない」ということです。


Feedback Loop

Validationだけでは終わりません。結果を蓄積して「どのようなパターンで失敗したか」を分析します。


例えば、

{
  "issue":"SQL Injection",

  "detected_pattern":
    "String Concatenation"
}

と保存します。開発者が、「これは問題ではない」と却下したら、「String Concatenation」が「False Positive」になりやすいと分析できます。


Self-Correction(自己修復)しやすいSchema設計

Validationしやすいように、計算値と記載値を分けて抽出します。

{
  "subtotal":10000,

  "tax":1000,

  "stated_total":12000,

  "calculated_total":11000
}

Validationでは、「stated_total = calculated_total」を比較します。
また、複数文書に矛盾がある場合は、

{
  "conflict_detected":true
}

のようなフラグを追加します。


4.4章のまとめ

Validation・Retry・Feedback Loopは次の流れで実装します。

この章のポイントは次のとおりです。

  • ValidationではSchemaだけでなくSemantic Errorも検証する
  • Retryでは「もう一度」ではなく、Validation Errorを具体的にフィードバックする
  • 元文書に情報が存在しない場合は、Retryしても改善しない
  • detected_patternを保存し、False Positiveの傾向分析に活用する
  • calculated_totalconflict_detectedなど、自己検証しやすいSchemaを設計する

Validationは抽出結果の品質を確認する工程、Retryはモデル自身に修正させる工程、Feedback Loopは運用結果を分析し、プロンプトや抽出ロジックを継続的に改善する工程です。

4.5 Design efficient batch processing strategies

大量のドキュメント分析やテスト生成を効率化するには、すべての処理を同期APIで即時実行するのではなく、処理結果が必要になる時間に応じて、同期処理とバッチ処理を使い分けることが重要です。

Anthropicの Message Batches API は、複数のMessages APIリクエストをまとめて送信し、非同期で処理するためのAPIです。即時応答を必要としない処理をバッチ化することで、通常のMessages APIよりもコストを抑えながら、大量のリクエストを処理できます。


Message Batches APIとは

Message Batches APIでは、複数の独立したMessages APIリクエストを、一つのバッチとして送信します。

バッチ内の各リクエストは独立して処理されます。そのため、一部のリクエストが失敗しても、ほかのリクエストの処理には影響しません。主な特徴は次のとおりです。

項目 内容
処理方式 非同期処理
料金 通常のAPI料金の50%
処理時間 多くのバッチは1時間以内に完了
最大処理時間 24時間
即時応答 保証されない
結果形式 JSONL
結果の並び順 入力順とは限らない
対応付け custom_idを使用
バッチ上限 100,000リクエストまたは256MBのいずれか早い方

「24時間」は通常の処理時間を示すものではなく、バッチが処理される最大期間です。多くのバッチは1時間以内に完了しますが、特定の時間までに完了することを保証するレイテンシSLAはありません。24時間以内に処理されなかったリクエストは、expiredになります。


50%のコスト削減はどこから来るのか

Eaxm Guideに記載されている 50% cost savings は、処理方法を工夫した場合の概算値ではありません。Message Batches APIに適用される、Anthropic公式の料金設定です。バッチ処理では、入力トークンと出力トークンの両方が、通常のMessages API料金の50%で課金されます。

したがって、同じモデルで同じ量のトークンを処理した場合、基本的な計算は次のようになります。

Batch APIの料金
= 通常APIのトークン料金 × 50%

ただし、次のような費用まで一律に半額になるという意味ではありません。

  • アプリケーション側のサーバー費用
  • データ保存費用
  • 外部ツールや外部APIの利用料金
  • 再試行によって追加で発生するトークン料金

Message Batches APIの50%削減とは、主にClaude APIの入力・出力トークン料金に適用される割引です。


同期APIとBatch APIを使い分ける

APIの選択は、処理量だけではなく、結果をいつまでに必要とするかで判断します。

同期APIに適した処理

次の処理は、結果を待ってから後続処理を進める必要があります。

  • Pull Requestのマージ前チェック
  • ユーザーの操作中に行うコードレビュー
  • 対話型エージェントの応答
  • デプロイ前のセキュリティ判定
  • CIパイプラインを継続するための判定

例えば、マージ前チェックをBatch APIで実行すると、結果が返るまでPull Requestをマージできません。

このような、ブロッキング処理には、同期Messages APIを使用します。

Batch APIに適した処理

次の処理は、結果が即時に必要ではありません。

  • 夜間のテストコード生成
  • 翌朝までに作成するレポート
  • 週次のコード品質監査
  • 大量のログ分析
  • 大量のドキュメント分類
  • 評価データセットの一括実行
  • リポジトリ全体の定期レビュー

このような非ブロッキングかつレイテンシを許容できる処理には、Message Batches APIが適しています。

ワークフロー 推奨API 理由
マージ前チェック 同期API 結果を待たなければ処理を続けられない
対話型コードレビュー 同期API ユーザーへの即時応答が必要
夜間テスト生成 Batch API 翌朝までに完了すればよい
週次セキュリティ監査 Batch API 即時性よりコストと処理量を重視
大量ドキュメント分類 Batch API 各処理を独立して非同期実行できる

24時間の処理枠を考慮して送信間隔を設計する

Message Batches APIを利用する場合、バッチの処理時間だけでなく、データがバッチへ投入されるまでの待ち時間も考慮します。例えば、処理対象を4時間ごとにまとめてバッチ送信するとします。

最も待ち時間が長いデータは、バッチ送信の直後に到着したデータです。このデータは、次のバッチ送信まで最大4時間待つことになります。さらに、バッチ処理には最大24時間かかる可能性があります。

最大待ち時間
= バッチ投入までの待ち時間 + バッチ処理時間

= 4時間 + 24時間
= 28時間

したがって、正常に処理されたバッチについては、30時間以内という業務目標に対して2時間の余裕を確保できます。

ただし、これはバッチが24時間以内に正常完了することを前提とした計算です。24時間以内に処理されずexpiredになった場合や、APIエラー後の再送時間まで含めて、30時間以内の完了を厳密に保証するものではありません。そのため、実運用では次も設計します。

  • expirederroredを検知する
  • 失敗したリクエストだけ再送する
  • 再送用の時間的余裕を確保する
  • 必要に応じて同期APIへフォールバックする
  • 業務上のSLAとAPIの処理上限を分けて考える

「4時間ごとに送れば30時間以内を保証できる」と単純に考えるのではなく、失敗・期限切れ・再送まで含めた運用設計が必要です。


custom_idでリクエストと結果を対応付ける

バッチ結果は、送信したリクエストと同じ順番で返るとは限りません。そのため、それぞれのリクエストに一意のcustom_idを設定します。

{
  "requests": [
    {
      "custom_id": "document_001",
      "params": {
        "model": "claude-sonnet-4-6",
        "max_tokens": 1024,
        "messages": [
          {
            "role": "user",
            "content": "このドキュメントを要約してください。"
          }
        ]
      }
    },
    {
      "custom_id": "document_002",
      "params": {
        "model": "claude-sonnet-4-6",
        "max_tokens": 1024,
        "messages": [
          {
            "role": "user",
            "content": "このドキュメントからリスクを抽出してください。"
          }
        ]
      }
    }
  ]
}

結果は、例えば次のようなJSONL形式で返ります。

{"custom_id":"document_002","result":{"type":"succeeded","message":{"content":[{"type":"text","text":"抽出結果"}]}}}
{"custom_id":"document_001","result":{"type":"succeeded","message":{"content":[{"type":"text","text":"要約結果"}]}}}

document_002が先に返っているため、配列の位置ではなく、custom_idを使って元のドキュメントと対応付けます。custom_idには、次のような意味の分かる値を使用すると管理しやすくなります。

audit_repo123_file045
document_20260720_001
test_generation_module_auth

custom_idは、1文字以上64文字以下で、英数字、ハイフン、アンダースコアを使用します。


失敗したリクエストだけを再送する

バッチ内の各リクエストは独立して処理されます。結果には、主に次の状態があります。

結果 意味
succeeded 正常終了
errored リクエストエラーまたは内部エラー
canceled バッチのキャンセルにより未処理
expired 24時間以内に処理されなかった

一部のリクエストが失敗しても、成功したリクエストまで再送する必要はありません。

例えば、100件中95件が成功し、5件がコンテキスト上限を超えて失敗した場合、100件すべてを送り直すのではなく、失敗した5件だけを再処理します。

成功した95件
→ 結果を保存

失敗した5件
→ custom_idで特定
→ ドキュメントを分割
→ 5件だけ再送

失敗原因に応じて、次のように修正します。

失敗原因 修正例
コンテキスト上限超過 ドキュメントを複数チャンクに分割
JSON形式の不正 SchemaやPromptを修正
入力パラメータの不正 通常のMessages APIで事前検証
出力不足 max_tokensを調整
一時的な内部エラー 同じリクエストを再送
24時間で期限切れ custom_idで対象を特定⇨新しいBatchで再投入

custom_idは、元のドキュメントやレコードを識別するためのキーです。アプリケーション側でcustom_idと業務データ(ドキュメントIDやファイル名など)の対応関係を管理しておくことで、erroredexpiredとなったリクエストだけを特定し、必要なデータだけを新しいBatchへ再投入できます。


大量投入の前にサンプルでPromptを検証する

大量のデータをいきなりバッチ処理すると、Promptの問題が数千件の出力へ一斉に反映されてしまいます。例えば、10,000件を処理した後に、出力項目が不足していることが判明すると、大量の再処理が必要になります。そこで、次の順序で進めます。

代表サンプルには、正常なデータだけでなく、次のような境界ケースも含めます。

  • 非常に長いドキュメント
  • 必須項目が欠けたドキュメント
  • 表記が一貫していないドキュメント
  • 曖昧または矛盾する記述
  • 抽出対象が存在しないドキュメント
  • 複数の候補値を含むドキュメント

この段階で、次の項目を確認します。

  • 必要な項目が抽出されるか
  • JSON Schemaに準拠しているか
  • False Positiveが多くないか
  • ドキュメントごとの形式差に対応できるか
  • max_tokensが十分か
  • 長い入力を分割する必要がないか

事前にPromptを改善することで、初回処理の成功率を高め、再送によるコストや処理時間を削減できます。


Tool UseとMessage Batches API

Tool Useについては、クライアント側ツールとサーバー側ツールを区別する必要があります。

クライアント側ツール

クライアント側ツールでは、Claudeがtool_useを返した後、アプリケーションがツールを実行し、その結果をtool_resultとして次のMessages APIリクエストへ送信します。

このような外部アプリケーションとの往復処理は、一つのバッチリクエスト内だけでは完結しません。バッチ結果としてtool_useを受け取った後、アプリケーション側でツールを実行し、続きのリクエストを別途送信する必要があります。

サーバー側ツール

現在のMessage Batches APIでは、Anthropic側で実行されるサーバー側ツールを利用できます。例えば、次のようなツールです。

  • Web Search
  • Web Fetch
  • Code Execution
  • MCP Connector
  • Tool Search

サーバー側ツールについては、Anthropic側のバッチワーカーがエージェントループを実行します。このため、「Message Batches APIではTool Useが一切利用できない」は、正確ではありません。正しくは、次のように整理できます。

Tool Useの種類 バッチ内での扱い
サーバー側ツール バッチワーカーがツール実行を含むループを処理可能
クライアント側ツール tool_use受信後、外部アプリケーションで実行し、後続リクエストが必要
事前に履歴を含めたMulti-turn 一つのMessagesリクエストとして送信可能
実行途中に人や外部処理から追加情報を返す対話 単一のバッチリクエストでは完結しない

Exam Guideの「単一リクエスト内でMulti-turn Tool Callingを実行できない」という説明は、主にクライアント側ツールとの動的な往復処理を指すものと思われます(現在のMessage Batches APIでは、Anthropicが提供するServer Toolsについては、バッチ処理内でツール実行を伴うエージェントループがサポートされています)。


実装イメージ

Python SDKでは、概念的には次のようにバッチを作成します。

import anthropic
from anthropic.types.message_create_params import MessageCreateParamsNonStreaming
from anthropic.types.messages.batch_create_params import Request

client = anthropic.Anthropic()

batch = client.messages.batches.create(
    requests=[
        Request(
            custom_id="document_001",
            params=MessageCreateParamsNonStreaming(
                model="claude-sonnet-4-6",
                max_tokens=1024,
                messages=[
                    {
                        "role": "user",
                        "content": "ドキュメントAを要約してください。",
                    }
                ],
            ),
        ),
        Request(
            custom_id="document_002",
            params=MessageCreateParamsNonStreaming(
                model="claude-sonnet-4-6",
                max_tokens=1024,
                messages=[
                    {
                        "role": "user",
                        "content": "ドキュメントBからリスクを抽出してください。",
                    }
                ],
            ),
        ),
    ]
)

print(batch.id)
print(batch.processing_status)

作成直後のprocessing_statusは、通常in_progressです。

処理完了後はendedになり、結果を取得できるようになります。

import time
import anthropic

client = anthropic.Anthropic()

batch_id = "msgbatch_xxxxxxxxx"

while True:
    batch = client.messages.batches.retrieve(batch_id)

    if batch.processing_status == "ended":
        break

    time.sleep(60)

for result in client.messages.batches.results(batch_id):
    print(result.custom_id, result.result.type)

実運用では、無限にポーリングするのではなく、次も実装します。

  • ポーリング間隔の調整
  • 最大待機時間
  • APIエラー時のバックオフ
  • erroredexpiredの抽出
  • 結果の永続化
  • 失敗分のみの再送

4.5章のまとめ

効率的なバッチ処理では、単に大量のリクエストをまとめるだけではなく、次の点を設計します。

1. 結果をすぐに必要とするか判断する
        ↓
2. 同期APIまたはBatch APIを選択する
        ↓
3. SLAからバッチ送信間隔を逆算する
        ↓
4. custom_idで入力と結果を対応付ける
        ↓
5. 失敗したリクエストだけを再送する
        ↓
6. 大量処理の前にサンプルでPromptを改善する

ポイントは以下の通りです。

  • マージ前チェックなどのブロッキング処理には同期APIを使う
  • 夜間処理や週次監査にはMessage Batches APIを使う
  • Batch APIの入力・出力トークン料金は通常APIの50%
  • 多くのバッチは1時間以内に完了するが、最大24時間の処理枠がある
  • バッチ結果の順序は保証されないため、custom_idで対応付ける
  • 成功した処理は再送せず、失敗した処理だけを修正して再送する
  • 大量処理の前に、代表サンプルを同期APIで検証する
  • クライアント側ツールの動的な往復処理は、一つのバッチリクエスト内では完結しない
  • 現在のAPIでは、サーバー側ツールを含むバッチ処理には対応している

4.6 Design multi-instance and multi-pass review architectures

レビュー品質を向上させるための2つのアプローチ

  • マルチインスタンス(Multi-instance)
  • マルチパス(Multi-pass)

について、説明しています。

ここでいう 「Pass(パス)」 とは、「レビューを1回実行する工程(レビューの1ルート・1フェーズ)」のことです。例えば、

  • Per-file Pass:各ファイルを個別にレビューする工程
  • Integration Pass:システム全体をレビューする工程

となります。


全体像

レビューは一度で終わらせるのではなく、

  1. ファイル単位のレビュー
  2. システム全体のレビュー
  3. 検証レビュー

という複数のレビュー工程(Pass)に分割することで、精度を向上させます。


Multi-instance(マルチインスタンス)

生成したコードを、そのまま同じモデルへレビューさせることは推奨されません。理由は、生成時の推論コンテキスト(Reasoning Context)を保持しているため、自分自身の判断を疑いにくいからです。

そのため、生成用Agentレビュー用Agentを分けることが推奨されます。


Multi-pass(マルチパス)

複数ファイルを一度にレビューすると、

  • 注意力が分散する(Attention Dilution)
  • ローカルな問題を見逃す
  • ファイル間の問題と混在する

可能性があります。そのため、レビューを複数のPass(工程)へ分割します。


Pass 1:Per-file Review

各ファイルを個別にレビューします。

この工程では、

  • バグ
  • Nullチェック漏れ
  • セキュリティ問題
  • コーディングミス

など、ファイル内だけで判断できる問題を検出します。


Pass 2:Integration Review

次に、システム全体をレビューします。

ここでは、

  • データフロー
  • API連携
  • モジュール依存
  • ファイル間の整合性

などを確認します。


Pass 3:Verification Review

最後に、レビュー結果そのものを検証します。

各指摘に対して、

{
  "issue": "SQL Injection",
  "severity": "High",
  "confidence": 0.94
}

のようにConfidenceも付与します。Confidenceが低いものだけをHuman Reviewへ回すことができます。


全体フロー


4.6章のポイント

ポイントは次の通りです。

  • 自己レビューには限界があるため、生成時とは独立したClaudeインスタンスでレビューする
  • Pass(レビュー工程)を分割することで、大規模レビューの精度を向上させる
  • Per-file Passではローカルな問題を検出し、Integration Passではファイル間の問題を検出する
  • Verification Passでは各指摘にConfidenceを付与し、人によるレビューが必要な項目を判断する
コード生成
      │
      ▼
独立したClaudeによるレビュー
      │
      ▼
Pass1:Per-file Review
(各ファイルを個別にレビュー)
      │
      ▼
Pass2:Integration Review
(システム全体をレビュー)
      │
      ▼
Pass3:Verification Review
(Confidenceを付与)
      │
      ▼
必要に応じてHuman Review

Pass(パス)とは、「レビューを1回実行する工程(レビューの1ルート・1フェーズ)」を意味します。レビュー対象や目的ごとに工程を分割することで、レビュー品質と検出精度を向上させることができます。

Domain 5: Context Management & Reliability


ドメイン5では、様々な記載方法が出てきますので、最初に全体像を整理します。

Claim-Source Mapping のデータ構造(例)

Provenance(来歴情報)Coordinator の判断情報 は分離して考えます。

  • SubAgent は「事実(Claim)」とその根拠(Provenance)を返す。
  • Coordinator は Finding を統合し、関連度や優先順位を付与する。
  • Synthesis Agent は Provenance を保持したまま最終レポートを生成する。

SubAgent が返す Findingの例

{
  "finding_id": "string",

  "claim": {
    "text": "string",
    "type": "financial_statistic | news_event | technical_finding | other",
    "status": "well_established | contested | uncertain"
  },

  "provenance": {
    "sources": [
      {
        "source_id": "string",
        "source_type": "string",

        "title": "string",
        "document_name": "string | null",
        "url": "string | null",
        "publisher": "string | null",

        "publication_date": "YYYY-MM-DD | null",
        "data_collection_date": "YYYY-MM-DD | null",

        "evidence": {
          "excerpt": "string",
          "page": "number | null",
          "section": "string | null"
        },

        "source_characterization": "string | null",

        "methodological_context": {
          "method": "string | null",
          "sample_scope": "string | null",
          "definition": "string | null",
          "limitations": [
            "string"
          ]
        }
      }
    ]
  },

  "confidence": 0.94,

  "conflict": {
    "has_conflict": false,
    "conflicting_finding_ids": [],
    "description": null
  }
}

Finding の各項目

項目 説明 Anthropicでの位置付け
finding_id Finding を一意に識別するID。Coordinator が重複排除や Conflict 管理を行う際に利用する。 管理情報
claim SubAgent が抽出した主張(Finding)そのもの。 Finding
claim.text 抽出した主張の本文。 Claim
claim.type Finding の種類。例:財務データ、ニュース、技術的知見など。Synthesis Agent が出力形式を決定する際にも利用できる。 Finding分類
claim.status Finding の性質。十分に確立された知見(well_established)、情報源によって見解が分かれるもの(contested)、根拠が十分でないもの(uncertain)を区別する。※CCA-F の責務分離を厳密に考えるなら、Coordinator が付与する属性として扱う設計も考えられる。 品質情報
provenance Claim の来歴(Provenance)全体を保持するオブジェクト。Anthropic が最も重視している部分。 Provenance
sources Claim を裏付ける情報源。複数の情報源で同じ Claim を支持している場合は配列で保持する。 Claim-Source Mapping
source_id 情報源を識別するID。 Source
source_type 情報源の種類(Annual Report、News、Research Paper など)。 Source Metadata
title 情報源のタイトル。 Source Metadata
document_name 文書名やファイル名。 Source Metadata
url 元文書のURL。 Source Metadata
publisher 発行元・公開元。 Source Metadata
publication_date 公開日。時系列の違いを矛盾と誤認しないために保持する。 Temporal Provenance
data_collection_date データ収集日。統計や調査結果では公開日より重要になる場合がある。 Temporal Provenance
evidence Claim の根拠となる引用情報。 Evidence
excerpt 実際の引用文や該当箇所。 Evidence
page 該当ページ。PDF 等の出典を追跡しやすくする。 Citation
section 該当セクションや章。 Citation
source_characterization 情報源の性質。「監査済み年次報告書」「プレスリリース」「ブログ記事」など。Synthesis Agent が情報源の信頼性を適切に表現するために利用する。 Provenance
methodological_context 調査方法や前提条件など、結果を正しく解釈するための文脈情報。 Provenance
method 調査・分析方法。 Methodology
sample_scope 調査対象・サンプル範囲。 Methodology
definition 用語や指標の定義。 Methodology
limitations 調査上の制約や注意事項。 Methodology
confidence SubAgent がその Claim に対して持つ確信度。モデル自身の推定値であり、人手レビューの判断材料となる。※そのまま信用せず、Validation Set による Calibration(校正)を行うことが推奨される。 Quality
conflict 他の Finding と矛盾する情報がある場合の管理情報。Coordinator が統合方針を決定する際に利用する。※厳密な責務分離では Coordinator が付与する属性として扱う設計も考えられる。 Conflict Management
has_conflict 矛盾する Finding が存在するか。 Conflict
conflicting_finding_ids 矛盾している Finding の ID 一覧。 Conflict
description 矛盾内容の説明。例:「統計値が異なる」「調査対象が異なる」「時点が異なる」など。 Conflict

補足

次のような役割分担になります。

SubAgent が返すもの

  • Claim
  • Provenance(Source / Citation / Evidence / Publication Date / Methodological Context)
  • Confidence

Coordinator が付与するもの

  • Relevance Score
  • Priority
  • Merge Group
  • Resolution Strategy
  • Claim Status(Well-established / Contested / Uncertain)
  • Conflict 情報

このように責務を分離することで、

  • SubAgent は事実と根拠(Provenance)の抽出に専念する
  • Coordinator は複数の Finding を比較・評価・統合する
  • Synthesis Agent は Provenance を保持したまま最終レポートを生成する

という Anthropic が推奨するマルチエージェントアーキテクチャに近い設計になります。


Coordinator が付与する情報

Coordinator は SubAgent が返した Finding を受け取り、今回のタスクに対する評価・整理を行います。

{
  "relevance_score": 0.96,
  "priority": "high",
  "merge_group": "financial_results",
  "resolution_strategy": "merge_sources"
}

各項目の説明

項目 説明
relevance_score 現在のユーザー要求に対する関連度
priority 優先度(High / Medium / Low など)
merge_group 同じ Finding として統合するグループ
resolution_strategy Merge・Conflict保持・Human Reviewなど統合方針

Synthesis Agent の役割

Synthesis Agent は Coordinator が決定した方針に従ってレポートを作成します。

重要なのは、Provenance を失わないことです。 つまり、

Claim
    │
    ├── Source
    ├── Citation / Evidence
    ├── Publication Date
    ├── Data Collection Date
    ├── Source Characterization
    └── Methodological Context

という Claim-Source Mapping を保持したまま統合します。


Provenance の構造

Finding
├── Claim
├── Provenance
│   ├── Source
│   ├── Citation
│   ├── Evidence
│   ├── Publication Date
│   ├── Data Collection Date
│   ├── Source Characterization
│   └── Methodological Context
├── Confidence
└── Conflict

ここで Claim-Source Mapping とは、単なる URL や Citation の一覧ではなく、
「どの Claim が、どの Source によって、どの Evidence に裏付けられているか」という 対応関係全体 を意味します。


エージェント全体の役割分担

SubAgent
    │
    ├─ Claim
    ├─ Provenance
    │   ├─ Source
    │   ├─ Citation
    │   ├─ Evidence
    │   ├─ Publication Date
    │   ├─ Data Collection Date
    │   ├─ Source Characterization
    │   └─ Methodological Context
    ├─ Confidence
    └─ Conflict
    │
    ▼
Coordinator
    │
    ├─ Relevance Score付与
    ├─ Priority付与
    ├─ Merge Group決定
    ├─ Conflict判定
    └─ Resolution Strategy決定
    │
    ▼
Synthesis Agent
    │
    ├─ Provenanceを保持したまま統合
    ├─ Well-established と Contested を区別
    ├─ Source Attribution(情報源の帰属) を保持
    ├─ Temporal Information を保持
    ├─ Financial Data → Table
    ├─ News → Prose
    └─ Technical Findings → Structured List

Agentの設計思想

各エージェントの責務を明確に分離します。

Agent 主な責務
SubAgent Finding と Provenance を生成する
Coordinator Finding を評価・優先順位付け・統合方針を決定する
Synthesis Agent Provenance を保持したまま最終レポートを生成する

この責務分離により、

  • Provenance を失わない
  • 矛盾情報を保持できる
  • 時系列情報を維持できる
  • 人が後から検証可能になる

という、 Traceability(追跡可能性)Explainability(説明可能性) を実現できます。

以降、各章の説明になります。

5.1 Context Management & Reliability

これまでの各章では、

  • Prompt設計
  • Tool Use
  • Multi-Agent
  • Session Management

等について説明してきました。

本章では、長時間の対話でも重要な情報を失わないContext Managementの説明になります。

ClaudeやOpenAIなどのLLMでは、会話が長くなるほど過去の情報が失われたり、重要な情報が埋もれたりする問題があります。これを防ぐためにContextを複数のレイヤで管理することを推奨しています。


Context Layerの全体像

Contextは、単なる会話履歴ではなく、役割ごとに整理された複数の情報から構成されます。

Conversation Context
│
├─ Conversation History
│
├─ Case Facts
│
├─ Issue Facts
│
├─ Tool Results
│
├─ SubAgent Findings
│
└─ Coordinator Metadata

それぞれの役割は次のようになります。

レイヤ 役割
Conversation History 会話そのもの
Case Facts 金額・注文番号・日付などの重要情報
Issue Facts 複数案件の管理
Tool Results Toolから取得したデータ
SubAgent Findings SubAgentが抽出した重要事項
Coordinator Metadata 関連度・優先順位・引用情報など

このように役割を分離することで、長い会話でも重要情報を保持できます。


なぜConversation Historyだけでは足りないのか

Conversation Historyだけを保持すれば十分ではなく、

  • 注文番号
  • 金額
  • 日付
  • ステータス

などの重要情報は、要約の中で失われやすくなります。例えば、

元の会話
注文番号:123456
返金額:12,800円
購入日:2025/6/15
配送予定:6/20

これを要約すると、

注文内容を確認済み。
返金対応予定。

となってしまい、数値情報が消えてしまいます。このような情報は Case Factsとして独立管理することを推奨しています。


Progressive Summarizationの注意点

長い会話では、途中で要約(Progressive Summarization)が行われますが、要約を繰り返すほど、細かな情報は失われます。特に失われやすい情報は次のようなものです。

  • 金額
  • 割引率
  • 日付
  • 注文番号
  • 顧客が希望した内容

これらは要約に含めるのではなく、構造化データとして別管理することが重要です。


Lost in the Middle

LLMには、Lost in the Middleという現象がある。長い入力では、先頭と末尾の情報は比較的保持できるが、中央部分の情報は見落とされやすくなリマス。このため、

  • 重要事項を冒頭へ配置する
  • 詳細はセクション分けする
  • 必要な情報だけを残す

ことを推奨しています。


Tool ResultもContextを圧迫する

Contextを消費するのは、会話だけではなく、Tool Resultも大量のトークンを消費します。例えば、注文検索APIが40項目返しても、返金処理で必要なのは、

  • 注文番号
  • 金額
  • ステータス
  • 購入日
  • 配送状況

だけかもしれません。不要な項目をそのまま残すと、Context Windowを無駄に消費します。このため、必要なフィールドだけを保持する設計を推奨しています。


5.1章のまとめ

Task Statement 5.1で重要なのは、「Conversation HistoryだけでContextを管理しない」という考え方です。重要な情報は役割ごとに分離し、長い対話でも失われないように設計することが、信頼性の高いAIエージェントを構築するための基本となります。

ここまで、長時間の対話でも重要な情報を失わないためのContext Managementについて説明してきましたが、Contextを保持できたとしても、AIがすべてを自律的に判断できるとは限りません。

次章5.2では、「どのタイミングで人へ判断を委ねるべきか」というエスカレーション設計について解説しています。

5.2 Design effective escalation and ambiguity resolution patterns

AIエージェントがすべての問い合わせを自律的に解決することが理想ですが、実際には人へ引き継ぐべきケースも存在します。「どのタイミングでエスカレーションするか」を明確に設計することが、信頼性の高いAIエージェントを構築する重要なポイントとなります。

エスカレーションの判断基準と、曖昧な状況での適切な対応方法を以下に記載します。


エスカレーションすべきケース

次のようなケースをエスカレーション対象としています。

  • お客様が人の担当者との対応を明確に希望している
  • ポリシーに該当するルールが存在しない
  • ポリシーの解釈が曖昧である
  • AIだけでは意味のある進展が期待できない

重要なのは、「難しい問題だからエスカレーションする」のではないという点で、判断基準は、AIが正しく判断できるだけの情報やルールが存在するかになります。


人を希望されたらすぐに引き継ぐ

例えば、

💬担当者につないでください。

という依頼があった場合、AIは勝手に調査を始めるべきではありません。

  • 悪い例

💬 まず注文状況を確認します。
💬 配送状況を確認します。
💬 返金状況を確認します。

  • 良い例

💬 承知しました。担当者へおつなぎします。

利用者が明確に人との対応を希望している以上、まずその意思を尊重することが重要です。


軽微な問題なら解決を提案してもよい

一方で、利用者が怒っていても、必ずエスカレーションするとは限りません。例えば、

💬 配送状況が確認できません。

という問い合わせであれば、LLMだけで解決できる可能性があり、この場合は、まず共感を示したうえで、解決策を提案します。

💬 ご不便をお掛けして申し訳ありません。配送状況を確認いたしますので、注文番号を教えていただけますでしょうか。

もし利用者が、

💬 いや、人と話したいです。

と改めて希望した場合には、その時点でエスカレーションします。


感情だけで判断してはいけない

LLMでは、利用者の感情分析(Sentiment Analysis)を利用することがありますが、感情だけをエスカレーションの判断材料にすることは推奨していません。

例えば、

💬 最悪だ!!もう二度と利用しない!!

という発言があっても、配送遅延という単純な問題であれば、LLMだけで解決できる場合があります。逆に、穏やかな文章であっても、契約変更や法的な問題など、LLMでは判断できないケースもあり、感情の強さと問題の難しさは一致しません。


自己申告のConfidenceも判断基準にしない

LLMで出力した「90%の確信」といった Confidence Score の自己評価だけで判断することも推奨していません。Confidenceはモデル自身の推定値であり、実際の正確性を保証するものではないためです。重要なのは、ポリシーに基づいて判断できるかどうかです。


ポリシーが曖昧ならエスカレーションする

例えば、企業の返品ポリシーに、

自社サイトで値下げされた場合は差額を返金します。

と書かれいた場合に、利用者が

💬 他社サイトの方が安いので価格を合わせてください。

と依頼した場合、このケースについては何も記載されていないので、LLMが

💬 「たぶん対応できます」
あるいは
💬 「たぶん対応できません」

と推測するべきではなく、ポリシーが存在しない、または解釈が曖昧な場合には、人へエスカレーションする ことが適切です。


複数候補が見つかった場合は人に確認する

ツール検索で、同じ名前の顧客が複数見つかることがあります。例えば、

Customer
No.x 田中 太郎、...
No.y 田中 太郎、...

という検索結果が返ってきた場合、LLMが「こちらだと思う」と推測してはならず、代わりに追加情報を確認します。

💬 本人確認のため、注文番号、または電話番号を教えていただけますでしょうか。

このように、追加の識別情報(Identifier)を取得することで、誤った顧客を選択するリスクを防ぎます。


Few-shotで判断基準を教える

エスカレーションの判断は、プロンプトだけで説明するよりも、Few-shot Examplesを追加した方が効果的です。

例えば、

ユーザー LLMの対応
担当者につないでください 直ちにエスカレーションする
配送状況を知りたい LLMが対応する
他社価格に合わせてほしい ポリシー未定義のためエスカレーションする
同姓同名が複数見つかった 追加の識別情報を確認する

このような具体例をシステムプロンプトへ含めることで、LLMは状況ごとの適切な対応を学習しやすくなります。


5.2本章のまとめ

「エスカレーションを感情や難易度ではなく、明確なルールに基づいて判断すること」 です。

ポイントを整理すると以下になります。

  • 利用者が人との対応を希望した場合は、まずその意思を尊重する
  • AIで解決可能な問題は、共感を示しながら自律的に対応する
  • 感情分析や自己申告のConfidence Scoreだけを判断基準にしない
  • ポリシーが存在しない、または解釈が曖昧な場合はエスカレーションする
  • ツール検索で複数候補が見つかった場合は、追加の識別情報を確認し、推測で選択しない
  • Few-shot Examplesを用いて、エスカレーション基準を具体例としてシステムプロンプトへ組み込む

適切なエスカレーション設計により、LLMは判断できないケースを人へ引き継げます。
一方で、マルチエージェントシステムでは、人へ引き継ぐ前に、エージェント同士で適切にエラーを伝達し、可能な限り自律的に復旧する仕組みも重要になります。
次章5.3では、Error Propagationについて解説しています。

5.3 Implement error propagation strategies across multi-agent systems

マルチエージェントシステムでは、すべてのSubAgentが常に正常に動作するとは限りません。例えば、

  • APIのタイムアウト
  • データベースへの接続失敗
  • 外部サービスの一時的な障害
  • 検索結果が存在しない

など、さまざまな状況が発生するため、エラーを単に通知するのではなく、「次の判断に利用できる情報」としてCoordinatorへ伝えること を推奨しています。


Error Propagationとは

Error Propagationとは、SubAgentが発生したエラーの内容をCoordinatorが適切に判断できる形で伝える仕組みです。単に、「Search Failed」と返すだけでは、Coordinatorは次に何をすればよいか判断できないので、

  • 何を検索したのか
  • どのようなエラーだったのか
  • 一部成功した結果はあるか
  • 他に試せる方法はあるか

まで含めて返します。これがStructured Error Contextになります。


エラーにも種類がある

すべてのエラーを同じように扱かってはいけません。例えば、APIへ接続できなかった場合と、検索した結果が0件だった場合では意味が異なるためです。

状況 意味
API Timeout アクセス失敗
Network Error アクセス失敗
認証エラー アクセス失敗
検索結果0件 正常終了(該当なし)

検索した結果、一致する注文が存在しなかった場合、これはエラーではなく検索は正常に完了しています。つまり、「アクセスできなかった」のか、「アクセスできたが該当データが存在しなかった」のか を区別することが重要になります。


Generic Errorを避ける

悪い例として、SubAgentが「Search unavailable」だけ返したとすると、Coordinatorでは、

  • APIが停止したのか
  • タイムアウトなのか
  • 認証エラーなのか
  • データが存在しないのか

分からず、このようなGeneric Error では、Coordinatorは適切な復旧方法を判断できません。


Structured Error Context

エラーは、Coordinatorが判断できる構造体で返します。例えば、

Failure Type
・Timeout
Attempted Query
・Order ID = 12345
Partial Results
・Customer情報までは取得済み
Alternative
・Retry
・Search by Email

のような情報があれば、Coordinatorは

  • 再試行する
  • 別の検索方法を試す
  • 他のSubAgentへ依頼する

などの判断が可能になります。


SubAgentはまず自分で復旧を試みる

SubAgentのエラーは、すぐにCoordinatorへ返すことは推奨しておらず、まずは、SubAgent自身が復旧を試みます。例えば、

  • 一時的な通信障害
  • API Timeout
  • Rate Limit

などは、リトライだけで解決する場合があります。


自分で解決できない場合だけ伝搬する

一方で、Retryしても失敗した場合は、Coordinatorへエラーを返します。このように、SubAgentが解決できる問題はローカルで処理し、解決できなかった場合だけCoordinatorへ伝えることで、システム全体の効率が向上します。


エラーを隠してはいけない

悪い設計として、エラーを隠してしまうケースがあります。例えば、検索に失敗したにもかかわらず、

検索結果
0件

として返してしまうと、Coordinatorは「検索は成功した」と誤解します。これは、Silent Failureと呼ばれる代表的なアンチパターンです。


一つの失敗で全体を止める必要もない

逆に、一つのSubAgentが失敗しただけで、全体の処理を終了してしまうことも推奨されません。例えば、4つの情報源を調査する場合、

News
Annual Report
Research Paper
Official Blog

のうち、Research Paperだけ取得できなかったとしても、残り3つから十分なレポートを作成できる場合があります。そのため、一部失敗した場合でも、利用可能な情報を使って処理を継続することが重要です。


Coverageを明示する

ただし、利用できなかった情報源がある場合は、そのことを利用者へ伝える必要がります。例えば、

調査結果
〇 年次報告書
〇 ニュース記事
〇 公式ブログ
× 学術論文(取得できませんでした)

というように、どこまで調査できたのかを明示します。このような情報をCoverage Annotationとして保持することを推奨しています。これにより、利用者は、「結論は十分な情報に基づいているのか」、「まだ不足している情報があるのか」を判断できます。


5.3章のまとめ

重要なのは、「エラーも重要なコンテキストとして扱う」という考え方です。

ポイントは以下の通りです。

  • エラーは単なる失敗ではなく、Coordinatorの次の判断材料となる情報である
  • 「アクセス失敗」と「検索結果が存在しない」を明確に区別する
  • 「Search unavailable」のような曖昧なエラーメッセージではなく、Failure Type・Attempted Query・Partial Results・Alternativeを含むStructured Error Contextとして返す
  • SubAgentは一時的な障害に対してはローカルでリトライし、自身で解決できない場合のみCoordinatorへエラーを伝搬する
  • エラーを成功として扱うSilent Failureや、一つの失敗でワークフロー全体を停止する設計はアンチパターンである
  • 利用できなかった情報源がある場合は、Coverage Annotationとして調査範囲や不足部分を明示し、利用者が結果の信頼性を判断できるようにする

エラーを適切に伝達できても、長時間の探索によってContextそのものが劣化してしまえば、LLMは正しい判断を続けられません。次章5.4では、大規模コードベースを長時間探索する際のContext Managementについて解説しています。

5.4 Manage context effectively in large codebase exploration

小規模なプロジェクトであれば、AIエージェントは会話履歴だけでも十分に状況を把握できますが、数百〜数千ファイル規模のコードベースを解析する場合は事情が異なり、長時間の探索では、

  • Context Windowがいっぱいになる
  • 過去の重要な情報を忘れてしまう
  • 発見済みの内容を再調査してしまう

といった問題が発生するため、探索結果を適切に保持しながら、Contextを効率よく管理する ことを推奨しています。


長時間の探索で発生するContext Degradation

長時間セッションでは、LLMの回答品質は徐々に低下することがあります。例えば、探索の前半では、

PaymentService
RefundRepository
RefundController

を正確に発見していたにもかかわらず、数時間後には

一般的なECシステムでは、通常はPaymentServiceのようなクラスがあります。

というように、実際に調査した内容ではなく、一般論で回答してしまうことがあります。これをContext Degradation と呼び、Contextが長くなるほど、モデルは発見した具体的な情報よりも一般的な知識に頼りやすくなる。


Scratchpadで重要な情報を保持する

この問題を防ぐため、Scratchpad の利用を推奨しています。Scratchpadとは、探索中に見つけた重要事項を記録するメモです。例えば、

Refund Flow
・RefundController
・RefundService
・RefundRepository
・PaymentGateway

というように、重要な情報だけを整理して保存します。次の探索では、長い会話履歴を参照するのではなく、Scratchpadを読み込むことで、必要な情報をすぐに利用できるようになります。


SubAgentへ探索を分担する

巨大なコードベースでは、一つのエージェントがすべてを調査するよりも、SubAgentへ分担した方が効率的です。例えば、

・SubAgent A
  テストコードを調査
・SubAgent B
  返金処理を調査
・SubAgent C
  依存関係を解析

のように役割を分割します。メインエージェントは、各SubAgentの結果だけを受け取り、全体を統合することにより、大量の探索ログがメインのContextへ流入することを防げます。


探索フェーズごとに要約を作成する

探索が終了したら、次の調査へ進む前に要約を作成します。

(例)Phase1 Summary
・返金処理を特定
・Controller〜Repositoryを確認
・PaymentGateway依存あり

次の探索では、このSummaryを最初のContextとして渡すことにより、新しいSubAgentは過去の調査結果を理解した状態で探索を開始できます。


/compactでContextを整理する

Claude Codeには、Contextを圧縮する /compact コマンドがあります。長時間の探索では、詳細な調査ログが大量に蓄積されてしまうので、重要な情報が埋もれてしまいます。/compact を実行することで、不要な探索ログを削減し、重要な情報を中心としたContextへ整理できます。長時間のコード解析では、定期的に利用すると効果的です。


Manifestによる状態保存

長時間の解析では、途中でセッションが終了したり、PCが再起動したりすることもあり得るので、各エージェントが現在の状態を保存する ことを推奨しています。例えば、

manifest
・解析済みディレクトリ
・発見した主要モジュール
・未調査エリア
・Scratchpadの場所

といった情報を保存します。Coordinatorは、再開時にManifestを読み込み、各エージェントへ必要な情報を渡することにより、最初から探索をやり直す必要がなくなります。


Crash Recovery

Manifestを利用すると、途中で作業が中断されても、探索を継続できます。

Project Analysis

Agent State Export

Manifest

Resume

Coordinator

Continue Exploration

このように、解析状況を構造化して保持することで、長時間に及ぶ探索でも効率よく作業を継続できるようにします。


5.4章のまとめ

重要なのは、「長時間のコード探索では、会話履歴だけに依存しないこと」という考え方です。

ポイントは以下の通り。

  • 長時間の探索では、Context Degradationにより、モデルが以前発見した具体的な情報ではなく一般論を返すことがある
  • Scratchpadへ重要事項を記録し、後続の探索で再利用することで、重要な知見を維持できる
  • 詳細な探索はSubAgentへ委譲し、メインエージェントは全体の調整と統合に専念する
  • 探索フェーズごとにSummaryを作成し、次のフェーズの初期Contextとして利用することで、Contextの劣化を防げる
  • /compact を活用して不要な探索ログを整理し、限られたContext Windowを有効活用する
  • Manifestへ解析状況を保存し、Coordinatorが再開時に読み込むことで、Crash Recoveryや長期間の解析を効率的に実現できる

Contextを適切に維持することで、長時間の解析でもAIは一貫した判断を続けられますが、Contextが維持されていても、LLMの判断そのものが正しいとは限りません。

次章5.5では、人によるレビューとConfidence Calibrationについて解説しています。

5.5 Human Review WorkflowとConfidence Calibration

LLMは非常に高い精度で情報を抽出できるが、「精度が97%あるから人による確認は不要」 とは言えません。LLMの出力をどのように人がレビューし、どのような基準で自動化を進めるか という運用設計も重要です。

Human Review Workflow(人によるレビュー)と、Confidence Calibration(信頼度校正)について整理しています。


全体精度だけでは品質は判断できない

例えば、請求書や契約書など10種類の帳票をLLMが処理し、全体では、「Accuracy=97%」という結果だったとしても帳票ごとに見ると、

ドキュメント 精度
請求書 99%
領収書 98%
発注書 98%
契約書 84%

となっている可能性があります。このように、全体精度だけを見ると高性能に見えても、契約書だけを見るとまだ十分な品質ではなく、Aggregate Accuracy(全体精度)だけでは問題を発見できないことがあります。


フィールドごとの精度も確認する

さらに、帳票全体ではなく、抽出する項目(Field)ごとの精度も確認する必要があります。例えば、
請求書で、

項目 精度
請求番号 99.8%
金額 99.5%
日付 98.9%
支払期限 89.2%

となった場合、もし支払期限だけ精度が低いのであれば、その項目だけ人のレビュー対象にすれば良いことになります。このような Field-Level Analysis を推奨しています。


Confidence Scoreは項目ごとに持つ

LLMは、抽出結果に対してConfidence Scoreを出力できます。例えば、

・請求番号 0.99
・請求金額 0.98
・支払期限 0.63

ように、項目ごとにConfidenceを持つことで、どこを重点的にレビューすべきか判断できます。重要なのは、文書全体ではなく、Field単位でConfidenceを管理すること です。


Confidenceはそのまま信用しない

ただし、Confidence Scoreはモデル自身による推定値であるので、Confidenceが0.99だからといって、99% 正しいことを意味するわけではありません。例えばモデルでは、Confidence 0.95以上でも、実際の正答率が90%しかない場合がありますし、逆に、Confidence 0.70でも実際には98%正しいケースもあり得ます。そのため、Confidence Calibration を推奨しています。


Calibration(校正)とは

Calibrationとは、Confidence Scoreと実際の正答率を一致させる調整作業です。例えば、検証データ(Validation Set)を利用して、

Confidence 実際の正答率
0.99 99%
0.95 96%
0.90 91%
0.80 80%

という関係を確認し、この結果を基に、レビュー対象となる閾値(Threshold)を決定します。例えば、

Confidence
0.90以上 ⇨ 自動承認
0.90未満 ⇨ Human Review

というように運用します。


Validation Setで評価する

Calibrationを行うためには、正解データを持つ Validation Setが必要となります。LLMが出力した結果を比較することで、実際の精度を測定できます。このような評価を継続することで、Confidence Scoreを現実の精度へ近づけられます。


Stratified Random Sampling

すべてのデータを人がレビューすることは非現実的であるため、Stratified Random Sampling(層化ランダムサンプリング)を推奨しています。例えば、Confidenceが高いデータでも、一定割合だけをランダムに抽出してレビューします。

High Confidence

Random Sampling

Human Review

Error Measurement

これにより、普段は見逃されてしまう新しい誤りパターン(Novel Error Pattern)を発見できます。


レビュー対象を優先順位付けする

人がレビューできる件数には限りがあるため、すべてを同じ優先度で確認するのではなく、レビュー対象を絞り込む必要があります。例えば、優先順位を次のようにします。

優先度 レビュー対象
Confidenceが低い項目
元文書に矛盾がある
判読が難しい文書
新しい帳票フォーマット
高Confidenceかつ十分に検証済みの帳票

限られた人のレビュー工数を、本当に必要なケースへ集中できるます。


人によるレビューを前提に設計する

LLMだけで完全自動化することを目的とせず、AIが得意な部分は自動化し、判断が難しいケースだけを人へ回すことが必要です。例えば、

  • Confidenceが低い
  • 元文書が不鮮明
  • 複数の解釈が存在する
  • 情報源同士が矛盾している

ような場合に、人のレビューに回します。これにより、品質を維持しながらレビュー工数を削減できます。


5.5章のまとめ

重要なのは、「AIの精度を正しく測定し、人によるレビューを効率的に設計すること」です。

ポイントは以下の通りです。

  • 全体精度(Aggregate Accuracy)だけでは品質を判断せず、ドキュメント種類やフィールド単位でも精度を分析する
  • モデルにはField-Level Confidence Scoreを出力させ、レビュー対象の優先順位付けに活用する
  • Confidence Scoreはそのまま信用せず、Validation Setを用いてCalibrationを行い、実際の正答率との対応関係を確認する
  • Confidenceが高い結果についても、Stratified Random Sampling(層化ランダムサンプリング)で継続的にレビューし、新たな誤りパターンを早期に発見する
  • Confidenceが低い項目や、曖昧・矛盾した文書を優先的にHuman Reviewへルーティングし、限られたレビュー工数を効率的に活用する

Human Reviewを効率化するためには、LLMが「なぜその結論に至ったのか」を後から確認できなければならず、そのためには、情報源との対応関係を保持するProvenanceが重要です。

次章5.6では、マルチソース統合におけるProvenanceについて解説しています。

5.6 Preserve information provenance and handle uncertainty in multi-source synthesis

AIエージェントが複数の情報源を調査し、1つのレポートへまとめる場面は、

  • 企業分析
  • 技術調査
  • 市場調査
  • RAGによる文書検索
  • マルチエージェントによるリサーチ

など多くあります。しかし、単純に要約を繰り返すだけでは、「どの情報が、どの情報源に基づいているのか」という重要な情報が失われてしまいます。このような情報の来歴を Provenance(プロベナンス) と呼び、マルチエージェントシステムにおいて最も重要な情報の一つと位置付けています。


Provenanceとは

Provenanceとは、情報の出所や根拠を追跡できる状態 を指します。例えば、

2025年度の売上は15%増加した。

という文章だけでは、誰が発表したのか、どの資料に記載されていたのか分かりません。一方で、

2025年度の売上は15%増加した。
出典
 Annual Report 2025
 P.32

であれば、後から根拠を確認できます。このような、Claim(主張)とSource(情報源)の対応関係 を保持することが、Provenanceの基本的な考え方です。


Claim-Source Mappingを保持する

要約だけを受け渡すことは推奨しておらず、例えば、SubAgentが

売上は15%増加した。

だけを返してしまうと、CoordinatorやSynthesis Agentは、その根拠を確認できなくなります。代わりに、少なくとも次の情報を保持します。

Claim
Source URL
Document Name
Relevant Excerpt

これをClaim-Source Mappingと呼び、Synthesis Agentは、この対応関係を保持したまま最終レポートを作成します。


要約でSource Attributionを失わない

長いレポートでは何度も要約が行われ、このときSource Attribution(情報源との対応付け)が失われると、「どの情報源がどの主張を裏付けているのか」が分からなくなります。例えば、

【悪い例】
複数の調査では、市場規模は2.5兆円とされている。
【良い例】
市場規模は2.5兆円。
出典
 IDC
 Market Report 2025

というように、要約後も情報源を保持します。


矛盾する情報は残す

複数の情報源を調査すると、信頼できる情報源でも同じ項目で違う値が抽出される場合もあります(矛盾する情報)。例えば、

情報源 市場規模
IDC 2.3兆円
Gartner 2.8兆円

この場合、LLMが「2.5兆円くらいだろう」と勝手に平均を取ったり、一方だけを採用したりしてはなりません。矛盾する情報はConflictとして両方保持することを推奨しています。

例えば、

IDC 2.3兆円
Gartner 2.8兆円
Conflict

というように、両方の情報を残す。どちらを採用するかは、Coordinatorまたは人が判断します。


時系列情報も保持する

時系列情報の場合、数値が異なっていても、必ずしも矛盾とは限りません。

情報源 公開日 市場規模
IDC 2024年 2.3兆円
Gartner 2025年 2.8兆円

上記の場合、単純に時点が異なるだけなので、Publication Date(公開日)やData Collection Date(データ収集日)を保持することを推奨しています。これにより、時系列の違いを矛盾と誤認することを防ぐ ことができます。


Methodological Contextも保持する

統計値が異なる理由は、調査方法の違いである可能性もあります。例えば、

IDC 国内市場のみ
Gartner グローバル市場

では、市場規模が異なるのは当然であり、調査方法や対象範囲などのMethodological Contextを保持することで、Synthesis Agentは情報源の違いを正しく理解できます。


Well-establishedとContestedを区別する

最終レポートでは、すべての情報を同じように扱うのではなく、情報の確実性を区別します。例えば、

「Well-established」 複数情報源が一致
「Contested」情報源によって値が異なる

というように整理し、どの情報が十分に裏付けられているかを理解できるようにします。


情報の種類に応じて出力形式を変える

すべてを同じ文章形式で出力せず、情報の種類に応じて、最も理解しやすい形式を選択します。例えば、

情報 推奨形式
財務データ 表形式
ニュース 文章
技術調査 箇条書き・構造化リスト

ように、情報に適した形式を選択することで、レポート全体の可読性と理解しやすさが向上します。


5.6章のまとめ

重要なのは、「要約しても情報の根拠(Provenance)を失わないこと」です。

ポイントは以下の通りです。

  • SubAgentは、Claimだけではなく、Source URL・Document Name・Relevant Excerptなどを含むClaim-Source Mappingを出力する
  • Synthesis Agentは、要約や統合を行う際も、ClaimとSourceの対応関係(Source Attribution)を保持する
  • 信頼できる情報源同士で数値が異なる場合は、一方を勝手に採用せず、Conflictとして明示的に保持する
  • Publication DateやData Collection Dateを含めることで、時系列の違いを矛盾と誤認しないようにする
  • 調査方法や対象範囲などのMethodological Contextを保持し、情報の背景も説明できるようにする
  • 最終レポートでは、Well-establishedな情報とContestedな情報を区別し、財務データ・ニュース・技術情報など、内容に応じて最適な表現形式を選択する

「正しい答えを出すこと」だけでなく、「その答えがどの情報源に基づいているかを追跡できること」が、信頼性の高いマルチエージェントシステムに不可欠な要件です。

おわりに

Claudeのディレクトリ構成のサンプル

本解説書が、CCAR-Fの試験合格にお役くに立てれば幸いです。また、内容は試験対策以外にも実業務でも十分に役立つと思いますのでClaude Code/Coworkの活用がますます進むことも期待しています。

my-project/
│
├── CLAUDE.md                    # プロジェクト全体のコンテキスト・ルール
│
├── .mcp.json                    # プロジェクトで利用するMCPサーバー定義
│
├── .claude/
│   ├── settings.json            # プロジェクト共通設定(Hooks、Permissions等)
│   ├── settings.local.json      # ローカル専用設定(通常Git管理しない)
│   │
│   ├── commands/                # カスタムスラッシュコマンド
│   │   ├── review.md
│   │   ├── release.md
│   │   └── deploy.md
│   │
│   ├── skills/                  # Claude Skills
│   │   ├── architecture/
│   │   ├── testing/
│   │   └── security/
│   │
│   ├── hooks/                   # Hookで実行するスクリプト
│   │   ├── check_refund.py
│   │   ├── lint.sh
│   │   └── notify.py
│   │
│   └── rules/                   # (任意)ルールやプロンプトテンプレート
│       ├── coding.md
│       ├── security.md
│       └── review.md
│
├── scripts/                     # CLI・自動化スクリプト
│   ├── build.sh
│   ├── deploy.sh
│   └── release.sh
│
├── Makefile                     # make build / make test 等
├── package.json
├── src/
├── tests/
└── docs/

本解説書が、CCA-Fの試験合格にお役くに立てれば幸いです。また、内容は試験対策以外にも実業務でも十分に役立つと思いますのでClaude Code/Coworkの活用がますます進むことも期待しています。

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?