|
| 1 | +根据你分享的网页内容,这里为你整理并转换成排版清晰、结构分明的 **Markdown** 格式: |
| 2 | + |
| 3 | +--- |
| 4 | + |
| 5 | +# 编写高效的智能体工具——使用智能体本身 |
| 6 | + |
| 7 | +**发布日期**:2025年9月11日 |
| 8 | + |
| 9 | +*智能体的效率完全取决于我们赋予它们的工具。本文将分享如何编写高质量的工具与评估流程,以及如何通过使用 Claude 针对自身优化工具来提升整体性能。* |
| 10 | + |
| 11 | +[Model Context Protocol (MCP)](https://www.anthropic.com/engineering/writing-tools-for-agents) 可以为 LLM 智能体赋予成百上千种工具来解决现实世界的任务。但我们该如何让这些工具发挥最大效用? |
| 12 | + |
| 13 | +在本文中,我们将介绍我们在提升各种智能体 AI 系统性能方面最有效的技术。内容包括: |
| 14 | + |
| 15 | +* 构建和测试你的工具原型 |
| 16 | +* 利用智能体创建并运行全面的工具评估 |
| 17 | +* 与 Claude Code 等智能体协同,自动提升工具的性能 |
| 18 | + |
| 19 | +最后,我们将总结在探索过程中发现的**编写高质量工具的核心原则**: |
| 20 | + |
| 21 | +* 选择合适的工具进行开发(以及避开不适合的工具) |
| 22 | +* 通过命名空间(Namespacing)划分清晰的功能边界 |
| 23 | +* 从工具向智能体返回有价值的上下文 |
| 24 | +* 针对 Token 效率优化工具的响应内容 |
| 25 | +* 对工具的描述和规范进行提示词工程(Prompt Engineering) |
| 26 | + |
| 27 | +--- |
| 28 | + |
| 29 | +## 什么是工具? |
| 30 | + |
| 31 | +在计算机科学中,**确定性系统**(Deterministic systems)在给定相同输入时每次都会产生完全相同的输出。而**非确定性系统**(Non-deterministic systems)——比如智能体——即使在相同的初始条件下,也可能产生多样化的响应。 |
| 32 | + |
| 33 | +传统的软件开发是在确定性系统之间建立契约。例如,调用函数 `getWeather("NYC")` 每次都会以完全相同的方式获取纽约市的天气。 |
| 34 | + |
| 35 | +而**工具(Tools)**是一种新型软件,它反映了**确定性系统**与**非确定性智能体**之间的契约。当用户提问 *“我今天需要带伞吗?”* 时,智能体可能会调用天气工具,也可能根据通用知识回答,甚至可能先询问具体的地理位置。有时,智能体还可能会产生幻觉,或者无法正确理解如何使用某个工具。 |
| 36 | + |
| 37 | +因此,为智能体编写软件需要从根本上转变思维:我们不能再像为其他开发者或系统编写函数和 API 那样去编写工具和 MCP 服务器,而是必须**面向智能体进行设计**。 |
| 38 | + |
| 39 | +我们的目标是:通过利用工具追求多样化的成功策略,扩大智能体在解决广泛任务时的有效“表面积”。幸运的是,根据我们的经验,那些对智能体最“符合人体工程学”(Ergonomic)的工具,往往对人类来说也出奇地直观易懂。 |
| 40 | + |
| 41 | +--- |
| 42 | + |
| 43 | +## 如何编写工具 |
| 44 | + |
| 45 | +在本节中,我们将介绍如何与智能体协同来编写并改进工具。 |
| 46 | + |
| 47 | +### 1. 构建原型 |
| 48 | + |
| 49 | +在亲自动手之前,很难预料智能体觉得哪些工具好用、哪些不好用。你可以先快速搭建一个工具原型并在本地进行测试。 |
| 50 | + |
| 51 | +* **提供文档**:如果你使用 Claude Code 来编写工具,为 Claude 提供工具将依赖的软件库、API 或 SDK(包括 MCP SDK)的文档会很有帮助。 |
| 52 | +* **本地连接**:将你的工具封装在本地 MCP 服务器或桌面扩展(DXT)中。 |
| 53 | +* 连接到 **Claude Code**:运行 `claude mcp add <name> <command> [args...]` |
| 54 | +* 连接到 **Claude Desktop** 应用:导航至 `Settings > Developer` 或 `Settings > Extensions`。 |
| 55 | + |
| 56 | + |
| 57 | + |
| 58 | +### 2. 运行评估 |
| 59 | + |
| 60 | +你需要通过运行评估来系统地衡量 Claude 使用工具的效果。建议协同智能体来帮助分析结果并决定如何改进工具。 |
| 61 | + |
| 62 | +* **生成评估任务**:任务应源于现实世界的使用场景,并基于真实的数据源和业务服务(例如内部知识库和微服务),避免使用过于简单的“沙盒”环境。 |
| 63 | +> **优秀任务示例**: |
| 64 | +> * *“下周与 Jane 安排一个会议,讨论我们最新的 Acme Corp 项目。附上上一次项目规划会议的记录,并预订一间会议室。”* |
| 65 | +> * *“客户 ID 9182 报告说他们的一次购买被扣款了三次。查找所有相关日志,并确定是否有其他客户受到相同问题的影响。”* |
| 66 | +> |
| 67 | +> |
| 68 | +
|
| 69 | + |
| 70 | +> **较弱任务示例**: |
| 71 | +> * *“下周与 jane@acme.corp 安排一个会议。”* |
| 72 | +> * *“在支付日志中搜索 purchase_complete 且 customer_id=9182。”* |
| 73 | +> |
| 74 | +> |
| 75 | +
|
| 76 | + |
| 77 | +* **运行评估流程**:建议通过直接的 LLM API 调用来编程式地运行评估。使用简单的智能体循环(包装了交替执行的 LLM API 和工具调用的 `while` 循环)。在系统提示词中,**引导智能体在调用工具前先输出其推理和反馈内容**(思维链 CoT),这能显著提升大模型的实际表现。 |
| 78 | +* **分析结果**:观察智能体在何处卡壳或感到困惑。检查工具调用指标:大量冗余的工具调用可能意味着需要调整分页或 Token 限制参数;大量的参数错误报错则意味着工具描述需要更清晰。 |
| 79 | + |
| 80 | +### 3. 与智能体协同优化 |
| 81 | + |
| 82 | +你可以直接把评估智能体的运行日志复制到 Claude Code 中,让它帮你分析结果并重构工具。 |
| 83 | + |
| 84 | +在实际测试中,这种基于留出测试集(Held-out test sets)的自动化优化表现优异,其最终提取的性能提升甚至超越了研究员手动编写的“专家级”工具实现。 |
| 85 | + |
| 86 | +--- |
| 87 | + |
| 88 | +## 高效编写工具的指导原则 |
| 89 | + |
| 90 | +### 原则一:为智能体选择“对”的工具 |
| 91 | + |
| 92 | +工具并不是越多越好。一个常见的错误是直接把现有的软件功能或 API 接口原封不动地包装成工具,而不考虑其是否适合智能体。 |
| 93 | + |
| 94 | +* **避免高消耗的暴力搜索**:如果一个工具直接返回“所有联系人”,智能体就必须逐个 Token 地去阅读,这会极大地浪费其宝贵的上下文空间。 |
| 95 | +* **整合与提炼**:建立少数几个针对高影响工作流的精细工具。 |
| 96 | +* *改进前*:分别提供 `list_users`、`list_events` 和 `create_event`。 |
| 97 | +* *改进后*:合并为一个 `schedule_event` 工具,自动查找空闲时间并安排日程。 |
| 98 | +* *改进前*:提供 `read_logs`。 |
| 99 | +* *改进后*:提供 `search_logs`,仅返回相关的日志行及上下文。 |
| 100 | + |
| 101 | + |
| 102 | + |
| 103 | +### 原则二:为工具划分命名空间(Namespacing) |
| 104 | + |
| 105 | +当工具功能重叠或目的模糊时,智能体容易混淆。通过通用前缀对相关工具进行分组(例如:按服务划分 `asana_search`、`jira_search`;按资源划分 `asana_projects_search`、`asana_users_search`),可以帮助智能体在正确的时间选择正确的工具。 |
| 106 | + |
| 107 | +### 原则三:返回有意义的上下文 |
| 108 | + |
| 109 | +工具实现应优先返回高信号(高价值)的信息。 |
| 110 | + |
| 111 | +* **多用语义化语言,少用低级技术标识符**:相比于加密的 UUID、Mime 类型或复杂的图片 URL,诸如 `name`、`file_type` 这样人类可读的字段更有助于智能体的下一步决策。 |
| 112 | +* **控制返回格式**:如果智能体既需要自然语言输出,又需要技术 ID 来触发下游工具,可以在工具中暴露一个 `ResponseFormat` 枚举参数,让智能体自主控制返回“简要(CONCISE)”还是“详细(DETAILED)”的响应,从而节省多达 $\sim 1/3$ 的 Token。 |
| 113 | + |
| 114 | +```typescript |
| 115 | +enum ResponseFormat { |
| 116 | + DETAILED = "detailed", |
| 117 | + CONCISE = "concise" |
| 118 | +} |
| 119 | + |
| 120 | +``` |
| 121 | + |
| 122 | +### 原则四:优化 Token 效率 |
| 123 | + |
| 124 | +针对可能返回大量数据的工具,务必实现分页(Pagination)、范围选择、过滤或截断(Truncation)机制,并设置合理的默认参数。 |
| 125 | + |
| 126 | +* 在 Claude Code 中,默认将工具响应限制在 25,000 个 Token 以内。 |
| 127 | +* 当工具抛出错误(例如输入验证失败)时,应通过提示词工程让错误信息清晰地传达**具体的、可操作的改进建议**,而不是返回晦涩的错误代码或一整段堆栈轨迹(Tracebacks)。 |
| 128 | + |
| 129 | +### 原则五:对工具描述进行提示词工程 |
| 130 | + |
| 131 | +工具的描述和规范会被直接加载到智能体的上下文中。编写工具描述时,把它当成你在向团队里的新员工介绍这个工具: |
| 132 | + |
| 133 | +* **将隐式背景显性化**:明确说明特殊的查询格式、利基术语的定义以及底层资源之间的关系。 |
| 134 | +* **消除参数歧义**:使用严谨的数据模型,避免含糊的命名。例如,不要使用 `user` 作为参数名,而应使用 `user_id`。 |
| 135 | + |
| 136 | +精确的工具描述改进效果显著。在 Anthropic 对 `Claude Sonnet 3.5` 进行精细化工具描述调整后,其在 **SWE-bench Verified** 评估中取得了行业领先(State-of-the-art) incremental 的优异表现。 |
0 commit comments