news 2026/9/14 7:50:12

Agent Skills 中 Read URL 工具的设计与实践:面向 LLM-as-Judge 研究链的结构化网页内容提取

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Agent Skills 中 Read URL 工具的设计与实践:面向 LLM-as-Judge 研究链的结构化网页内容提取

Agent Skills 中 Read URL 工具的设计与实践:面向 LLM-as-Judge 研究链的结构化网页内容提取

【免费下载链接】Agent-Skills-for-Context-EngineeringA comprehensive collection of Agent Skills for context engineering, multi-agent architectures, and production agent systems. Use when building, optimizing, or debugging agent systems that require effective context management.项目地址: https://gitcode.com/GitHub_Trending/ag/Agent-Skills-for-Context-Engineering

导读

readUrl是 llm-as-judge-skills 示例项目中 Research 工具族(webSearch、readUrl、extractClaims、verifyClaim、synthesize)的核心成员之一,负责把给定 URL 的网页内容提取为带来源元数据的结构化文本,供研究型 Agent 做深入阅读与后续的 claim 提取、交叉验证与综合归纳。本文以 tools/research/read-url.md 为骨架,结合仓库中 webSearch 工具规范、Research Agent 定义 以及 TypeScript 工具实现模式,完整讲解该工具的输入/输出 Schema、内容类型处理策略、错误码设计、实现注意事项,以及它在多 Agent 研究流水线中的实际调用位置。读完你可以直接照搬这套工具定义搭建自己的网页阅读工具,并将其接入 Agent 的检索—阅读—验证工作流。

一、工具定位:Research 工具链中承上启下的一环

在 llm-as-judge-skills 的 Research Agent 中,一个完整的研究任务被拆解为五步:webSearch(检索)→readUrl(精读)→extractClaims(抽取论断)→verifyClaim(交叉验证)→synthesize(综合成文)。readUrl恰好处于"检索命中"与"深入分析"的衔接点:

  • 上游webSearch返回带 snippet 的结果列表(标题、URL、摘要、域名、相关度分数),只解决"有哪些相关来源"的问题;
  • 下游extractClaims需要的是"干净可读的正文文本",而不是掺杂导航、广告、侧边栏的原始 HTML——这正是readUrl的输出职责。

工具的设计目的在 read-url.md 中被明确为:"Extract and parse content from a given URL. Returns structured text content with metadata about the source."(从给定 URL 提取并解析内容,返回带来源元数据的结构化文本)。其 description 字段还特别强调"Use after webSearch to get full content from relevant results"(在 webSearch 之后使用,以获取相关结果的完整内容),说明这两个工具是配套使用的。

二、Tool 定义:AI SDK + Zod 的声明式工具结构

readUrl采用 Vercel AI SDK 的tool()工厂函数配合 Zod 描述参数,完整定义如下(出自 read-url.md):

import { tool } from "ai"; import { z } from "zod"; export const readUrl = tool({ description: `Read and extract content from a URL. Returns the main text content, stripped of navigation and ads. Use after webSearch to get full content from relevant results.`, parameters: z.object({ url: z.string().url() .describe("The URL to read"), contentType: z.enum(["auto", "article", "documentation", "paper", "code"]).default("auto") .describe("Hint for content type to optimize extraction"), maxLength: z.number().min(1000).max(50000).default(10000) .describe("Maximum characters to return"), extractSections: z.boolean().default(true) .describe("Whether to identify and label sections"), includeMetadata: z.boolean().default(true) .describe("Include author, date, and other metadata") }), execute: async (input) => { return extractUrlContent(input); } });

这段定义透露出三层设计信息,与仓库的 工具设计模式 相互印证:

  1. description 是给模型看的"路由信号"tools/index.md指出工具的 description 要"清晰描述工具做什么"。readUrl 的 description 不仅说明功能,还写明了使用时机(webSearch 之后)和收益(去掉导航与广告),帮助模型在webSearchreadUrlverifyClaim等多个工具间做出正确选择。
  2. Zod 负责类型安全与默认值:所有可选参数都通过.default()提供默认值,模型不传参也能安全执行;z.string().url()在入口处就拦截非法 URL。这与仓库中src/tools/evaluation/direct-score.tsDirectScoreInputSchema定义输入、z.infer推导类型的做法完全一致。
  3. execute 只做一件事:把经过校验的输入转交给extractUrlContent内部实现。execute与"参数校验"、"提取逻辑"的职责分离,是 tools/index.md 中"Standard Tool Structure"推荐的写法。

三、输入参数详解(Input Schema)

read-url.md 给出的输入参数表如下,结合 Tool 定义可以补充取值约束与默认值:

字段类型必填说明约束 / 默认值
urlstring要读取的 URL必须通过z.string().url()校验,非法 URL 在进入 execute 前即被拒绝
contentTypeenum内容类型提示,用于优化提取策略auto(默认)/article/documentation/paper/code
maxLengthnumber返回的最大字符数默认10000,范围1000 ~ 50000z.number().min(1000).max(50000)强制约束)
extractSectionsboolean是否识别并标记章节默认true,输出中对应content.sections字段
includeMetadataboolean是否包含作者、日期等元数据默认true,输出中对应metadata字段

参数设计中值得注意的两个工程细节:

  • maxLength 的上下限:最小 1000、最大 50000 字符的约束既防止模型给出过小的截断值(导致正文不完整),也限制单次返回过大(避免撑爆上下文窗口)。这体现了"工具输出要服务于上下文工程"的思想——在 context-fundamentals 技能中,"有效管理上下文"是核心原则,控制读取长度正是其落地手段。
  • contentType 是"提示"而非"开关":它只是 hint(提示),用于让提取器选择更合适的解析策略,即便模型猜错类型,auto模式下的自动探测仍然兜底。

四、输出结构详解(Output Schema)

readUrl返回结构化结果,完整接口如下(出自 read-url.md):

interface ReadUrlResult { success: boolean; url: string; title: string; content: { full: string; sections?: { heading: string; level: number; // h1=1, h2=2, etc. content: string; }[]; }; metadata?: { author?: string; publishedDate?: string; lastModified?: string; description?: string; keywords?: string[]; source: string; }; stats: { totalCharacters: number; truncated: boolean; sectionsFound: number; }; error?: { code: string; message: string; }; }

这个输出结构是刻意面向"研究型 Agent"设计的,几个字段各有用途:

输出区块字段对下游研究流程的意义
顶层success/url/title快速判断读取成败、确认来源身份,便于引用溯源
content.full去除导航广告后的正文直接作为extractClaims的输入文本
content.sections带 heading 与 level 的章节数组支持按章节检索,Agent 可只针对命中章节做细读
metadataauthor / publishedDate / lastModified / description / keywords / source供研究综合(synthesis)阶段评估来源权威性与时效性
statstotalCharacters / truncated / sectionsFound暴露截断状态,防止 Agent 误把不完整内容当全文引用
errorcode / message机器可读的错误码,供上层做重试或降级决策

其中metadatastats与 Research Agent 的质量标准直接呼应:该 Agent 的指令要求"note the recency and authority of sources"(记录来源的时效性与权威性),publishedDatesource字段正是为此提供数据;而 research-synthesis-prompt.md 在综合阶段要求标注每条 finding 的来源、日期与类型,同样依赖这里的 metadata。

五、完整使用示例

官方使用示例如下(出自 read-url.md):

const content = await readUrl.execute({ url: "https://eugeneyan.com/writing/llm-evaluators/", contentType: "article", maxLength: 15000, extractSections: true, includeMetadata: true }); // Result: // { // success: true, // url: "https://eugeneyan.com/writing/llm-evaluators/", // title: "Evaluating the Effectiveness of LLM-Evaluators", // content: { // full: "LLM-evaluators, also known as LLM-as-a-Judge...", // sections: [ // { // heading: "Key considerations before adopting an LLM-evaluator", // level: 2, // content: "Before reviewing the literature..." // }, // ... // ] // }, // metadata: { // author: "Eugene Yan", // publishedDate: "2024-06-15", // source: "eugeneyan.com" // }, // stats: { // totalCharacters: 15000, // truncated: true, // sectionsFound: 8 // } // }

示例选用的 eugeneyan.com 这篇文章正是本示例项目 README 所依据的 LLM-Evaluators 研究来源,用它做演示既真实又贴合"研究素材阅读"的场景。注意示例中totalCharacters: 15000truncated: true:当maxLength设为 15000 而正文实际更长时,工具会截断并明确标记,下游 Agent 需要感知这一信号,避免把片段当全文。

在实际的 Agent 调用链中,这个工具通常不是被直接execute,而是由 Research Agent 通过tools注册表调用:

tools: { webSearch: researchTools.webSearch, readUrl: researchTools.readUrl, extractClaims: researchTools.extractClaims, verifyClaim: researchTools.verifyClaim, synthesize: researchTools.synthesize }

(见 research-agent.md)。模型会在webSearch拿到结果列表后,挑选高相关度 URL 调用readUrl获取全文,再交给extractClaims

六、Content Type Handling:五种内容类型的提取策略

针对不同网页形态,readUrl提供不同的提取优化策略(出自 read-url.md):

类型优化策略
article优先提取正文,跳过侧边栏(Prioritize main content, skip sidebars)
documentation保留代码块,维持文档结构(Preserve code blocks, keep structure)
paper抽取摘要、章节与参考文献(Extract abstract, sections, references)
code保留格式与语法高亮(Preserve formatting, syntax highlighting)
auto从内容中自动探测类型(Detect type from content)

这五种策略对应的核心诉求是**"按内容形态调整信息保真度"**:

  • 文章(article)场景下,导航、侧边栏、推荐位是噪声,应尽可能剥离;
  • 技术文档(documentation)场景下,代码块与层级结构是信息主体,必须原样保留——这与仓库 context-fundamentals 中"保留代码结构供模型理解"的原则一致;
  • 论文(paper)场景下,摘要、章节、参考文献是后续 claim 验证的重要锚点;
  • 代码(code)场景下,格式与高亮直接影响可读性。

模型只需提供 contentType hint,具体解析逻辑由实现方(示例中为extractUrlContent)分派。从仓库结构看,readUrl属于"工具规范文档(MD)+ 实际 TypeScript 实现"双轨模式:规范在 tools/research/read-url.md,而同类工具的落地方案可参考 src/tools/evaluation/direct-score.ts 中tool({...})+execute的写法。

七、错误处理:面向重试与降级的错误码设计

readUrl定义了六种机器可读错误码(出自 read-url.md):

const errorCodes = { "URL_NOT_FOUND": "Page does not exist (404)", "ACCESS_DENIED": "Page requires authentication (401/403)", "TIMEOUT": "Request timed out", "BLOCKED": "Access blocked by robots.txt or rate limit", "INVALID_CONTENT": "Content could not be parsed", "UNSUPPORTED_TYPE": "Content type not supported (e.g., binary)" };

这套错误码设计遵循 tools/index.md 中定义的ToolError模式:

interface ToolError { code: string; // Machine-readable error code message: string; // Human-readable message retryable: boolean; // Whether retry might help details?: object; // Additional context }

每种错误的"可重试性"不同,Agent 的应对策略也应不同:

错误码含义建议策略
URL_NOT_FOUND页面 404 不存在不重试,报告来源失效,改选其他候选 URL
ACCESS_DENIED需要认证(401/403)不重试,跳过该来源或换镜像/缓存版本
TIMEOUT请求超时可重试(配合退避),或换更短 maxLength 再试
BLOCKED被 robots.txt 或限流拦截不立即重试,放慢频率或更换 UA 后隔段时间再试
INVALID_CONTENT内容无法解析不重试,该来源 HTML 结构异常,换源
UNSUPPORTED_TYPE内容类型不支持(如二进制)不重试,改请求 PDF/文本版本接口

在 Research Agent 的质量标准里,"Never fabricate information or sources"(绝不编造信息或来源)与"clearly indicate when information is uncertain"(明确标示不确定信息)是硬性要求,而 readUrl 的error.code正是让 Agent 能够准确表达"这个来源读不到/读不全"的依据,避免把失败伪装成成功结果。

八、实现注意事项:做一名礼貌且可靠的网络读者

read-url.md 的 Implementation Notes 给出六条生产级实现规范,逐条解读如下:

  1. Respect robots.txt:读取并遵守目标站点的 robots.txt 指令。这既是法律与道德义务,也是避免被封禁的前提——与错误码BLOCKED直接相关。
  2. Rate Limiting:不要对同一域名发起高频请求("Don't hammer the same domain")。建议按域名维护请求队列与最小间隔,配合滑动窗口限流。
  3. User Agent:使用合适的 UA 字符串。清晰标识自己是"研究型 Agent 的抓取工具"并附带联系方式,比伪装浏览器更合规,也更不容易被 WAF 误伤。
  4. Timeouts:设置合理超时(10~30 秒)。超时过长会拖慢整个研究流水线,过短又容易误杀慢速站点,10~30s 是文档给出的经验区间,超时后返回TIMEOUT错误码。
  5. JavaScript Rendering:对 JS 重渲染的站点(如 SPA),纯 HTTP 抓取拿不到正文,需要评估使用 headless browser(如 Playwright/Puppeteer)渲染后再提取。代价是更高延迟与资源开销,建议仅在auto探测失败或显式标记时启用。
  6. Caching:对重复读取做内容缓存。研究流水线中同一 URL 可能被多次访问(如多轮验证),缓存正文与 metadata 能显著降低延迟与对源站的打扰,与webSearch工具的缓存建议保持一致(见 web-search.md 的 Implementation Notes 第 2 条)。

从仓库现状看,这六条是工具规范的约定层内容,具体落地取决于实际实现;当把readUrl接入生产环境时,建议同时为extractUrlContent补充日志与指标(单次提取耗时、截断比例、错误码分布),以便持续调优。

九、在流水线中与其他工具协同

readUrl的价值只有在完整研究流水线中才能最大化。以下是 Research Agent 文档中定义的五步工作流(research-agent.md):

readUrl服务于E(Deep Reading)环节,其前后衔接如下:

  • C → D(Initial Search → Source Selection)webSearch按 query 返回结果与relevanceScore,Agent 据此筛选要精读的 URL 清单;
  • E(Deep Reading):对每个入选 URL 调用readUrl,得到干净正文 + 章节 + metadata;
  • F(Claim Extraction):把content.fullsections交给extractClaims,抽取带置信度的论断;
  • G(Cross-Verification):论断与metadata.publishedDatesource一起参与verifyClaim的交叉验证,时效性与权威性成为置信度评估的输入;
  • H(Synthesis):最终由 research-synthesis-prompt.md 综合,其模板要求每条 finding 携带 source/date/type——恰好是readUrl输出的metadatastats所提供的字段。

也就是说,readUrl输出的结构化程度直接决定了整条流水线后续环节的质量:content.sections支撑章节级引用、metadata支撑来源评估、stats.truncated防止误引不完整内容、error.code支撑失败降级。这也是它在 tools/index.md 的 Research 工具类别中被列为webSearch之后首选工具的原因("Find information → webSearch, readUrl")。

十、结语:把 readUrl 的设计思想迁移到自己的 Agent 系统

回顾readUrl这个工具,其值得复用的设计要点可以总结为四条:

  1. 用 description 承载路由语义:一句话说清"做什么、什么时候用、带来什么好处",让模型在多工具场景下正确选择;
  2. 用 Zod 承载约束与默认值:非法输入在入口拦截,可选参数全部有安全默认值,maxLength的 min/max 限制从源头控制上下文占用;
  3. 用结构化输出承载下游需求:正文、章节、元数据、统计、错误码分而治之,每个下游环节(抽取、验证、综合)都能拿到恰好需要的字段;
  4. 用错误码承载失败语义:可重试与不可重试的错误清晰区分,让 Agent 能做重试、换源、降级等理性决策。

如果你正在构建自己的研究型 Agent(例如 LLM-as-a-Judge 评测前的资料收集阶段),可以直接照搬 read-url.md 的工具定义与错误码约定,配合 web-search.md 完成"检索—精读"闭环,再接入 research-synthesis-prompt.md 完成带引用的综合报告。更完整的工程落地方案(含真实 TypeScript 实现与测试)可继续查阅 src/tools/evaluation/direct-score.ts 与 tests 目录,作为扩展同族工具时的参照。

【免费下载链接】Agent-Skills-for-Context-EngineeringA comprehensive collection of Agent Skills for context engineering, multi-agent architectures, and production agent systems. Use when building, optimizing, or debugging agent systems that require effective context management.项目地址: https://gitcode.com/GitHub_Trending/ag/Agent-Skills-for-Context-Engineering

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/14 7:48:25

免费完整导出微信聊天记录到 Word 和 CSV

免费完整导出微信聊天记录到 Word 和 CSV 【免费下载链接】WeChatMsg 提取微信聊天记录,将其导出成HTML、Word、CSV文档永久保存,对聊天记录进行分析生成年度聊天报告 项目地址: https://gitcode.com/GitHub_Trending/we/WeChatMsg 换手机的前一天…

作者头像 李华
网站建设 2026/9/14 7:48:05

深度学习调参指南:Batch Size如何影响模型训练与泛化

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/14 7:47:57

公板接口选型与调试实战:USB/HDMI/网口/WiFi/CVBS全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华