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
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.md | web-search 本地契约、server-side schema、流事件回收 |
| 08-web-fetch-tool.md | web-fetch 权限门、URL 校验、二次摘要 |
| 05-model-adapter-provider-and-auth.md | HSt / 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):
tools是空数组——web_search不是普通本地工具,而是通过extraToolSchemas注入的 server-side capability;- 专用 systemPrompt:"You are an assistant for performing a web search tool use",
querySource明确标记为web_search_tool; 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_update | Searching: <query> |
content_block_start+web_search_tool_result | 读取结果条数,发search_results_received | Found 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)的权限更像普通本地网络工具:
- 先查预批准 host/path 列表——如
docs.python.org、developer.mozilla.org、kubernetes.io整站预批准;github.com/anthropics、vercel.com/docs等则是 path 级白名单(注意github.com整站并不在预批准列表里); - 把 URL 归一化成
domain:<hostname>规则键; - 按
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-search | web-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.md | web-search 深挖:本地契约、调用链、流事件、版本漂移 |
| docs/docs/01-runtime/08-web-fetch-tool.md | web-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
相关推荐
内网横向移动与域渗透工具链全景解析:Learn-Web-Hacking 内网攻击工具指南
内网横向移动与域渗透工具链全景解析:Learn Web Hacking 内网攻击工具指南 内网横向移动是 Web 安全从"边界突破"走向"域内接管"的关键阶段。
网络安全应用安全渗透测试教程文档HitCC完全指南:Claude Code CLI v2.1.197完整逻辑逆向工程知识库,一文看懂AI Agent内部架构
HitCC完全指南:Claude Code CLI v2.1.197完整逻辑逆向工程知识库,一文看懂AI Agent内部架构 HitCC 是一套面向 Claud
微信支付Java SDK集成指南:3步跑通第一笔JSAPI支付
微信支付Java SDK集成指南:3步跑通第一笔JSAPI支付 在 Java 后端接入微信支付,最容易踩坑的不是调接口,而是签名、验签、证书更新、回调解密这些"
后端金融科技
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考