面向AI代理的命令行工具设计指南 是做什么的?
代理伸手拿命令,而不是拿手册。仅存在于文档中的规则,只有代理碰巧读到才会遵守。这些规则背后的数据见 references/evidence.md。
规则: 工具的每一条规则都由工具本身在适用的时刻陈述。工具打印的内容、拒绝的内容以及使其变得容易的内容,就是手册本身。
代理如何使用工具
- 伸手先拿命令;只有在不确定时才打开手册,而且经常是自信但错误。
- 阅读是为了确认已经制定的计划:它寻找的是语法,而不是规则。
- 在每次会话之间忘记一切,每次重新学习工具。
- 同时发送多个调用。
- 为工具打印的每一个字符,在后续每次请求中再次付费。
- 无法廉价等待:它轮询或睡眠,而每次轮询都是一次付费请求。
- 更可靠地执行眼前看到的答案,而不是之前看到的文档。
方法
共12项检查,每项附带验证方法。tool 是一个虚构命令。
- 在使用点教学。 命令的答案说明刚刚走的路线的代价,并指出更好的路线。
验证:每个存在已知错误用法的动词都应在自己的输出中说明。$ tool machine new created m-41 (stops by itself in 60 min) note: work started by hand in this machine keeps no run record. for a job you need to follow: tool job start --from <dir> -- <cmd> - 拒绝即教导。 说明拒绝了什么、为什么,以及带上调用者自身参数的确切下一条命令。在一次回答中给出所有问题。绝不在没有文字信息的情况下以非零退出。用法错误只打印那一个子命令的正确形式。
验证:禁止无消息的退出路径;每次拒绝都附带tool: refused: `job wait j-7` would hold this turn for up to 40 min. next: tool job show j-7 (how it stands now) tool job start … --notify (be told when it ends)next:。 - 将手册内置于工具。
tool rules打印完整的操作规则,以版本代码结尾。代理手动驱动的动词拒绝一个尚未设置当前代码(TOOL_RULES=<code>)的非交互式调用者,仅一行。作为机器接口的动词保持开放。规则变更时代码随之改变。 验证:一个全新的代理,仅给定命令名称,在其第一次创建、更改或删除某些内容的调用之前,规则就已存在于其上下文中。 - 让正确的路径成为更简单的路径。 在写“优先选择X”之前,先让X完成整个工作:接受代理真正拥有的输入,立即返回,保留记录。代理会绕过那些阻塞、丢弃历史或无法接受其输入的推荐命令。陈述后果,而非偏好:“Y不保留记录”有效,“优先选择X”无效。 验证:对于文档中的每一个“优先选择”,指出被避免的路径提供了哪些优选路径缺少的东西,并弥补这一差距。
- 一条命令回答“我现在哪里,为什么”。
tool status,几行内容:我的资源是什么,什么在运行,上一条操作如何结束以及为什么,接下来做什么。代理直接读取工具的存储或日志意味着状态缺少了某个事实。 验证:统计真实转录中的此类读取次数;最常见的三个问题应纳入状态。 - 长时间工作:启动、返回、告知。 超过大约一分钟:
start立即返回一个句柄;show <handle>提供时间线、退出代码和最后几行,即使工作进程已消失或调用者已死亡;结果以结果和原因的形式传递给调用者。消息只有携带代理现在可以采取行动的新信息时才合格:没有周期性的“继续加油”。 验证:默认情况下没有阻塞超过60秒的操作;每个作业都有记录和包含结果、原因及下一步操作的通知。 - 少打印。 默认输出适合一个屏幕:大约40行或2000个字符。更多内容输出到文件,文件路径会打印,或使用
--full标志。无横幅,无进度动画;会话内设置一次即生效。被截断的输出会说明并指出其余内容在哪。 验证:测量真实一周内每个命令返回的字符数,并为最大的三个总和分配预算。 - 两位读者:一个人和一个程序。 终端上的文本。使用管道,或使用
--json:仅输出JSON行,字段名稳定,最后有一个摘要。退出代码指示结果:0表示完成,分别为拒绝、错误用法、超时、从未运行提供不同的代码。诊断信息输出到标准错误。 验证:tool <verb> | cat可解析;--help列出所有退出代码。 - 重复安全,即时安全。 运行两次命令不会执行两次操作,或者说操作已经完成。同一代理同时发出的两个调用不会丢失彼此的写入:锁定,或者用文字拒绝第二个。破坏性动词需要明确的标志并提供
--dry-run。 验证:测试所有写入动词同时运行两次。 - 设定边界并留下记录。 默认时间限制;工具创建的内容会自动过期;
list显示残留项;cleanup删除此调用者创建的内容;一件事情的成本由一条命令体现。每个操作都记录下是谁、什么时间以及工具的构建版本;tool version进行标识。 验证:中途杀死调用者;无内容无限运行,记录会说明发生了什么。 - 一件事情一个名称。 命令、输出、错误和文档中相同的名词;每个动作在不同名词间使用同一个动词。未知标志和多余参数被拒绝,从不忽略。 验证:列出工具打印的所有名词;每个概念精确对应一个名词。
- 秘密不出。 绝不在命令行上,绝不被回显,绝不在记录中:从文件、标准输入或环境变量读取,在输出中遮蔽。
编写工具手册
手册负责解释;工具负责执行。没有约束性的东西单独存在于手册中。
- 描述: 工具做什么以及何时加载,使用任务会用到的语言,指明动词。
- 顺序: 首先列出约束性规则,每条附带后果;然后是一个目标和命令的简短表格;接着是失败情况及应对措施。
- 大小: 最多150行,每行不超过100个字符。代理打印长行被截断的文件时会丢失每个宽表格行的末尾。
- 表格: 表格单元格内不放置约束性内容。
在全新代理上验证
一个之前从未见过该工具或其手册的新会话,给定一个真实的任务和命令名称:
- 记录每次调用、其输出及其退出代码。
- 统计:帮助查询次数、失败调用次数、失败调用的重复次数、轮询次数、直接读取存储或日志的次数、返回的字符数。
- 任何大于零的次数都是工具的缺陷,而非代理的缺陷。修复消息或路径,然后在另一个新会话中再次运行。
- 在加载手册的情况下再运行一次:情况不得变得更糟,手册不得与工具矛盾。
当全新代理完成任务且没有进行帮助查询、没有需要猜测解决的失败调用、没有轮询、没有直接读取存储时,即为成功。
失败模式
仅手册规则(工具从未陈述) · 静默失败(非零退出,无文字) · 有原因无下一步(有原因但无命令) · 全部帮助输出 · 推荐但更差(推荐的路径缺乏另一路径的优点) · 状态缺口(代理读取存储) · 阻塞(命令占用回合) · 唠叨(没有新信息的周期性消息) · 去查看通知(只说发生了某事,不说是什么) · 文本墙 · 静默截断 · 写入丢失(两个同时调用,一个结果) · 两个名称 · 残留物(没有内容过期)。