面向 Agent 的 CLI 接口规范
面向 Agent 的 CLI 接口规范
概述
面向 Agent 的 CLI 接口规范定义了为 AI Agent 设计和消费 CLI 工具的标准实践。与传统面向人类的 CLI 不同,Agent CLI 需要兼顾人类可读性和机器可解析性,并在有状态会话中保持一致性。
1. 为什么 CLI 是 Agent 接口的一等公民
LLM 的核心能力是生成和解析结构化文本,CLI 天然匹配这一能力:
| Agent 能力 | CLI 匹配 |
|---|---|
| 文本生成 | 命令字符串直接对应 |
| 链式推理 | 管道组合(`cmd1 |
| 结构化输出 | --json 提供机器解析 |
| 能力发现 | --help 提供自描述文档 |
| 错误处理 | 退出码 + stderr 结构化错误信息 |
2. 双模式交互设计
2.1 无状态子命令模式
适用于脚本、流水线和一次性操作:
cli-tool project new -o output.json --type writercli-tool --project output.json writer add-heading -t "Title"cli-tool --project output.json export render output.pdf -p pdf特征:
- 每次调用独立进程,无上下文保持
- 通过文件(JSON session)持久化状态
- 可组合性:每个命令的输出是下一个命令的输入
2.2 有状态 REPL 模式
适用于交互式 Agent 会话:
$ cli-tool╔══════════════════════════════╗║ cli-tool v1.0.0 ║╚══════════════════════════════╝
tool> project new --name MyProject✓ Created: MyProject
tool[MyProject]> add-heading -t "Chapter 1"✓ Added heading
tool[MyProject]*> save✓ Saved (modified)
tool[MyProject]> exit特征:
- 单进程,上下文在内存中保持
- 提示符反映当前状态(项目名、修改标记
*) - 自动保存:一次可变操作后自动持久化到 session 文件
2.3 默认行为
@click.group(invoke_without_command=True)@click.pass_contextdef cli(ctx): if ctx.invoked_subcommand is None: ctx.invoke(repl, project_path=None)无参数启动时进入 REPL,确保 Agent 和人类用户的直觉行为一致。
3. JSON 输出协议
3.1 --json Flag
每个命令必须支持 --json 标志:
# 人类可读$ cli-tool project info --project report.jsonName: Q1 ReportType: writerPages: 1Modified: yes
# Agent 消费$ cli-tool --json project info --project report.json{"name": "Q1 Report", "type": "writer", "pages": 1, "modified": true}3.2 JSON 输出规范
- 结构一致性:相同命令的 JSON 结构始终一致
- 类型正确性:布尔值用
true/false而非字符串 - 错误格式统一:
{"error": "message", "code": "ERROR_CODE"} - 路径绝对化:输出中的文件路径使用绝对路径
4. 帮助自发现
Agent 通过 --help 发现能力,因此帮助文档必须:
- 命令树完整:
--help显示所有子命令和选项 - 描述清晰:每个命令有一句话描述其功能和副作用
- 示例实用:帮助中可包含常见用法示例
- JSON 模式标注:标注哪些命令支持
--json
5. Auto-Save 与 --dry-run 模式
5.1 问题
Session-based CLI 在一次性子命令模式下,如果修改了内存中的 session 但未调用 save_session(),变更会静默丢失。
5.2 解决方案
def one_shot_mutation(session, args): session.apply_change(args) # Auto-save after mutation if not args.dry_run: session.save()规则:
- 一次性子命令执行可变操作后,自动保存
- 提供
--dry-run标志抑制保存,用于预览和测试 - REPL 模式下由用户显式控制保存时机
6. 统一 REPL Skin 概念
当系统包含多个 CLI 工具时,使用统一的 REPL Skin 确保一致的 UX:
- 品牌横幅:启动时显示工具名、版本、SKILL.md 路径
- 统一提示符:
tool[ProjectName]*>格式,*表示未保存 - 消息标准:
✓绿色成功、✗红色错误、⚠黄色警告、●蓝色信息 - 表格格式:统一的列对齐和标题样式
- 进度条:一致的进度指示
每个 CLI 工具拷贝(而非 import)共享的 skin 文件,确保独立安装的 CLI 不相互依赖。
7. 内省命令
Agent 在执行操作前需要理解当前状态:
| 命令 | 用途 |
|---|---|
info | 显示当前项目/会话的关键信息 |
list | 列出所有可用项(图层、轨道、页面等) |
status | 显示当前状态摘要 |
--json + 上述命令 | 机器可读的结构化状态 |
Agent-Cheap 设计:status --json 应返回紧凑摘要,让 Agent 无需读取大型文件即可理解状态。
8. 陷阱与对策
| 陷阱 | 对策 |
|---|---|
| 子命令修改后忘记保存 | Auto-save + --dry-run 模式 |
| Agent 无法解析人类格式的输出 | 每个命令支持 --json |
| Agent 不理解当前状态 | 提供 info/status/list 内省命令 |
| 多个 CLI 工具的 UX 不一致 | 统一 REPL Skin,每个工具拷贝 |
| REPL 启动不明显 | 无参数时默认进入 REPL(invoke_without_command) |
| 帮助文档对 Agent 不友好 | 命令描述简洁,标注副作用和前置条件 |
9. 设计取舍
拷贝 vs Import REPL Skin
选择:每个 CLI 拷贝 skin 文件而非 Python import。
原因:
- 每个 CLI 是独立的 pip 包,不应交叉依赖
- 拷贝允许各 CLI 在未来独立演进 skin
- 代价是更新 skin 需要重新发布所有 CLI
文件状态 vs 内存状态
选择:REPL 使用内存状态,子命令使用文件状态。
原因:
- REPL 是长进程,内存状态高效
- 子命令是短进程,文件状态保证进程间一致性
- 通过 session JSON 文件桥接两种模式