Claude Platform Docs
MessagesModel capabilities

Search results

Enable natural citations for RAG applications by providing search results with source attribution

Search result content blocks let Claude cite your own content the same way it cites web search results: each citation carries the source and title you provided. Use them in RAG (Retrieval-Augmented Generation) applications where Claude needs to attribute answers to your documents.

All active models support search results with citations, with the exception of Claude Haiku 3. No beta header is required: search results are part of the standard Messages API.

How it works

Search results can be provided in two ways:

  1. From tool calls: Your custom tools return search results, enabling dynamic RAG applications
  2. As top-level content: You provide search results directly in user messages for pre-fetched or cached content

In both cases, Claude cites the search results automatically when citations are enabled. No special prompting is needed: ask your question, and citations appear on the text blocks that draw on your content.

Search result schema

Search results use the following structure:

{
  "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
  }
}

Required fields

FieldTypeDescription
typestringMust be "search_result"
sourcestringThe source of the content. Any stable string works: a URL, or an internal identifier such as kb://article-1234
titlestringA descriptive title for the search result
contentarrayAn array of text blocks containing the actual content

Optional fields

FieldTypeDescription
citationsobjectCitation configuration with enabled Boolean field. Citations are disabled by default; every example on this page sets "enabled": true explicitly. All search results in a request must use the same setting (see Citation control)
cache_controlobjectCache control settings (for example, {"type": "ephemeral"})

Each item in the content array must be a text block with:

  • type: Must be "text"
  • text: The actual text content (non-empty string)

Search results hold text only. Images and other media are not supported inside the content array.

Method 1: Search results from tool calls

Returning search results from your custom tools enables dynamic RAG applications: tools fetch content at runtime, and Claude cites it in the response. The following example forces the tool call with tool_choice, so the retrieval step runs every time.

Example: Knowledge base tool

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

client = Anthropic()

# Define a knowledge base search tool
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"],
    },
}


# Function to handle the tool call
def search_knowledge_base(query):
    # Your search logic here
    # Returns search results in the correct format
    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},
        ),
    ]


# Build up the conversation in a list, starting with the user's question
messages = [
    MessageParam(role="user", content="How do I configure the timeout settings?")
]

# Create a message with the tool
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,
)

# When Claude calls the tool, provide the search results.
# The tool_use block is not always first: iterate to find it.
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"])

    # Append Claude's turn, then the tool result, to the running conversation
    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
                )
            ],
        )
    )

    # Send the tool result back
    final_response = client.messages.create(
        model="claude-opus-5",
        max_tokens=1024,
        messages=messages,
    )
    print(final_response)

Method 2: Search results as top-level content

You can also provide search results directly in user messages. This is useful for: