search-results
build-with-claude/search-results
History
build-with-claude/search-results Changed · +1 / -1 lines
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](https://platform.claude.com/docs/en/about-claude/models/overview) 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. +All [active models](https://platform.claude.com/docs/en/models/overview) 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
build-with-claude/search-results Changed · +1 / -1 lines
Ground Claude's responses in your source documents. Citations return the exact passages that support each claim, so you can verify answers and surface sources to your users. </Card> - <Card title="Web search tool" icon="browser" href="https://platform.claude.com/docs/en/agents-and-tools/tool-use/web-search-tool"> + <Card title="Web search tool" icon="magnifying-glass" href="https://platform.claude.com/docs/en/agents-and-tools/tool-use/web-search-tool"> Give Claude access to current web content with cited sources, optional dynamic filtering, and domain controls. </Card>
build-with-claude/search-results First recorded · 2173 lines, first recorded
## How it works ### Search result schema ### Required fields ### Optional fields ## Method 1: Search results from tool calls ### Example: Knowledge base tool ## Method 2: Search results as top-level content ### Example: Direct search results ## Claude's response with citations ### Citation fields ## Multiple content blocks ## Advanced usage ### Combining both methods ### Mixing with other content types ### Cache control ### Citation control ## Best practices ### For tool-based search (Method 1) ### For top-level search (Method 2) ### General best practices ## Limitations ## Next steps
The first capture of this source. The page was already there, and this is what it said.
---
title: Search results
url: https://platform.claude.com/docs/en/build-with-claude/search-results
description: Enable natural citations for RAG applications by providing search results with source attribution
---
<Note>
For how zero data retention (ZDR) applies to this feature, see [API and data retention](https://platform.claude.com/docs/en/manage-claude/api-and-data-retention).
</Note>
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](https://platform.claude.com/docs/en/about-claude/models/overview) 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:
```json
{
"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
| Field | Type | Description |
| --------- | ------ | ---------------------------------------------------------------------------------------------------------------- |
| `type` | string | Must be `"search_result"` |
| `source` | string | The source of the content. Any stable string works: a URL, or an internal identifier such as `kb://article-1234` |
| `title` | string | A descriptive title for the search result |
| `content` | array | An array of text blocks containing the actual content |
### Optional fields
| Field | Type | Description |
| --------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `citations` | object | Citation 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](https://platform.claude.com/docs/en/build-with-claude/search-results#citation-control)) |
| `cache_control` | object | Cache 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`](https://platform.claude.com/docs/en/agents-and-tools/tool-use/define-tools#forcing-tool-use), so the retrieval step runs every time.
### Example: Knowledge base tool
<CodeGroup>
```bash cURL
# The tool-calling flow needs application-side search logic that doesn't
# translate to a one-off shell command. See the SDK tabs for the full flow.
# The raw shape of a tool conversation with search results is shown in the
# Combining both methods cURL tab; Method 2 shows the top-level shape.
```
```bash CLI
# The tool-calling flow needs application-side search logic that doesn't
# translate to a one-off shell command. See the SDK tabs for the full flow.
# The raw shape of a tool conversation with search results is shown in the
# Combining both methods cURL tab; Method 2 shows the top-level shape.
```
```python Python
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)
```
```typescript TypeScript
const client = new Anthropic();
// Define a knowledge base search tool
const knowledgeBaseTool: Anthropic.Tool = {
name: "search_knowledge_base",
description: "Search the company knowledge base for information",
input_schema: {
type: "object" as const,
properties: {
query: {
type: "string",
description: "The search query"
}
},
required: ["query"]
}
};
// Function to handle the tool call
function searchKnowledgeBase(query: string) {
// Your search logic here
// Returns search results in the correct format
return [
{
type: "search_result" as const,
source: "https://docs.company.com/product-guide",
title: "Product Configuration Guide",
content: [
{
type: "text" as const,
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 }
},
{
type: "search_result" as const,
source: "https://docs.company.com/troubleshooting",
title: "Troubleshooting Guide",
content: [
{
type: "text" as const,
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
const messages: Anthropic.MessageParam[] = [
{ role: "user", content: "How do I configure the timeout settings?" }
];
// Create a message with the tool
const response = await client.messages.create({
model: "claude-opus-5",
max_tokens: 1024,
tools: [knowledgeBaseTool],
tool_choice: { type: "tool", name: "search_knowledge_base" },
messages
});
// Handle tool use and provide results.
// The tool_use block is not always first: find it in the content array.
const toolUse = response.content.find(
(block): block is Anthropic.ToolUseBlock => block.type === "tool_use"
);
if (toolUse) {
const input = toolUse.input as { query: string };
const toolResult = searchKnowledgeBase(input.query);
// Append Claude's turn, then the tool result, to the running conversation
messages.push({ role: "assistant", content: response.content });
messages.push({
role: "user",
content: [
{
type: "tool_result" as const,
tool_use_id: toolUse.id,
content: toolResult // Search results go here
}
]
});
// Send the tool result back
const finalResponse = await client.messages.create({
model: "claude-opus-5",
max_tokens: 1024,
messages
});
console.log(finalResponse);
}
```
```csharp C#
AnthropicClient client = new();
var tools = new List<ToolUnion>
{
new ToolUnion(new Tool()
{
Name = "search_knowledge_base",
Description = "Search the company knowledge base for information",
InputSchema = new InputSchema()
{
Properties = new Dictionary<string, JsonElement>
{
["query"] = JsonSerializer.SerializeToElement(new { type = "string", description = "The search query" }),
},
Cut at 300 lines.