ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Claude Code内置双网络工具全解析:web-search与web-fetch调用链(HitCC逆向分析)

Claude Code内置双网络工具全解析:web-search与web-fetch调用链(HitCC逆向分析)

【免费下载链接】HitCC

Complete reverse-engineering documentation of the full logic of Claude Code CLI Node.js version v2.1.197

项目地址:https://gitcode.com/gh_mirrors/hi/HitCC
点击查看免费下载

Claude Code 内置了两个网络工具——web-search(网页搜索)与web-fetch(网页抓取)。本文基于HitCC(Claude Code CLI v2.1.197 的完整逆向分析文档库)拆解这两个工具的完整调用链:web-search 如何"借道"消息 API 触发服务端搜索,web-fetch 如何完成本地抓取 + 小模型二次提炼,并对比两者在权限模型、缓存策略与结果整形上的本质差异。

🧭 先搞清楚:HitCC 是什么,证据在哪

HitCC 不是一个源码仓库,而是一份逆向工程知识库:它从 Claude Code CLI v2.1.197 的发行包中提取 JavaScript bundle,逐步还原运行时逻辑、模块边界与工具调用链,可作为学习分析与高相似度重写的参考。

逆向时定位的核心证据文件包括提取后的 bundle(cli.extracted.bundle.pretty.js)与claude/sdk-tools.d.ts,对应的分析文档集中在docs/docs/01-runtime/目录:

文档内容
07-web-search-tool.mdweb-search 本地契约、server-side schema、流事件回收
08-web-fetch-tool.mdweb-fetch 权限门、URL 校验、二次摘要
05-model-adapter-provider-and-auth.mdHSt / m1o / Hpc统一模型调用门面
06-stream-processing-and-remote-transport.md流事件处理与远端传输

💡 先记住一个最重要的结论:两个工具名字像兄弟,实现却是完全不同的两条路——web-search 是"服务端工具包装器",web-fetch 是"本地抓取 + 本地提炼"。

🔍 web-search 完整调用链:一次"借道"消息 API 的服务端搜索

它不是本地搜索引擎客户端

WebSearchTool不直接请求任何公开搜索接口。它的真实身份是:把query和域名过滤条件包装成web_searchserver-side tool schema,再通过统一消息 API 发给 Anthropic message API,由服务端完成搜索。

本地契约(输入 / 输出)可直接还原:

  • 输入:{ query, allowed_domains?, blocked_domains? };校验规则:query不能为空,allowed_domains与blocked_domains不能同时出现
  • 输出:{ query, results, durationSeconds },稳定对外暴露的字段只有title和url
  • 工具属性:只读(isReadOnly: true)、并发安全、maxResultSizeChars = 100000
  • 权限门:passthrough("WebSearchTool requires permission."),被当作"需要用户同意的服务端能力",而不是普通本地网络工具

从 WebSearchTool.call 到 POST /v1/messages 的完整链路

WebSearchTool.call(input, context) → 构造 user message:"Perform a web search for the query: <query>" → 构造 server-side tool schema: { type: "web_search_20250305", name: "web_search", max_uses: 8, ... } → HSt(...) 统一模型调用门面 → m1o(...) → Hpc(...) → Kur(clientFactory, requestFn, retryContext) → client.beta.messages.create(...) → POST /v1/messages?beta=true

这条链有三个值得注意的细节(详见 07-web-search-tool.md):

  1. tools是空数组——web_search不是普通本地工具,而是通过extraToolSchemas注入的 server-side capability;
  2. 专用 systemPrompt:"You are an assistant for performing a web search tool use",querySource明确标记为web_search_tool;
  3. toolChoice并非恒定强制——只有tengu_plum_vx3特性开关打开时才显式强制{ type: "tool", name: "web_search" },并联动关闭 thinking。

界面上的 "Searching..." 是谁算出来的?

答案是:客户端自己。WebSearchTool.call(...)边收流边维护进度,监听三类关键流事件:

流事件本地动作界面效果
content_block_start+server_tool_use记录tool_use_id—
content_block_delta+input_json_delta正则抽取 partial JSON 中的 query,变化时发query_updateSearching: <query>
content_block_start+web_search_tool_result读取结果条数,发search_results_receivedFound N results for "<query>"

收流结束后,整理器_l_(...)把所有 assistant 块拍平:遇到web_search_tool_result只保留每项的title和url。再回灌给模型继续推理时,结果会被降成纯文本tool_result——模板里还带一句 REMINDER:必须用 markdown 超链接引用上面的 sources。也就是说,"强制引用来源"不是系统层自动注入的,而是工具 transcript 文本模板里显式追加的。

🌐 web-fetch 完整调用链:URL 校验、域名预检与小模型二次提炼

权限门:预批准表 + domain preflight

与 web-search 的passthrough不同,WebFetch(用户可见名为Fetch)的权限更像普通本地网络工具:

  1. 先查预批准 host/path 列表——如docs.python.org、developer.mozilla.org、kubernetes.io整站预批准;github.com/anthropics、vercel.com/docs等则是 path 级白名单(注意github.com整站并不在预批准列表里);
  2. 把 URL 归一化成domain:<hostname>规则键;
  3. 按deny / ask / allow规则三态决策——直接允许、命中拒绝、或弹窗询问。

URL 校验、domain preflight 与抓取参数

WebFetch.call({ url, prompt }) → CY4(url) 校验:长度 ≤ 2000 · 不能带用户名/密码 · hostname 须像正常域名 → 命中 15 分钟本地缓存则直接返回 → http 自动升级 https → bY4(hostname) domain preflight: GET /api/web/domain_info?domain=<hostname> 返回三态:allowed / blocked / check_failed(失败即抛错,不盲抓) → do1(url) 本地 HTTP GET: maxRedirects: 0 · 上限 10 MiB · 超时 60s Accept: "text/markdown, text/html, */*" → turndown 将 HTML 转成 markdown → 写入本地缓存(TTL 15 分钟 · 总量上限 50 MiB)

几个容易忽略的边界(详见 08-web-fetch-tool.md):

  • 重定向只允许同协议、同端口,且 hostname 仅允许www.归一化;若跳到不同 host,不会自动跟随,而是返回特殊文本要求模型重新发起一次WebFetch;
  • domain preflight 有本地缓存(最多 128 条、TTL 5 分钟),企业 / 受管设置可通过skipWebFetchPreflight直接跳过;
  • 非文本 content-type 一律落地保存为二进制附件(text/*、JSON、XML、JS 等除外)。

二次摘要:trusted / untrusted 两档 prompt 模板

抓完后是否直接返回原文,取决于一个条件:

预批准 URL + 内容为text/markdown+ 长度 < 100000 字符 →直接返回原始 markdown,不再摘要;否则进入lo1(...)二次提炼。

lo1(...)会把页面内容截断到 10 万字符,用固定模板Web page content: --- <markdown> --- <user prompt>组装 prompt,再通过UZ(...)发起一次普通小模型调用(querySource: "web_fetch_apply"、tools: []、thinking 关闭)。

这里有个安全设计亮点:模板分两档——

  • trusted(预批准 URL):只要求基于内容给出简洁回答,可包含代码示例、文档摘录;
  • untrusted(非预批准 URL):额外追加本地安全约束——单次引用上限 125 字符、精确引用必须加引号、不评论自身合法性、不输出歌曲歌词。

最终WebFetchOutput为{ bytes, code, codeText, result, durationMs, url },但回灌 transcript 时只保留result字符串。

⚖️ web-search 与 web-fetch 的三条本质差异

维度web-searchweb-fetch
实现本质server-side tool 包装器(web_search经extraToolSchemas注入消息 API)本地工具:本地抓取 + 本地小模型提炼
进度反馈从server_tool_use / input_json_delta / web_search_tool_result流事件实时解析只有静态Fetching…
核心结果服务端 search hit(title / url)与 source link本地抓取内容经模型提炼后的文本
权限模型passthrough(需用户同意的服务端能力)domain:<host>规则 + deny/ask/allow 三态
transcript 回灌文本模板(含Links:列表 + 引用 REMINDER)仅result字符串

两者也有共同点:都归入usage.server_tool_use统一计数面(web_search_requests/web_fetch_requests),流式 UI 也都会把对应 result block 归到tool-input状态。

⚠️ 版本漂移:为什么运行时和文档里"存在两个版本"

逆向过程中发现一个有趣现象——bundle 里同时存在两代证据:

  • 运行时代码路径:web-search 实际构造的是web_search_20250305,本地也没有传user_location;web-fetch 则只有本地实现,找不到主动构造web_fetch_202xxxxschema 的包装器;
  • bundle 内嵌 SDK 文档:却出现了WebSearchTool20260209/web_search_20260209与WebFetchTool20260209/web_fetch_20260209,以及UserLocation等新字段。

这说明平台侧的 server-side 能力比当前 CLI 实际走的本地包装器"更新"。HitCC 对此的结论非常克制:不能据此反推当前用户态Fetch工具已等价于 server-sideweb_fetch。这类"证据边界判断"正是该知识库的价值所在。

📚 延伸阅读:HitCC 相关文档路径

文档说明
docs/docs/01-runtime/07-web-search-tool.mdweb-search 深挖:本地契约、调用链、流事件、版本漂移
docs/docs/01-runtime/08-web-fetch-tool.mdweb-fetch 深挖:权限门、preflight、二次摘要
docs/docs/01-runtime/05-model-adapter-provider-and-auth.md统一模型调用门面HSt / Hpc与 provider 鉴权
docs/docs/01-runtime/06-stream-processing-and-remote-transport.md流事件处理与远端传输
docs/docs/05-appendix/02-evidence-map.md统一术语与证据索引

想亲手验证分析对象,可以按以下方式获取被分析的发行包,再配合仓库 recovery_tools/ 下的 Python 脚本做初步解混淆:

npm pack @anthropic-ai/claude-code@2.1.197

【免费下载链接】HitCC

Complete reverse-engineering documentation of the full logic of Claude Code CLI Node.js version v2.1.197

项目地址:https://gitcode.com/gh_mirrors/hi/HitCC
点击查看免费下载

相关推荐

上一篇:DataHub 术语传播动作(Glossary Term Propagation Action)实战指南:配置、原理与源码级解析
下一篇:Calibre 繁简转换插件 TradSimpChinese 使用指南:繁转简、简转繁与日文竖排

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进