跳转到内容

面向 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 无状态子命令模式

适用于脚本、流水线和一次性操作:

Terminal window
cli-tool project new -o output.json --type writer
cli-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_context
def cli(ctx):
if ctx.invoked_subcommand is None:
ctx.invoke(repl, project_path=None)

无参数启动时进入 REPL,确保 Agent 和人类用户的直觉行为一致。

3. JSON 输出协议

3.1 --json Flag

每个命令必须支持 --json 标志:

Terminal window
# 人类可读
$ cli-tool project info --project report.json
Name: Q1 Report
Type: writer
Pages: 1
Modified: 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 文件桥接两种模式