跳转到正文

Anthropic《Writing effective tools for agents》系统解读:非确定性契约与 PPT Master 的脚本接口

原文:Writing effective tools for agents — with agents
实践项目:PPT Master
前置阅读:《Building effective agents》 · 《Effective context engineering》 · 《Effective harnesses》

第一篇解读介绍了 ACI 的概念,但那只是原文的一个附录。这一篇是同一主题的完整展开。

原文开篇给出的定位很关键:

Tools are a new kind of software which reflects a contract between deterministic systems and non-deterministic agents.

确定性系统与非确定性 Agent 之间的契约。 传统 API 是两个确定性系统之间的契约——调用方知道自己要什么,按签名传参即可。而 Agent 会误解、会选错、会在错误的时机调用,工具设计必须为这些情况留出余地。


一、为什么不能直接包装 API

原文指出的核心约束是上下文:

LLM agents have limited "context" (that is, there are limits to how much information they can process at once).

由此得出第一条设计原则:不是每个 API 端点都该成为一个工具。

Implement a few thoughtful tools targeting specific high-impact workflows.

原文的例子非常具体:

Instead of implementing a list_users, list_events, and create_event tools, consider implementing a schedule_event tool which finds availability and schedules an event.

三个原子操作合并成一个面向工作流的工具。差别在于,前者要求 Agent 自己编排三次调用并处理中间结果,每一步都消耗上下文且可能出错;后者把编排逻辑放进了确定性代码。


二、评估驱动的开发流程

这是原文方法论的主干,也是最容易被跳过的部分。

构建评估任务

原文强调任务必须来自真实场景,并给出一个合格样例:

Schedule a meeting with Jane next week to discuss our latest Acme Corp project. Attach the notes from our last project planning meeting and reserve a conference room.

同时警告要避免:

Overly simplistic or superficial "sandbox" environments.

每个任务需要配套可验证的目标响应,可选地记录期望的工具调用序列。

收集多维指标

不只看准确率,还要看运行时间、工具调用次数、token 消耗、错误率。原文建议开启 interleaved thinking 以观察 Agent 的决策逻辑。

用 Agent 改进工具

这是文章标题里"with agents"的含义:

Claude is an expert at analyzing transcripts and refactoring lots of tools all at once.

把评估记录直接交给 Claude Code 分析,让它一次性重构大量工具。Anthropic 用这个流程改进了 Slack 和 Asana 的内部工具,准确率有明显提升。

顺序不能颠倒

先有评估任务,才知道工具在哪里失败;先有失败记录,Agent 才有东西可分析。没有评估的工具优化,是在猜测哪里需要改。


三、具体设计原则

命名空间

用前缀或后缀分组相关工具,如 asana_search / jira_search,或 asana_projects_search / asana_users_search。目的是帮助 Agent 在工具变多时仍能选对。

返回有意义的上下文

优先返回高信号信息,避免低层技术标识:

避免改用
uuidname
256px_image_urlimage_url
mime_typefile_type

原文还建议实现 response_format 参数,提供 DETAILEDCONCISE 两档。文中的 Slack 案例显示,concise 版本把响应从 206 token 减到 72 token,约为原来的三分之一。

Token 效率

实现分页、范围选择、过滤和截断,并设置合理默认值:

We restrict tool responses to 25,000 tokens by default.

截断时要给出清晰引导:

Encourage agents to pursue more token-efficient strategies, like making many small and targeted searches instead of a single, broad search.

错误响应

不要返回不透明的错误码或 traceback,而要提供 具体且可操作的改进建议

工具描述

原文认为这是投入产出比最高的优化:

Even small refinements to tool descriptions can yield dramatic improvements.

描述应当像向新员工介绍工具一样明确,参数命名不能有歧义(user_id 优于 user)。文中提到 Claude Sonnet 在 SWE-bench Verified 上达到 SOTA,正得益于对工具描述的精确修订,错误率因此大幅下降。

原文还给了一个有趣的失败案例:Claude 在使用 web search 工具时会不必要地给 query 参数追加"2025",最终通过改进工具描述解决——模型的怪异行为,往往是描述留下的歧义造成的。


从概念转入实践

PPT Master 由数十个顶层 Python 入口和更多内部模块构成 Agent 的工具面。脚本数量会随拆分方式变化,以下关注接口边界而不是把某个计数当作长期事实。


四、工具整合:source_to_md 的调度器设计

PPT Master 用五个主要后端家族处理更广的输入集合:PDF;DOCX/HTML/EPUB/IPYNB 及可经 Pandoc 处理的 DOC、ODT、RTF、LaTeX、RST、Org、Typst;XLSX/XLSM;PPTX/PPTM/PPSX/PPSM/POTX/POTM;以及 URL。统一调度器还识别 Markdown 与纯文本。五个后端家族的入口是:

text
scripts/source_to_md/
├── pdf_to_md.py
├── doc_to_md.py
├── excel_to_md.py
├── ppt_to_md.py
└── web_to_md.py

但暴露给 Agent 的主入口是一个统一调度器:

bash
python3 scripts/source_to_md.py <file-or-url-or-dir> [...]

这正是原文 schedule_event 例子的同构实现:Agent 不需要先判断文件类型再选择后端,只需交出路径。类型判断、后端路由、批量处理都在确定性代码里完成。

值得注意的是,底层后端仍然可以直接调用(文档里明确列出了直接调用方式)。这保留了在调度器判断失误时的逃生通道,同时不让常规路径承担选择成本。

同样的整合出现在 project_manager.py,它用子命令组织项目生命周期操作:

bash
python3 scripts/project_manager.py init <project_name> --format ppt169
python3 scripts/project_manager.py import-sources <project_path> <sources...>
python3 scripts/project_manager.py validate <project_path>

这是原文命名空间建议的另一种实现——不是给平铺的工具加前缀,而是用子命令建立层级。


五、错误响应:error_helper.py 的结构与暴露边界

原文要求错误信息提供"具体且可操作的改进建议"。PPT Master 有一个专门模块做这件事:

python
ERROR_SOLUTIONS = {
    'missing_svg_output': {
        'message': 'Missing svg_output directory',
        'solutions': [
            'Create the svg_output directory: mkdir svg_output',
            'Place generated SVG files in this directory',
            'Ensure SVG files follow naming convention: slide_XX_name.svg'
        ],
        'severity': 'error'
    },
    ...
}

每个错误声明三个字段:发生了什么可以怎么做(多条具体动作)、严重程度

对照原文的要求,这个 数据结构 是合格的:solutions 里给的是可直接执行的命令和可检验的条件,而不是"请检查配置"这类无信息量的提示。severity 字段也能表达"必须停下"与"可以继续"。

但不能把结构存在直接写成主 ACI 已经使用它。当前只有 validate_project_structure(..., verbose=True) 才会把 solutions 拼入输出,而 project_manager.py validate 的主入口没有启用这个参数。因此,error_helper.py 更准确的定位是 已有的辅助能力或遗留接口;主验证入口当前并未把这些可操作建议暴露给 Agent。


六、Token 效率:用调用方式代替参数

原文的方案是给工具加 response_format 参数。PPT Master 达成了同样的目标,但走的是另一条路——在文档里规定调用纪律

svg_quality_checker.py 的使用规则有两条:

场景规则理由
运行检查不得用 tail / head / grep 过滤输出"One run already reports all pages"——过滤会导致"发现一个、修一个、再跑一次"的往返循环,每轮都累积上下文
检查通过不要打开或 cat 完整 JSON成功时"use the exit status and terminal summary"就够了
检查失败且输出被截断只读该次运行写入报告中的相关 issue 数组避免整份报告进入上下文

这三条实际上实现了原文 DETAILED / CONCISE 的效果:失败时详细,成功时极简。

但实现方式有本质差异

原文把输出控制做进 工具参数,由工具自己保证;PPT Master 做进 文档纪律,依赖 Agent 遵守。

前者是机制,后者是约定。约定在 Agent 上下文被压缩、或规则文档没有被加载的路径上会失效。这一点留到第九节讨论。


七、超出原文的部分:prompt_audit.py

PPT Master 有一个原文没有对应物的工具——面向维护者的 prompt 预算审计:

bash
python3 skills/ppt-master/scripts/prompt_audit.py --json

它检查的内容包括:

检查项失败级别
语料总量与热点文件的 token 上限超预算报 error
声明的加载集(路由/阶段场景)预算超预算、文件未知、选择器漂移报 error
加载覆盖率语料文件不属于任何加载集且无豁免时报 error
注册表声明(版式、模式、样式、图表等)的 ID 与数量漂移报 error
Markdown 引用与声明的权威边断链或未引用报 error
跨文件精确/近似重复warning
Schema 多处定义warning

其中预算策略的设计尤其克制:

Budgets are stable, deliberately rounded limits rather than mirrors of the current token count. Once set, do not raise or lower a passing ceiling, including to restore headroom after prompt growth.

上限一旦设定就不许调整,除非真的溢出。 这防止了预算被逐步稀释——如果每次接近上限就调高,预算就失去了约束意义。

笔者观点

这个工具把"上下文预算"从一个抽象概念变成了审计命令可检的指标,而且检的是 静态语料——Skill 文档本身的体量。

它同时呼应了三篇文章:Agent Skills 的分层加载(加载集覆盖率检查确保每个文件都属于某条加载路径)、上下文工程的注意力预算(token 上限)、以及本文的工具设计(结构化 JSON 输出与稳定错误信封 AUDIT_SETUP_ERROR)。

原文讨论的是"给 Agent 用的工具",这是"给维护 Agent 的人用的工具"——但它守护的正是 Agent 的上下文健康。


八、工具描述的实际载体

原文强调工具描述是投入产出比最高的优化点。PPT Master 的工具描述不在函数 docstring 里,而在 scripts/docs/ 下的独立 Markdown:

文档行数覆盖
svg-pipeline.md826SVG 处理链路
confirm_ui.md599确认界面的完整协议
conversion.md592源材料转换
prompt_audit.md审计工具用法与清单维护规则

这个安排与第二篇解读讨论的"代码的两种角色"一致:Agent 读 scripts/docs/ 理解接口,执行 scripts/ 下的 Python,不需要把源码读进上下文。

从工具描述的角度看,这些文档承担的正是原文说的"像向新员工介绍工具一样"的职责——而且因为不受 docstring 长度限制,可以包含完整的失败处理和恢复路径。


九、对照原文校准三个工具设计判断

1. 不能复用 --format 表达输出详略

第六节指出,PPT Master 的 token 效率部分依靠文档纪律实现。原文的做法是把输出详略做进工具参数,但具体项目仍要先检查已有 CLI 语义。

svg_quality_checker.py--format 已用于声明期望画布格式,不能再赋予 concise|detailed 含义。更重要的是,检查器在失败时要求先审阅未过滤终端输出中的完整 issue 集、让 Agent 合并修复;只有终端被截断时才从同一次 JSON 报告定向读取相关字段,成功时则以退出状态和终端摘要收口。这是一项有意的往返成本设计,不应仅为形式上贴合原文而改写。

如果未来有实际证据表明失败输出经常造成上下文压力,可以新增名称不冲突的输出模式;在此之前,现行契约更准确的描述是“详细失败、简洁成功,并把完整 JSON 留在磁盘”。

2. 未设统一长度上限是一项取舍

原文给出的默认值是 25000 token。PPT Master 的检查器对多页 deck 的完整 JSON 报告没有声明长度上限——正常情况下由"成功时不读完整 JSON"的纪律规避;失败时先审阅终端完整问题集,只有终端输出被截断才读取落盘报告中的相关 issue 数组。

但直接截断也会破坏“单次检查返回完整失败集合、集中修复”的约束,并可能把后面的阻断问题藏掉。当前做法是在终端输出被截断时,从该次落盘报告中只读取相关 issue 数组。只有出现可复现的超大报告问题时,才适合补充按页或按 issue 类型查询的独立接口,而不是先删掉信息。

3. 展示样例不是现成的工具评估集

这是最需要先分清“展示结果”和“可重放输入”的一处。

原文的核心方法论是:构建真实任务评估集 → 运行并收集多维指标 → 把记录交给 Claude 分析并重构工具。

PPT Master 的当前目录清单包含 21 个展示项目,覆盖论文解读、品牌手册、城市更新、技术蓝图等多种题材,也保留了 Design Spec、SVG 和最终 PPTX 等输出。它们是 Generate 路线的结果样例,并不覆盖四条顶层路线;多数项目也没有标准化的 sources/ 输入目录,因此不能直接重放成端到端任务。

这些样例可以为未来的输出不变量和题材选择提供种子,但若要研究工具误用,仍需另行定义输入、路线、预期行为和评分规则。不能把“有展示结果”写成“已经有可复现的多路线评估素材”。


十、我的理解:工具设计是把不确定性挡在代码之外

核心观点

给 Agent 写工具的目标,不是让工具能力更强,而是 让 Agent 犯错更难

每一个需要 Agent 自己判断的环节,都是一个可能出错的点。工具整合消灭的是"选哪个后端"的判断,默认值消灭的是"传什么参数"的判断,可操作的错误信息消灭的是"失败后该做什么"的判断。

按这个标准回看 PPT Master 的三处设计:

  • source_to_md.py 调度器——消灭了类型判断;
  • error_helper.py 的 solutions 列表——具备减少失败后方向判断的结构,但当前主验证入口尚未暴露它;
  • project_manager.py 子命令——消灭了"该调哪个脚本"的判断。

第九节的三个判断说明,工具设计不能只按通用文章做表面对齐:参数名已有领域含义,完整失败集合承担修复语义,展示样例也缺少可重放输入。先验证真实失败,再改最小的拥有接口,才能避免为假设问题增加机制。

原文那句"even small refinements to tool descriptions can yield dramatic improvements"的另一面是:如果一件事可以由默认值决定,就不该写进描述让模型记住。


十一、下一步

Demystifying evals for AI agents— 本文第九节区分了展示样例与可复现任务;下一篇继续讨论什么证据才能支持工具或流程改动(系统解读)。


← 返回 Anthropic 学习地图