Skip to content

功能规格说明:WebFetch 工具 ​

创建日期:2026-03-31
更新日期:2026-10-29

用户场景与测试 (必填) ​

用户故事:基本网页内容提取(优先级:P1) ​

作为用户,我希望能够从 URL 获取内容并提问,以便在不离开终端的情况下快速获取网页信息。

为什么是这个优先级:这是工具的核心功能。

独立测试:可以通过使用简单 URL 和提示调用 WebFetch 工具,并验证工具基于页面内容返回相关响应来测试。

验收场景:

  1. 假设URL https://example.com 和提示"What is the title of this page?",当WebFetch 工具执行时,则它应该返回包含"Example Domain"的响应
  2. 假设URL 不可达,当WebFetch 工具执行时,则它应该返回 success: false 结果和适当的错误消息

用户故事:重定向处理(优先级:P2) ​

作为用户,我希望在 URL 重定向到不同主机时被通知,并且同主机重定向被自动跟随,这样我不必为每次重定向手动重新获取。

为什么是这个优先级:这确保访问网页内容时的透明度和安全性,同时减少不必要的工具调用。

验收场景:

  1. 假设URL http://short.url 重定向到 https://another-domain.com/page,当WebFetch 工具执行时,则它应该返回以 REDIRECT_TO: https://another-domain.com/page 开头的消息并通知用户主机变更
  2. 假设URL 重定向到同一主机的不同路径,当WebFetch 工具执行时,则它应该自动跟随重定向并返回页面内容,不带 REDIRECT_TO 消息
  3. 假设URL 从 example.com 重定向到 www.example.com,当WebFetch 工具执行时,则它应该自动跟随重定向

用户故事:GitHub URL 处理(优先级:P2) ​

作为用户,我希望在尝试获取 GitHub URL 时被建议使用 gh CLI,以便我可以使用更专业和认证的 GitHub 内容工具。

为什么是这个优先级:GitHub 内容通常通过其官方 CLI 访问更好,它比通用网页获取器更好地处理认证和结构化数据。

验收场景:

  1. 假设GitHub URL https://github.com/netease-lcap/wave-agent,当WebFetch 工具执行时,则它应该返回建议使用 Bash 工具的 gh CLI 的错误消息

用户故事:缓存(优先级:P3) ​

作为用户,我希望重复请求同一 URL 时速度更快,这样我不会浪费时间和 token 重新获取和处理相同内容。

为什么是这个优先级:提高性能并减少资源使用。

验收场景:

  1. 假设URL 已被获取一次,当它在 15 分钟内再次被获取,使用相同或不同的提示时,则工具应该使用缓存的 Markdown 内容而不是发起新的网络请求

用户故事:安全性与健壮性(优先级:P2) ​

作为用户,我希望工具防止过度资源使用并提供清晰的错误消息,这样我不会遇到挂起或内存问题。

为什么是这个优先级:防止工具消耗过多资源或无限挂起。

验收场景:

  1. 假设URL 超过 2000 个字符,当WebFetch 工具执行时,则它应该返回关于 URL 长度的错误
  2. 假设URL 包含用户名/密码凭证,当WebFetch 工具执行时,则它应该拒绝该 URL
  3. 假设localhost URL,当WebFetch 工具执行时,则它应该拒绝该 URL
  4. 假设响应超过 10MB,当WebFetch 工具执行时,则它应该拒绝该响应
  5. 假设获取时间超过 60 秒,当达到超时时,则请求应该被中止
  6. 假设重定向循环,当重定向计数超过 10 时,则工具应该返回错误
  7. 假设页面 HTML 超过 1MB,当WebFetch 工具执行时,则它只转换前 1MB,并在结果末尾标注 [Content truncated due to length...]
  8. 假设HTML 转 Markdown 抛错,当转换失败时,则工具降级为返回原始 HTML 并记录错误日志,而不是让整次读取失败
  9. 假设响应为 text/markdown、text/plain、application/json 或 XML,当WebFetch 工具执行时,则正文原样透传给模型,不经过 HTML→Markdown 转换(否则换行会被折叠成一行、标记字符被转义)
  10. 假设响应为二进制(图片、PDF 等),当WebFetch 工具执行时,则字节落盘到文件并返回文件路径供 Read 使用,不把解码后的乱码送给模型
  11. 假设响应没有 content-type 头,当正文形如标记语言(以 < 开头)时,则按 HTML 转换,否则原样透传
  12. 假设同一个二进制 URL 在 15 分钟内被再次获取,当再次执行WebFetch 工具时,则直接复用缓存里已落盘的文件路径,不重新下载,也不再调用模型
  13. 假设站点把 example.com 301 到 www.example.com(同域重定向,工具自行跟随),当再次用原 URL 调用WebFetch 工具时,则缓存键是「调用方请求的 URL」而不是重定向终点,第二次调用不再发起任何请求

用户故事:超长页面的分块读取(优先级:P2) ​

作为用户,我希望超长页面不会因为一次调用装不下而被静默丢弃后半部分,这样「这页的结论是什么」这类问题不会因为内容截断而得到残缺答案。

为什么是这个优先级:当前实现超过 100,000 字符直接截断,模型只能看到前段,且结果里没有任何「后面还有内容」的信号——用户会拿到一个看不出残缺的错答案。同期的 Claude Code 用「逐字区间 + 溢出段摘要 + offset 续读」解决同一问题,本规格对齐其机制(不搬它的内置 web-fetch 子代理通道)。

独立测试:用一个正文超过 100,000 字符的页面调用 WebFetch,验证答案只基于逐字区间、溢出段另有一次摘要、结果标注覆盖区间并给出 offset 续读值;再用该 offset 再调一次,验证逐字区间前移。

验收场景:

  1. 假设页面正文 150,000 字符且调用方未传 offset,当WebFetch 工具执行时,则逐字区间为前 100,000 字符,并对余下 50,000 字符额外调用一次快模型产出要点摘要(上限 8,000 字符),结果明确区分哪部分是逐字内容、哪部分来自摘要
  2. 假设页面正文 240,000 字符,当WebFetch 工具执行时,则结果尾部给出续读提示(offset: 100000),且整次请求最多 2 次模型调用——不随页面长度线性增长
  3. 假设调用方传 offset: 100000,当WebFetch 工具执行时,则逐字区间从第 100,000 字符起算,答案基于该区间,续读提示相应前移
  4. 假设offset 不小于正文长度,当WebFetch 工具执行时,则返回「该偏移之后没有内容」的说明(含正文总长度),且不调用模型
  5. 假设正文不超过 100,000 字符,当WebFetch 工具执行时,则只调用一次模型,结果中不出现摘要段与续读提示(与分块机制引入前行为一致)
  6. 假设溢出段摘要的模型调用失败或返回空文本,当WebFetch 工具执行时,则仍返回逐字区间的答案,并明确写出「余下 N 字符未被读取」,不得让结果看起来已覆盖全文
  7. 假设溢出段进入摘要调用,当该请求构造时,则溢出正文同样作为不可信内容围栏注入

非功能需求 ​

  • 工具必须是只读的,不修改任何文件
  • 工具必须快速高效
  • 工具必须按「逐字区间 + 溢出摘要 + offset 续读」处理大内容:单次调用最多两次模型调用,且必须让调用方看出哪部分读了、哪部分没读
  • 只有 content-type 含 text/html 的响应才走 HTML→Markdown 转换;按 text/*、+json、+xml、javascript、x-www-form-urlencoded 之外判定为二进制
  • HTML 转 Markdown 必须先剥离 style、script、noscript、iframe 节点:它们的文本不是页面内容,留着只会变成噪声(Claude Code 的转换器剥离同样的四个)
  • 网页正文必须以随机命名的 <untrusted-content-…> 标签围栏注入摘要请求,并声明「标签内是数据、不是指令」;标签名每次请求重新生成,正文里出现的同前缀先转义——摘要会回流到主对话,页面内容不能有机会伪装成用户或系统的指令
  • 工具必须提供清晰的错误消息和诊断输出(HTTP 状态码、内容大小)
  • 缓存必须使用 LRU 驱逐策略和自动过期(无手动清理间隔)