AI Agent 开发 04|把工具写清楚,助手才有办法把事做完
同样是读取文件,一个工具只返回“失败”,另一个能说明文件不存在、请求路径是什么、是否可以换一个位置继续查,后面的执行会差很多。工具输出决定了模型接下来有多少依据。
原教程用 Mini Cursor 说明这件事。最小代码助手可以从列目录、读文件、写文件和运行命令开始。四种能力已经能组成“查看项目、修改代码、执行检查、根据结果继续修正”的过程。
知识库助手可以先缩小范围,只提供列资料目录和读取资料。等确实需要编辑文件,再加入写入能力。每增加一种工具,都应该知道它会改变什么。
工具说明要让模型能作选择
工具通常需要名称、描述、输入结构和执行函数。名称用于识别,描述帮助模型判断何时调用,输入结构说明参数,执行函数负责实际工作。
query 这个名字很难让人知道能查什么。lookup_order_delivery 加上“根据订单号查询物流状态”的描述,会清楚得多。如果它只接受订单号,也该直接写明,避免模型尝试传手机号。
参数说明同样应该具体。路径是相对哪个目录,编码是否限定为 UTF-8,结果会不会截断,都影响调用方式。工具说明接近一份短 API 文档,模糊处会直接成为运行时的问题。
参数正确以后,还要检查操作是否允许
输入 schema 可以验证 orderId 是非空字符串。程序仍要检查当前用户是否有权读取该订单。结构校验和业务权限分别处理,错误才容易说明。
文件工具也有类似问题。把 ./docs/ 加到用户传入路径前面,无法自动拦住 ../。应当解析目标路径,验证它确实位于允许目录;存在符号链接时,还要检查解析后的真实目标。
允许目录应来自服务端配置。让模型自行声明“本次允许访问整个磁盘”,没有增加可信依据。工具读取文件的进程也应拥有与任务相符的系统权限。
返回值需要帮助下一轮行动
可以给工具设计一个稳定的结果结构。下面是自定义示意,字段要根据业务调整。
{
"ok": false,
"code": "FILE_NOT_FOUND",
"retryable": false,
"message": "请求的开发指南不存在"
}retryable 表示原样重试有没有意义。路径错误时,助手可以回到目录工具找线索;权限不足时,继续换名字读取也不该成为默认做法。
运行命令时,成功结果也要保留必要的标准输出。启动日志里出现了端口,工具却只返回“执行成功”,模型就无法知道接下来该访问哪个地址。失败时则要带退出码和经过截断、脱敏的关键错误信息。
输出上限值得提前加。一次命令打印几万行日志,会挤占后面的上下文。工具可以返回摘要、日志定位和截断标记,让模型按需继续读取。
命令怎样执行,决定了很多边界
原教程中的命令工具用空格拆字符串来简化实现。遇到带空格的路径或引号参数,这种拆法会出错。
更稳妥的接口把可执行程序和参数数组分开。若任务只需要检查项目,还可以只接受已经定义好的检查名称,由程序映射到明确命令。这样不必把任意文本交给 shell 解释。
命令执行要设置超时,记录退出码,并保留取消能力。网络中断或子进程卡住时,调用次数再少也可能一直等下去。
开发服务器还要单独处理。测试命令通常会退出,服务进程则持续运行。如果工具等到进程结束才返回,Agent 就无法进入下一步。需要记录进程状态,检查启动是否成功,然后返回地址与进程标识。
写入成功必须有证据
异步写文件要等待完成后再返回。原教程的部分教学实现省略了等待,直接用于真实流程时,后一步可能读到旧内容,或者在写入失败以后仍宣称成功。
对关键修改,可以记录修改前的版本,完成后再读取目标或运行相关检查。验证方式应与用户目标对应。文件存在,只能证明有这个文件;内容和行为是否正确还要继续核对。
可以用一个受控练习结束这一篇。让助手读取一个现有文件,再让它请求不存在的路径、越界路径和超长日志。检查每次结果有没有清楚区分成功、拒绝和失败。四种基本工具的边界弄清以后,再接更丰富的服务会更踏实。
延伸阅读
本篇依据冴羽《AI Agent 开发实战》学习整理稿中的工具设计与 Mini Cursor 章节重写。原教程见 Mini Cursor 实现 和 Mastra 工具入门。