Claude Platform Docs
Messagesモデルの機能

検索結果

ソース帰属付きの検索結果を提供することで、RAGアプリケーションで自然な引用を有効にします

検索結果コンテンツブロックを使用すると、ClaudeはWeb検索結果を引用するのと同じ方法で、あなた自身のコンテンツを引用できます。各引用には、あなたが提供したソースとタイトルが含まれます。Claudeが回答をあなたのドキュメントに帰属させる必要がある「Retrieval-Augmented Generation」(検索拡張生成)、すなわちRAGアプリケーションで使用してください。

Claude Haiku 3を除く、すべてのアクティブなモデルが引用付きの検索結果をサポートしています。ベータヘッダーは不要です。検索結果は標準のMessages APIの一部です。

仕組み

検索結果は2つの方法で提供できます。

  1. ツール呼び出しから: カスタムツールが検索結果を返し、動的なRAGアプリケーションを実現します
  2. トップレベルコンテンツとして: 事前取得済みまたはキャッシュ済みのコンテンツについて、ユーザーメッセージ内で検索結果を直接提供します

どちらの場合も、引用が有効になっていれば、Claudeは検索結果を自動的に引用します。特別なプロンプトは必要ありません。質問をするだけで、あなたのコンテンツを参照するテキストブロックに引用が表示されます。

検索結果のスキーマ

検索結果は次の構造を使用します。

{
  "type": "search_result",
  "source": "https://example.com/article", // Required: Source URL or identifier
  "title": "Article Title", // Required: Title of the result
  "content": [
    // Required: Array of text blocks
    {
      "type": "text",
      "text": "The actual content of the search result..."
    }
  ],
  "citations": {
    // Optional: Citation configuration
    "enabled": true // Enable/disable citations for this result
  }
}

必須フィールド

フィールド説明
typestring"search_result" である必要があります
sourcestringコンテンツのソース。安定した文字列であれば何でも使用できます。URL、または kb://article-1234 のような内部識別子など
titlestring検索結果の説明的なタイトル
contentarray実際のコンテンツを含むテキストブロックの配列

オプションフィールド

フィールド説明
citationsobjectenabled ブール値フィールドを持つ引用設定。引用はデフォルトで無効です。このページのすべての例では "enabled": true を明示的に設定しています。リクエスト内のすべての検索結果は同じ設定を使用する必要があります(引用の制御を参照)
cache_controlobjectキャッシュ制御設定(例:{"type": "ephemeral"}

content 配列の各項目は、次を持つテキストブロックである必要があります。

  • type"text" である必要があります
  • text:実際のテキストコンテンツ(空でない文字列)

検索結果はテキストのみを保持します。画像やその他のメディアは content 配列内ではサポートされていません。

方法1:ツール呼び出しからの検索結果

カスタムツールから検索結果を返すことで、動的なRAGアプリケーションが実現します。ツールは実行時にコンテンツを取得し、Claudeはそれを応答内で引用します。次の例では、tool_choice を使用してツール呼び出しを強制しているため、検索ステップが毎回実行されます。

例:ナレッジベースツール

from anthropic.types import (
    MessageParam,
    TextBlockParam,
    SearchResultBlockParam,
    ToolResultBlockParam,
)

client = Anthropic()

# ナレッジベース検索ツールを定義
knowledge_base_tool = {
    "name": "search_knowledge_base",
    "description": "Search the company knowledge base for information",
    "input_schema": {
        "type": "object",
        "properties": {"query": {"type": "string", "description": "The search query"}},
        "required": ["query"],
    },
}


# ツール呼び出しを処理する関数
def search_knowledge_base(query):
    # ここに検索ロジックを記述
    # 正しい形式で検索結果を返す
    return [
        SearchResultBlockParam(
            type="search_result",
            source="https://docs.company.com/product-guide",
            title="Product Configuration Guide",
            content=[
                TextBlockParam(
                    type="text",
                    text="To configure the product, navigate to Settings > Configuration. The default timeout is 30 seconds, but can be adjusted between 10-120 seconds based on your needs.",
                )
            ],
            citations={"enabled": True},
        ),
        SearchResultBlockParam(
            type="search_result",
            source="https://docs.company.com/troubleshooting",
            title="Troubleshooting Guide",
            content=[
                TextBlockParam(
                    type="text",
                    text="If you encounter timeout errors, first check the configuration settings. Common causes include network latency and incorrect timeout values.",
                )
            ],
            citations={"enabled": True},
        ),
    ]


# ユーザーの質問から始めて、会話をリストとして構築
messages = [
    MessageParam(role="user", content="How do I configure the timeout settings?")
]

# ツールを指定してメッセージを作成
response = client.messages.create(
    model="claude-opus-5",
    max_tokens=1024,
    tools=[knowledge_base_tool],
    tool_choice={"type": "tool", "name": "search_knowledge_base"},
    messages=messages,
)

# Claudeがツールを呼び出したら、検索結果を提供します。
# tool_useブロックが常に先頭とは限らないため、反復して探します。
tool_use = next((block for block in response.content if block.type == "tool_use"), None)
if tool_use is not None:
    tool_result = search_knowledge_base(tool_use.input["query"])

    # Claudeのターン、続いてツール結果を進行中の会話に追加
    messages.append(MessageParam(role="assistant", content=response.content))
    messages.append(
        MessageParam(
            role="user",
            content=[
                ToolResultBlockParam(
                    type="tool_result",
                    tool_use_id=tool_use.id,
                    content=tool_result,  # Search results go here
                )
            ],
        )
    )

    # ツール結果を送り返す
    final_response = client.messages.create(
        model="claude-opus-5",
        max_tokens=1024,
        messages=messages,
    )
    print(final_response)

方法2:トップレベルコンテンツとしての検索結果

ユーザーメッセージ内で検索結果を直接提供することもできます。これは次のような場合に便利です。

  • 検索インフラストラクチャから事前取得したコンテンツ
  • 以前のクエリからキャッシュされた検索結果
  • 外部検索サービスからのコンテンツ
  • テストと開発

例:直接の検索結果

from anthropic.types import MessageParam, TextBlockParam, SearchResultBlockParam

client = Anthropic()

# ユーザーメッセージ内で検索結果を直接提供
response = client.messages.create(
    model="claude-opus-5",
    max_tokens=1024,
    messages=[
        MessageParam(
            role="user",
            content=[
                SearchResultBlockParam(
                    type="search_result",
                    source="https://docs.company.com/api-reference",
                    title="API Reference - Authentication",
                    content=[
                        TextBlockParam(
                            type="text",
                            text="All API requests must include an API key in the Authorization header. Keys can be generated from the dashboard. Rate limits: 1000 requests per hour for standard tier, 10000 for premium.",
                        )
                    ],
                    citations={"enabled": True},
                ),
                SearchResultBlockParam(
                    type="search_result",
                    source="https://docs.company.com/quickstart",
                    title="Getting Started Guide",
                    content=[
                        TextBlockParam(
                            type="text",
                            text="To get started: 1) Sign up for an account, 2) Generate an API key from the dashboard, 3) Install our SDK using pip install company-sdk, 4) Initialize the client with your API key.",
                        )
                    ],
                    citations={"enabled": True},
                ),
                TextBlockParam(
                    type="text",
                    text="Based on these search results, how do I authenticate API requests and what are the rate limits?",
                ),
            ],
        )
    ],
)

print(response)

引用付きのClaudeの応答

検索結果がどのように提供されたかに関係なく、Claudeは検索結果の情報を使用する際に自動的に引用を含めます。

{
  "role": "assistant",
  "content": [
    {
      "type": "text",
      "text": "All API requests must include an API key in the Authorization header. Keys can be generated from the dashboard.",
      "citations": [
        {
          "type": "search_result_location",
          "cited_text": "All API requests must include an API key in the Authorization header. Keys can be generated from the dashboard. Rate limits: 1000 requests per hour for standard tier, 10000 for premium.",
          "source": "https://docs.company.com/api-reference",
          "title": "API Reference - Authentication",
          "search_result_index": 0,
          "start_block_index": 0,
          "end_block_index": 1
        }
      ]
    },
    {
      "type": "text",
      "text": "\n\nTo set this up from scratch, you'll need to "
    },
    {
      "type": "text",
      "text": "sign up for an account, generate an API key from the dashboard, install the SDK using `pip install company-sdk`, and initialize the client with your API key.",
      "citations": [
        {
          "type": "search_result_location",
          "cited_text": "To get started: 1) Sign up for an account, 2) Generate an API key from the dashboard, 3) Install our SDK using pip install company-sdk, 4) Initialize the client with your API key.",
          "source": "https://docs.company.com/quickstart",
          "title": "Getting Started Guide",
          "search_result_index": 1,
          "start_block_index": 0,
          "end_block_index": 1
        }
      ]
    }
  ]
}

引用フィールド

各引用には次が含まれます。

フィールド説明
typestring検索結果の引用では常に "search_result_location"
sourcestring元の検索結果のソース
titlestring または null元の検索結果のタイトル
cited_textstring引用されたブロックの全文を連結したもの。content[start_block_index:end_block_index] の内容を結合したものと等しくなります。出力トークンにはカウントされません。
search_result_indexintegerリクエスト内のすべての search_result ブロックの中での、引用された検索結果の0始まりのインデックス。出現順(すべてのメッセージとツール結果にわたって)で数えます。
start_block_indexinteger検索結果の content 配列内で最初に引用されたブロックの0始まりのインデックス。
end_block_indexinteger検索結果の content 配列内で引用されたブロック範囲の排他的な終了インデックス。常に start_block_index より大きくなります。

ブロックインデックスは検索結果の content 配列のスライスを識別し、cited_text はそのスライスの全文です。テキストブロックは引用可能な最小単位です。Claudeはブロック内の部分文字列ではなく、ブロック全体を引用します。より細かい粒度の引用を得るには、検索結果のコンテンツをより小さなブロックに分割してください(複数のコンテンツブロックを参照)。

複数のコンテンツブロック

検索結果は content 配列内に複数のテキストブロックを含めることができます。

{
  "type": "search_result",
  "source": "https://docs.company.com/api-guide",
  "title": "API Documentation",
  "content": [
    {
      "type": "text",
      "text": "Authentication: All API requests require an API key."
    },
    {
      "type": "text",
      "text": "Rate Limits: The API allows 1000 requests per hour per key."
    },
    {
      "type": "text",
      "text": "Error Handling: The API returns standard HTTP status codes."
    }
  ],
  "citations": { "enabled": true }
}

レート制限のブロックを参照する引用は次のようになります。

{
  "type": "search_result_location",
  "cited_text": "Rate Limits: The API allows 1000 requests per hour per key.",
  "source": "https://docs.company.com/api-guide",
  "title": "API Documentation",
  "search_result_index": 0,
  "start_block_index": 1,
  "end_block_index": 2
}

この検索結果が引用されると、start_block_indexend_block_index が引用の対象となるブロックを識別し、cited_text にはまさにそれらのブロックのテキストが含まれます。コンテンツをより小さく焦点を絞ったブロックに分割すると、Claudeはより細かい引用境界を得られます。コンテンツを1つのブロックにまとめると、すべての引用が全文を返すことになります。これは、引用機能のカスタムコンテンツドキュメントで使用されているのと同じモデルです。

高度な使用方法

両方の方法の組み合わせ

同じ会話内で両方の方法を混在させることができます。Claudeはどちらのソースからも引用し、search_result_index はソースに関係なく、リクエスト内の順序ですべての search_result ブロックをカウントします。

次の例は完全な会話を再現しています。最初のユーザーメッセージには事前取得した検索結果が含まれ、アシスタントのターンでナレッジベースツールが呼び出され、ツール結果が2つ目の検索結果を返します。Claudeの回答は両方のソースを引用します。

from anthropic.types import (
    MessageParam,
    SearchResultBlockParam,
    TextBlockParam,
    ToolResultBlockParam,
    ToolUseBlockParam,
)

client = Anthropic()

knowledge_base_tool = {
    "name": "search_knowledge_base",
    "description": "Search the company knowledge base for information",
    "input_schema": {
        "type": "object",
        "properties": {"query": {"type": "string", "description": "The search query"}},
        "required": ["query"],
    },
}

# 検索結果を両方の方法で提供する会話を再現します。最初の
# ユーザーメッセージには事前取得した結果が含まれ、ツール結果は別の結果を返します
response = client.messages.create(
    model="claude-opus-5",
    max_tokens=1024,
    tools=[knowledge_base_tool],
    messages=[
        MessageParam(
            role="user",
            content=[
                SearchResultBlockParam(
                    type="search_result",
                    source="https://docs.company.com/overview",
                    title="Product Overview",
                    content=[
                        TextBlockParam(
                            type="text",
                            text="Acme Dashboard is a monitoring tool for distributed systems. It supports real-time alerting and custom metric dashboards.",
                        )
                    ],
                    citations={"enabled": True},
                ),
                TextBlockParam(
                    type="text",
                    text="What does Acme Dashboard do, and what plans is it available on?",
                ),
            ],
        ),
        MessageParam(
            role="assistant",
            content=[
                TextBlockParam(
                    type="text", text="Let me check the pricing information."
                ),
                ToolUseBlockParam(
                    type="tool_use",
                    id="toolu_01A09q90qw90lq917835lq9",
                    name="search_knowledge_base",
                    input={"query": "Acme Dashboard pricing plans"},
                ),
            ],
        ),
        MessageParam(
            role="user",
            content=[
                ToolResultBlockParam(
                    type="tool_result",
                    tool_use_id="toolu_01A09q90qw90lq917835lq9",
                    content=[
                        SearchResultBlockParam(
                            type="search_result",
                            source="https://docs.company.com/pricing",
                            title="Pricing Plans",
                            content=[
                                TextBlockParam(
                                    type="text",
                                    text="Acme Dashboard is available on the Starter plan at $10 per user per month and the Enterprise plan with custom pricing.",
                                )
                            ],
                            citations={"enabled": True},
                        )
                    ],
                )
            ],
        ),
    ],
)

print(response)

応答は両方のソースを引用します。事前取得した結果は search_result_index: 0、ツールが返した結果は search_result_index: 1 となり、会話内で search_result ブロックが出現する順序と一致します。

{
  "role": "assistant",
  "content": [
    {
      "type": "text",
      "text": "Here's what I found about Acme Dashboard:\n\n**What it does:** "
    },
    {
      "type": "text",
      "text": "Acme Dashboard is a monitoring tool for distributed systems. It supports real-time alerting and custom metric dashboards.",
      "citations": [
        {
          "type": "search_result_location",
          "cited_text": "Acme Dashboard is a monitoring tool for distributed systems. It supports real-time alerting and custom metric dashboards.",
          "source": "https://docs.company.com/overview",
          "title": "Product Overview",
          "search_result_index": 0,
          "start_block_index": 0,
          "end_block_index": 1
        }
      ]
    },
    {
      "type": "text",
      "text": "\n\n**Available plans:** "
    },
    {
      "type": "text",
      "text": "Acme Dashboard is available on the Starter plan at $10 per user per month and the Enterprise plan with custom pricing.",
      "citations": [
        {
          "type": "search_result_location",
          "cited_text": "Acme Dashboard is available on the Starter plan at $10 per user per month and the Enterprise plan with custom pricing.",
          "source": "https://docs.company.com/pricing",
          "title": "Pricing Plans",
          "search_result_index": 1,
          "start_block_index": 0,
          "end_block_index": 1
        }
      ]
    }
  ]
}

他のコンテンツタイプとの混在

ユーザーメッセージでは、search_result ブロックは他の任意のコンテンツブロックと並べて配置できます。方法2の例では検索結果と text の質問を組み合わせており、画像ブロックやドキュメントブロックも同じように加えることができます。

ツール結果はより厳格です。tool_result のcontent配列内のいずれかのブロックが search_result である場合、そのすべてのブロックが search_result でなければなりません。同じツール結果内で検索結果と他のブロックタイプを混在させると、バリデーションエラーが返されます。ツール由来の検索結果と一緒に補足テキストを返すには、いずれかの検索結果の content 配列内にテキストブロックとして含めてください。そうすれば、そのテキストも引用可能になります。

キャッシュ制御

検索結果ブロックに cache_control を追加すると、リクエスト間で再利用するためにキャッシュできます。同じブロック上で citations と並べて配置します。

{
  "type": "search_result",
  "source": "https://docs.company.com/guide",
  "title": "User Guide",
  "content": [{ "type": "text", "text": "..." }],
  "citations": { "enabled": true },
  "cache_control": { "type": "ephemeral" }
}

キャッシュ可能な最小長やその他の要件については、プロンプトキャッシングを参照してください。

引用の制御

デフォルトでは、検索結果の引用は無効になっています。citations 設定を明示的に指定することで引用を有効にできます。

{
  "type": "search_result",
  "source": "https://docs.company.com/guide",
  "title": "User Guide",
  "content": [{ "type": "text", "text": "Important documentation..." }],
  "citations": {
    "enabled": true // Enable citations for this result
  }
}

citations.enabledtrue に設定されている場合、Claudeは検索結果を参照するテキストブロックに引用参照を付加します。

ベストプラクティス

ツールベースの検索(方法1)の場合

  • 動的コンテンツ: リアルタイム検索や動的なRAGアプリケーションに使用します
  • エラー処理: 検索が失敗した場合は適切なメッセージを返します
  • 結果の制限: コンテキストのオーバーフローを避けるため、最も関連性の高い結果のみを返します

トップレベル検索(方法2)の場合

  • 事前取得コンテンツ: すでに検索結果がある場合に使用します
  • バッチ処理: 複数の検索結果を一度に処理するのに最適です
  • テスト: 既知のコンテンツで引用の動作をテストするのに最適です

一般的なベストプラクティス

  1. 結果を効果的に構造化する:

    • 明確で永続的なソースURLを使用する
    • 説明的なタイトルを提供する
    • 長いコンテンツを論理的なテキストブロックに分割し、Claudeにより細かい引用境界を与える
  2. 一貫性を維持する:

    • アプリケーション全体で一貫したソース形式を使用する
    • タイトルがコンテンツを正確に反映していることを確認する
    • フォーマットの一貫性を保つ
  3. エラーを適切に処理する: 検索が失敗したり何も返さなかったりした場合は、エラーを発生させる代わりに、結果を説明するプレーンテキストブロック(例:{"type": "text", "text": "No results found."})を返してください。Claudeは空の結果をユーザーに説明し、会話は継続します。

制限事項

  • 検索結果コンテンツブロックは、Claude API、Amazon Bedrock、Google Cloudで利用できます。
  • 検索結果内ではテキストコンテンツのみがサポートされています(画像やその他のメディアは不可)。
  • search_result ブロックはユーザーメッセージ内(ツール結果内を含む)にのみ配置できます。検索結果を含むアシスタントメッセージは拒否されます。
  • 同じリクエストでWeb検索ツールが有効になっている場合、すべての search_result ブロックで引用を有効にする必要があります。

次のステップ

ストリーミング応答で拒否の停止理由を検出して処理し、拒否されたリクエストをフォールバックモデルで再試行します。

Claudeの応答をソースドキュメントに基づかせます。引用は各主張を裏付ける正確な箇所を返すため、回答を検証し、ユーザーにソースを提示できます。

引用付きソース、オプションの動的フィルタリング、ドメイン制御により、Claudeに最新のWebコンテンツへのアクセスを提供します。

コンテンツブロックタイプを含む、Messages APIの完全なドキュメントを参照してください。

cache_control で検索結果をキャッシュし、繰り返しのリクエストにおけるコストとレイテンシを削減します。

Was this page helpful?