关于"zero data retention"(零数据保留),即 ZDR 如何适用于此功能,请参阅 API 与数据保留。
搜索结果内容块让 Claude 能够像引用网络搜索结果一样引用您自己的内容:每个引用都带有您提供的来源和标题。在 Claude 需要将答案归属到您的文档的 RAG("Retrieval-Augmented Generation",检索增强生成)应用中使用它们。
所有活跃模型都支持带引用的搜索结果,Claude Haiku 3 除外。无需 beta 标头:搜索结果是标准 Messages API 的一部分。
搜索结果可以通过两种方式提供:
在这两种情况下,当启用引用时,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
}
}| 字段 | 类型 | 描述 |
|---|---|---|
type | string | 必须为 "search_result" |
source | string | 内容的来源。任何稳定的字符串都可以:URL,或内部标识符,例如 kb://article-1234 |
title | string | 搜索结果的描述性标题 |
content | array | 包含实际内容的文本块数组 |
| 字段 | 类型 | 描述 |
|---|---|---|
citations | object | 带有 enabled 布尔字段的引用配置。引用默认禁用;本页面上的每个示例都显式设置了 "enabled": true。请求中的所有搜索结果必须使用相同的设置(请参阅引用控制) |
cache_control | object | 缓存控制设置(例如,{"type": "ephemeral"}) |
content 数组中的每个项目必须是具有以下内容的文本块:
type:必须为 "text"text:实际的文本内容(非空字符串)搜索结果仅包含文本。content 数组内不支持图像和其他媒体。
从您的自定义工具返回搜索结果可实现动态 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)您也可以在用户消息中直接提供搜索结果。这适用于:
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 在使用其中的信息时都会自动包含引用:
{
"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
}
]
}
]
}每个引用包括:
| 字段 | 类型 | 描述 |
|---|---|---|
type | string | 对于搜索结果引用,始终为 "search_result_location" |
source | string | 来自原始搜索结果的来源 |
title | string 或 null | 来自原始搜索结果的标题 |
cited_text | string | 被引用块的完整文本,拼接而成。等于 content[start_block_index:end_block_index] 的内容连接在一起。不计入 output tokens。 |
search_result_index | integer | 被引用的搜索结果在请求中所有 search_result 块中的从 0 开始的索引,按它们出现的顺序(跨所有消息和工具结果)。 |
start_block_index | integer | 搜索结果的 content 数组中第一个被引用块的从 0 开始的索引。 |
end_block_index | integer | 搜索结果的 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_index 和 end_block_index 标识引用涵盖了其中哪些块,而 cited_text 恰好包含这些块的文本。将内容拆分为更小、更聚焦的块可以为 Claude 提供更精细的引用边界;将内容合并为一个块意味着每个引用都会返回完整文本。这与 Citations 功能中自定义内容文档使用的模型相同。
您可以在同一对话中混合使用两种方法。Claude 会从任一来源引用,并且 search_result_index 按请求顺序计数所有 search_result 块,无论来源如何。
以下示例重放了一个完整的对话。第一条用户消息携带一个预先获取的搜索结果,助手轮次调用知识库工具,工具结果返回第二个搜索结果。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 内容数组中的任何块是 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.enabled 设置为 true 时,Claude 会将引用参考附加到使用该搜索结果的文本块上。
引用是全有或全无的:请求中的所有搜索结果必须全部启用引用,或全部禁用引用。混合使用不同引用设置的搜索结果会导致错误。
有效地组织结果:
保持一致性:
优雅地处理错误: 当搜索失败或没有返回任何内容时,返回一个描述结果的纯文本块(例如,{"type": "text", "text": "No results found."}),而不是抛出错误:Claude 会向用户解释空结果,对话继续进行。
search_result 块只能出现在用户消息中(包括工具结果内部)。包含搜索结果的助手消息会被拒绝。search_result 块都必须启用引用。在流式传输响应中检测和处理拒绝停止原因,并在备用模型上重试被拒绝的请求。
让 Claude 的响应基于您的源文档。引用会返回支持每个论断的确切段落,以便您验证答案并向用户展示来源。
让 Claude 访问当前的网络内容,并提供引用来源、可选的动态过滤和域名控制。
查看完整的 Messages API 文档,包括内容块类型。
使用 cache_control 缓存搜索结果,以降低重复请求的成本和延迟。
Was this page helpful?