AI Agent 友好的 CLI,不只是加一个 --json
很多 CLI 对人很好用:有彩色表格、进度条、确认提示和详细说明。但同一套交互交给 AI Agent 后,常常变得脆弱。Agent 需要猜表格列、等待一个无法回答的确认框,或者把几千行日志塞进上下文,最后在一句 “Something went wrong” 面前失去恢复路径。
问题不在于 Agent 不会用终端,而在于这类 CLI 只设计了人机界面,没有设计稳定的机器契约。
一个 Agent 友好的 CLI,至少应该让调用方回答四个问题:我能做什么?执行前会改什么?执行后到底发生了什么?失败以后应该重试、修正输入,还是交给人?
终端输出和机器接口是两个产品面
--json 是起点,但不是终点。真正的目标是把 stdout 变成稳定接口,而不是把原来的表格临时包进 JSON。
机器输出需要稳定字段、明确类型和版本约束。列表命令还要支持字段选择、分页游标和数量上限,否则一次“查看事件”就可能吞掉整个上下文窗口。长任务则应返回任务 ID,让 Agent 查询状态,而不是持续输出无法定位的日志流。
人和 Agent 可以共享同一个命令入口,但不必共享同一种呈现:TTY 中保留适合阅读的表格;非 TTY 或显式指定机器模式时,返回结构化结果。这样既不牺牲人的体验,也不要求 Agent 解析视觉格式。
不要让控制流藏在交互提示里
传统 CLI 喜欢在危险操作前询问“是否继续”。这对坐在终端前的人有效,对无人值守的 Agent 却意味着流程永久阻塞。
更稳妥的做法,是把控制流变成显式参数和状态转换:
- 先读取当前状态;
- 生成结构化执行计划;
- 标出风险、影响范围和必要权限;
- 获得明确授权后执行;
- 返回结果与可查询的回执。
因此,dry-run 不应只打印一段“将要部署”的说明,而应返回资源、旧值、新值、风险等级和是否需要审批。高风险写入还应支持幂等键、计划哈希或确认令牌,避免 Agent 在超时后重复执行已经成功的操作。
{
"plan_id": "plan_42",
"changes": 3,
"risk": "high",
"approval_required": true,
"expires_at": "2026-07-17T10:30:00Z"
}这个结构的价值不在格式本身,而在于它把“准备做什么”和“已经做了什么”分开了。
错误信息应该驱动下一步动作
面向人的错误提示经常只需要让人看懂;面向 Agent 的错误还必须支持决策。
一个可操作的错误至少要包含:稳定错误码、失败阶段、相关输入、是否可重试、恢复建议和请求 ID。退出码也应区分输入或权限等永久失败,与超时、限流等瞬态失败。
{
"ok": false,
"error": {
"code": "permission_denied",
"retry": "never",
"hint": "Request the deploy role before retrying"
},
"meta": {
"request_id": "req_8f31",
"schema_version": "1"
}
}retry: never 能阻止 Agent 用相同身份盲目重试;request_id 则让人和后端日志讨论的是同一次操作。相比更长的自然语言,这些字段更能降低错误恢复成本。
可发现性决定 Agent 能否正确调用
Agent 经常从 --help 开始理解工具。帮助信息应该简洁、稳定,明确参数类型、必填项、枚举值和副作用。更进一步,可以提供机器可读的命令描述,让 Agent 不必从自然语言逆向推导 schema。
输入同样需要机器通道。扁平参数适合人手工调用;复杂对象则适合通过 JSON 或 stdin 传入,减少嵌套数据在字符串转义、数组拆分和类型转换中的损失。
不过,机器可调用不等于放松校验。Agent 输入应当像外部 API 请求一样被视为不可信:路径必须限定在允许目录内,命令参数不能直接拼接进 shell,权限范围应尽量小,敏感值不能出现在日志和错误回显中。
设计重点是闭环,而不是格式
Agent 友好最终不是一张参数清单,而是一条能闭环的协议:
发现能力 → 描述意图 → 预览影响 → 授权执行
→ 获取回执 → 验证状态 → 失败恢复如果只增加 JSON 输出,却没有 dry-run、幂等语义、状态查询和可操作错误,Agent 仍然只能“更方便地读到一个不可控结果”。反过来,一套结构化、可验证、可恢复的 CLI,可以同时服务脚本、CI、Agent 和人类操作者。
所以,判断 CLI 是否真正适合 Agent,不妨检查这些问题:
- 输出 schema 是否稳定并支持版本演进?
- 大结果能否裁剪、分页或异步查询?
- 写操作能否先预览,再以明确授权执行?
- 超时后能否查询状态,而不是直接重试?
- 错误能否告诉调用方下一步该做什么?
- 输入、权限和日志是否按不可信边界设计?
当这些问题都有明确答案,CLI 才不只是“能被 Agent 调用”,而是开始具备被 Agent 可靠编排的条件。
来源与说明
本文受 sorrycc 的文章《编写 AI Agent 友好的 CLI》启发。原文以八条规则、Bad/Good 对照和 Node.js 示例给出实践清单。本文未转载原文的完整示例与代码骨架,而是重新组织为机器契约、执行闭环和恢复语义三个层次,并补充了 schema 版本、幂等、异步回执与请求追踪等工程判断。具体实现请阅读原文。