12. Web工具族 - WebSearch与WebFetch
所属分组:工具系统
概述
Web 工具族是 Claude Code 中实现网络信息获取的核心工具集,包括 WebSearchTool 和 WebFetchTool。这两个工具分别负责网络搜索和网页内容抓取,为 Claude 提供实时的外部信息获取能力,弥补模型训练数据的时效性限制。
WebSearchTool 通过调用 Anthropic 的 Web Search API 执行实时搜索,支持查询过滤和结果汇总;WebFetchTool 则负责从指定 URL 抓取内容,并支持通过提示词对内容进行处理。本文将深入分析这两个工具的实现机制、权限控制、内容处理流程以及与模型的交互方式。
源码位置
- WebSearchTool 核心实现:tools/WebSearchTool/WebSearchTool.ts(file:///e:/2026plan/AI_Lab/claude-code-sourcemap-main/restored-src/src/tools/WebSearchTool/WebSearchTool.ts)
- WebSearchTool UI 组件:tools/WebSearchTool/UI.tsx(file:///e:/2026plan/AI_Lab/claude-code-sourcemap-main/restored-src/src/tools/WebSearchTool/UI.tsx)
- WebSearchTool 提示词:tools/WebSearchTool/prompt.ts(file:///e:/2026plan/AI_Lab/claude-code-sourcemap-main/restored-src/src/tools/WebSearchTool/prompt.ts)
- WebFetchTool 核心实现:tools/WebFetchTool/WebFetchTool.ts(file:///e:/2026plan/AI_Lab/claude-code-sourcemap-main/restored-src/src/tools/WebFetchTool/WebFetchTool.ts)
- WebFetchTool UI 组件:tools/WebFetchTool/UI.tsx(file:///e:/2026plan/AI_Lab/claude-code-sourcemap-main/restored-src/src/tools/WebFetchTool/UI.tsx)
- WebFetchTool 提示词:tools/WebFetchTool/prompt.ts(file:///e:/2026plan/AI_Lab/claude-code-sourcemap-main/restored-src/src/tools/WebFetchTool/prompt.ts)
- WebFetchTool 工具函数:tools/WebFetchTool/utils.ts(file:///e:/2026plan/AI_Lab/claude-code-sourcemap-main/restored-src/src/tools/WebFetchTool/utils.ts)
- WebFetchTool 预批准列表:tools/WebFetchTool/preapproved.ts(file:///e:/2026plan/AI_Lab/claude-code-sourcemap-main/restored-src/src/tools/WebFetchTool/preapproved.ts)
核心实现分析
WebSearchTool 实现机制
WebSearchTool 的核心实现位于 tools/WebSearchTool/WebSearchTool.ts,它通过调用 Anthropic 的 Web Search API 执行实时搜索:
ts
export const WebSearchTool = buildTool({
name: WEB_SEARCH_TOOL_NAME,
searchHint: 'search the web for current information',
maxResultSizeChars: 100_000,
shouldDefer: true,
async description(input) {
return `Claude wants to search the web for: ${input.query}`
},
// ... 其他配置
} satisfies ToolDef<InputSchema, Output, WebSearchProgress>)
输入输出 Schema
ts
const inputSchema = lazySchema(() =>
z.strictObject({
query: z.string().min(2).describe('The search query to use'),
allowed_domains: z
.array(z.string())
.optional()
.describe('Only include search results from these domains'),
blocked_domains: z
.array(z.string())
.optional()
.describe('Never include search results from these domains'),
}),
)
const outputSchema = lazySchema(() =>
z.object({
query: z.string().describe('The search query that was executed'),
results: z
.array(z.union([searchResultSchema(), z.string()]))
.describe('Search results and/or text commentary from the model'),
durationSeconds: z
.number()
.describe('Time taken to complete the search operation'),
}),
)
WebSearchTool 支持查询词、允许域名列表和阻止域名列表作为输入参数,输出包含查询结果和文本摘要的组合。
搜索执行流程
call 方法实现了完整的搜索执行流程:
- 构建工具 Schema:将用户输入转换为 Anthropic Web Search API 所需的格式
- 调用模型 :使用
queryModelWithStreaming发送搜索请求,支持流式响应 - 处理流式结果 :解析
server_tool_use和web_search_tool_result事件,提取搜索结果 - 生成输出:将搜索结果和模型摘要组合成最终输出
关键代码片段:
ts
const toolSchema = makeToolSchema(input)
const queryStream = queryModelWithStreaming({
messages: [userMessage],
systemPrompt: asSystemPrompt(['You are an assistant for performing a web search tool use']),
tools: [],
signal: context.abortController.signal,
options: {
model: useHaiku ? getSmallFastModel() : context.options.mainLoopModel,
extraToolSchemas: [toolSchema],
querySource: 'web_search_tool',
// ...
},
})
平台兼容性
WebSearchTool 根据不同的 API 提供商判断是否启用:
ts
isEnabled() {
const provider = getAPIProvider()
const model = getMainLoopModel()
if (provider === 'firstParty') {
return true
}
if (provider === 'vertex') {
const supportsWebSearch =
model.includes('claude-opus-4') ||
model.includes('claude-sonnet-4') ||
model.includes('claude-haiku-4')
return supportsWebSearch
}
if (provider === 'foundry') {
return true
}
return false
}
WebFetchTool 实现机制
WebFetchTool 负责从指定 URL 抓取内容,并支持通过提示词对内容进行处理:
ts
export const WebFetchTool = buildTool({
name: WEB_FETCH_TOOL_NAME,
searchHint: 'fetch and extract content from a URL',
maxResultSizeChars: 100_000,
shouldDefer: true,
// ... 其他配置
} satisfies ToolDef<InputSchema, Output>)
输入输出 Schema
ts
const inputSchema = lazySchema(() =>
z.strictObject({
url: z.string().url().describe('The URL to fetch content from'),
prompt: z.string().describe('The prompt to run on the fetched content'),
}),
)
const outputSchema = lazySchema(() =>
z.object({
bytes: z.number().describe('Size of the fetched content in bytes'),
code: z.number().describe('HTTP response code'),
codeText: z.string().describe('HTTP response code text'),
result: z.string().describe('Processed result from applying the prompt to the content'),
durationMs: z.number().describe('Time taken to fetch and process the content'),
url: z.string().describe('The URL that was fetched'),
}),
)
WebFetchTool 需要 URL 和提示词两个参数,输出包含抓取内容的处理结果。
权限控制机制
WebFetchTool 实现了多层次的权限控制:
- 预批准域名检查 :通过
isPreapprovedHost检查域名是否在预批准列表中 - 规则匹配 :根据
deny、ask、allow三种规则类型进行权限判断 - 动态授权建议:提供添加允许规则的建议,方便用户快速授权
关键代码片段:
ts
async checkPermissions(input, context): Promise<PermissionDecision> {
// 检查预批准列表
if (isPreapprovedHost(parsedUrl.hostname, parsedUrl.pathname)) {
return { behavior: 'allow', updatedInput: input, decisionReason: { type: 'other', reason: 'Preapproved host' } }
}
// 检查 deny 规则
const denyRule = getRuleByContentsForTool(permissionContext, WebFetchTool, 'deny').get(ruleContent)
if (denyRule) {
return { behavior: 'deny', message: `${WebFetchTool.name} denied access to ${ruleContent}.`, decisionReason: { type: 'rule', rule: denyRule } }
}
// 检查 ask 规则
const askRule = getRuleByContentsForTool(permissionContext, WebFetchTool, 'ask').get(ruleContent)
if (askRule) {
return { behavior: 'ask', suggestions: buildSuggestions(ruleContent) }
}
// 默认行为:询问用户
return { behavior: 'ask', suggestions: buildSuggestions(ruleContent) }
}
内容处理流程
call 方法实现了完整的内容抓取和处理流程:
- URL 获取 :调用
getURLMarkdownContent获取网页内容 - 重定向检测:检查是否存在跨域重定向,若有则提示用户重新调用
- 内容处理:根据内容类型和大小决定是否直接返回或通过模型处理
- 二进制内容处理:对于 PDF 等二进制内容,保存到本地并在结果中提示
关键代码片段:
ts
const response = await getURLMarkdownContent(url, abortController)
// 重定向检测
if ('type' in response && response.type === 'redirect') {
const message = `REDIRECT DETECTED: The URL redirects to a different host.
Original URL: ${response.originalUrl}
Redirect URL: ${response.redirectUrl}
...`
return { data: { bytes: Buffer.byteLength(message), code: response.statusCode, ... } }
}
// 内容处理
let result: string
if (isPreapproved && contentType.includes('text/markdown') && content.length < MAX_MARKDOWN_LENGTH) {
result = content
} else {
result = await applyPromptToMarkdown(prompt, content, abortController.signal, isNonInteractiveSession, isPreapproved)
}
结果渲染
两个工具都通过 mapToolResultToToolResultBlockParam 方法将结果转换为模型可理解的格式:
ts
// WebSearchTool
mapToolResultToToolResultBlockParam(output, toolUseID) {
const { query, results } = output
let formattedOutput = `Web search results for query: "${query}"\n\n`
// ... 处理结果
formattedOutput += '\nREMINDER: You MUST include the sources above in your response to the user using markdown hyperlinks.'
return { tool_use_id: toolUseID, type: 'tool_result', content: formattedOutput.trim() }
}
// WebFetchTool
mapToolResultToToolResultBlockParam({ result }, toolUseID) {
return { tool_use_id: toolUseID, type: 'tool_result', content: result }
}
关键设计要点
- 预批准机制:WebFetchTool 通过预批准域名列表实现安全的零授权访问,支持文档、博客等公共内容的快速获取
- 重定向防护:检测跨域重定向并阻止自动跟随,防止钓鱼攻击和权限绕过
- 流式搜索:WebSearchTool 支持流式搜索结果,实时显示搜索进度
- 平台适配:根据 API 提供商和模型类型动态决定是否启用搜索功能
- 内容处理策略:根据内容类型和大小采用不同的处理策略,平衡性能和质量
与其他模块的关系
- 工具系统:WebSearchTool 和 WebFetchTool 是工具系统的重要组成部分,与其他工具并列使用
- 权限系统:依赖权限系统进行域名级别的访问控制
- API 服务层 :WebSearchTool 依赖
services/api/claude.ts中的queryModelWithStreaming方法 - 配置系统:预批准域名列表通过配置系统管理
- UI 层 :通过各自的
UI.tsx组件提供工具使用和结果的终端渲染
小结
Web 工具族为 Claude Code 提供了实时网络信息获取能力,WebSearchTool 支持实时搜索和结果汇总,WebFetchTool 支持网页内容抓取和处理。两个工具都实现了完善的权限控制机制,通过预批准列表和规则匹配确保安全访问。其设计体现了安全性和可用性的平衡,为用户提供了灵活而安全的网络信息获取方式。