SIGNAL / designing-cli-tools-for-ai-agents
如何为 AI Agent 设计 CLI 工具
传统 CLI 假设使用者是终端前的人类,当调用者变成 AI Agent 时这些隐式契约全部失效。本文定义一套面向 Agent 的 CLI 设计规范——非交互优先、渐进发现、结构化输出、可操作错误、幂等与安全预演,并附可直接嵌入 Agent 系统的 RFC 2119 风格规范文档。
如何为 AI Agent 设计 CLI 工具
背景
传统 CLI 假设使用者是坐在终端前的人类——能按方向键、能读懂模糊提示、能从上下文推断下一步。但当 CLI 的调用者变成 AI Agent 时,这些隐式假设全部失效。Agent 不能处理交互式 prompt,不能从模糊错误中恢复,不能猜测未文档化的行为。
CLI 设计规范在当前节点的紧迫性由三个趋势驱动:
- Agent 调用取代人类调用成为主流场景 —— Claude Code、Codex CLI、Cursor 等 Agent 已常态化通过 CLI 与工具交互,CLI 不再是人类专属界面
- Skill/Plugin 生态爆发 —— Skill 本质上就是「CLI 工具 + Agent 使用说明」,CLI 质量直接决定 Agent 的能力天花板
- 传统 CLI 的隐式契约全面失效 —— TTY 检测、交互式 prompt、模糊错误信息在 Agent 语境下都是致命缺陷,必须显式化
从架构上看,CLI 工具是 Agent 的行动接口(Action Interface)。模型不直接执行工具,而是通过编排层(orchestration layer)发起调用请求。编排层负责:
- 参数验证:检查 flag 是否合法
- 权限门控:验证 Agent 是否有权执行该操作
- 执行与捕获:运行命令,捕获 stdout/stderr 和退出码
- 结果反馈:将结构化输出返回给模型用于下一步推理
一个设计良好的 CLI 让编排层的工作变得简单——输入通过 flag 传入,输出通过 JSON 返回,错误通过退出码和 stderr 报告。编排层不需要解析人类文本、处理交互式 prompt 或猜测命令是否成功。
┌─────────────┐ structured call ┌──────────────┐
│ LLM Model │ ──────────────────────── │ Orchestrator │
│ (决策层) │ ◄── structured result ── │ (编排层) │
└─────────────┘ └──────┬───────┘
│
flags + stdin │ stdout + stderr + exit code
│
┌──────▼───────┐
│ CLI Tool │
│ (执行层) │
└──────────────┘
设计原则
输入
1. 非交互优先
规则:所有必要输入必须能通过 flag、环境变量或 stdin 传入。交互式流程只作为人类 fallback。
Agent 无法处理运行中途弹出的交互式选择。如果命令执行到一半要求用户按方向键选择环境,Agent 会直接卡死。
# 反模式:阻塞 Agent
$ mycli deploy
? Which environment? (use arrow keys)
# 正确:所有输入通过 flag 传入
$ mycli deploy --env staging --tag v1.2.3
设计要点:
- 支持
--stdin从管道读取复杂输入(如 JSON 配置) - 检测
CI=true或NO_TTY环境变量时自动禁用交互 - 当 flag 缺失且非 TTY 环境时,CLI 应报错退出而非进入交互模式
2. 渐进发现
规则:不要一次性倾倒全部文档。让 Agent 按需逐层探索命令能力。
Agent 的上下文窗口有限。如果顶层 --help 输出 200 行文档,大部分内容会被浪费。正确的做法是分层暴露:
# 第一层:顶层命令列出子命令
$ mycli --help
Commands:
deploy Deploy application to target environment
build Build container image
config Manage configuration
status Show deployment status
# 第二层:子命令给出聚焦选项和示例
$ mycli deploy --help
Options:
--env Target environment (staging, production)
--tag Image tag (default: latest)
--force Skip confirmation
--dry-run Preview changes without executing
Examples:
mycli deploy --env staging
mycli deploy --env production --tag v1.2.3
mycli deploy --env staging --force
设计要点:
- 示例比描述更重要——Agent 从示例中模式匹配调用方式
- 考虑提供
mycli completion --shell agent输出机器可读的命令树
3. 可预测的命令结构
规则:命令遵循统一的 resource + verb 模式,让 Agent 能从已知命令推断未知命令。
如果 Agent 学会了 mycli service list,它应该能推断出 mycli deploy list、mycli config list 也存在。一致的命名模式降低 Agent 的探索成本。
# 统一的 resource-verb 模式
mycli service list
mycli service get <id>
mycli service create --name <name>
mycli service delete <id> --yes
mycli deploy list
mycli deploy get <id>
mycli deploy create --env <env> --tag <tag>
mycli deploy rollback <id> --yes
设计要点:
- 选择一种模式并全局一致:
noun verb或verb noun - 全局 flag 位置一致(如
--json、--verbose始终可用) - 避免同义词混用(不要一处用
remove另一处用delete)
输出
4. 结构化输出
规则:成功输出应包含机器可提取的关键数据。支持 --json 切换。
Agent 需要从命令输出中提取信息用于后续步骤。纯人类友好的文本(带 emoji、颜色码、进度条)对 Agent 是噪音。
# 人类友好输出(默认)
$ mycli deploy --env staging --tag v1.2.3
✓ Deployed v1.2.3 to staging
# Agent 友好输出
$ mycli deploy --env staging --tag v1.2.3 --json
{
"status": "success",
"environment": "staging",
"tag": "v1.2.3",
"url": "https://staging.myapp.com",
"deploy_id": "dep_abc123",
"duration_seconds": 34
}
设计要点:
- 即使是默认文本输出,也应包含关键 ID 和 URL 等可 grep 的字段
- 避免在输出中混入 ANSI 颜色码(通过
--no-color/NO_COLOR环境变量禁用) - 列表类命令支持
--output table、--json、--output csv
5. 可操作错误
规则:错误信息必须告诉 Agent 下一步该做什么,而不只是说哪里出了问题。
Agent 擅长自我修正,但前提是错误信息给出了足够的修正线索。
# 反模式:模糊错误
$ mycli deploy --env staging
Error: deployment failed
# 正确:给出修正路径
$ mycli deploy --env staging
Error: No image tag specified.
Usage: mycli deploy --env staging --tag <image-tag>
Available tags: mycli build list --output tags
Latest tag: v1.2.3
设计要点:
- 使用非零退出码区分错误类型(1=用户错误,2=系统错误,3=权限错误)
- 错误输出到 stderr,正常结果输出到 stdout
# JSON 格式的错误输出
$ mycli deploy --env staging --json
{
"status": "error",
"code": "MISSING_TAG",
"message": "No image tag specified",
"suggestion": "mycli deploy --env staging --tag <image-tag>",
"related_commands": ["mycli build list --output tags"],
"retryable": false
}
retryable 字段让 Agent 区分瞬态错误(网络超时、限流)和永久错误(参数缺失、权限不足),从而决定是重试还是换策略。
执行
6. 幂等与可重试
规则:同一命令执行两次应产生相同结果,不应制造重复副作用。
Agent 会因为网络超时、上下文丢失或任务重试而重复执行命令。如果 deploy 执行两次创建了两个部署,Agent 无法安全地重试任何操作。
# 首次执行
$ mycli deploy --env staging --tag v1.2.3
deployed v1.2.3 to staging (deploy_id: dep_abc123)
# 重复执行:返回已有结果而非创建重复
$ mycli deploy --env staging --tag v1.2.3
already deployed v1.2.3 to staging (deploy_id: dep_abc123, no-op)
设计要点:
- 对于天然非幂等操作(如发送消息),在文档中明确标注
- 提供
status或get子命令让 Agent 先检查状态再决定是否执行
7. 安全预演
规则:破坏性操作必须支持 --dry-run 预览和 --yes 确认跳过。
Agent 应该能在不产生副作用的情况下验证操作计划,然后再决定是否执行。
# 预览模式:展示将要发生什么
$ mycli deploy --env production --tag v1.2.3 --dry-run
Would deploy v1.2.3 to production:
- Stop 3 running instances
- Pull image registry.io/app:v1.2.3
- Start 3 new instances
- Run health checks
No changes made.
# 确认执行
$ mycli deploy --env production --tag v1.2.3 --yes
Deployed v1.2.3 to production (deploy_id: dep_xyz789)
设计要点:
- dry-run 输出应与实际执行输出结构一致,方便 Agent 对比验证
进阶设计
以上 7 条核心原则确保单条命令可被 Agent 稳定调用。以下模式在此基础上叠加,覆盖跨命令组合、版本演进、长时间运行和权限管控等更复杂的场景。
组合性
Agent 以管道思维工作——把多个命令串联起来完成复杂任务。CLI 应支持命令间的数据流动。
# 从上游命令获取输入
mycli deploy --env staging --tag $(mycli build --output tag-only)
# 通过 stdin 传入复杂配置
cat config.json | mycli config import --stdin
# 列表输出可被下游消费
mycli service list --json | jq '.[] | select(.status == "unhealthy") | .id'
设计要点:
- 提供
--output tag-only或--output id-only等精简输出模式 - 支持
--stdin从管道读取输入 - 列表命令的 JSON 输出应是数组,方便
jq处理 - 单条记录命令的输出应是对象
$()嵌套存在命令输出注入风险,优先使用--stdin+ 管道传递复杂数据
版本与兼容性
Agent 的 skill 文件和 workflow 可能锁定特定的命令格式。CLI 的输出格式变更会破坏 Agent 的解析逻辑。
设计要点:
- 使用语义化版本号,输出格式变更视为 breaking change
- 提供
--api-versionflag 或MYCLI_API_VERSION环境变量 - 废弃字段先标记 deprecated,至少保留一个主版本周期
mycli version --json返回版本信息供 Agent 检测兼容性
超时与取消
Agent 需要知道命令是否会长时间运行,以及如何安全取消。
设计要点:
- 长时间操作支持
--timeoutflag - 超时后返回明确的超时错误码(而非静默挂起)
- 异步操作返回 job ID,提供
mycli job status <id>查询进度 - 支持
mycli job cancel <id>安全取消
# 异步操作模式
$ mycli deploy --env production --tag v2.0.0 --async
Job started: job_abc123
Check status: mycli job status job_abc123
$ mycli job status job_abc123 --json
{
"job_id": "job_abc123",
"status": "running",
"progress": "pulling image (2/4 steps)",
"started_at": "2026-05-08T10:30:00Z",
"estimated_completion": "2026-05-08T10:32:00Z"
}
权限与作用域
Agent 的操作应受到明确的权限边界约束。CLI 应让权限模型对 Agent 透明。
设计要点:
- 权限不足时返回明确错误和所需权限名称
- 提供
mycli auth whoami查看当前身份和权限 - 支持
--scope或--as限制操作范围 - 敏感操作的审计日志应包含调用者身份
$ mycli service delete prod-db --yes
Error: Permission denied.
Required: service:delete on resource prod-db
Current permissions: service:read, service:list
Request access: mycli auth request-permission service:delete
Agent-Friendly CLI 设计规范
可直接嵌入 Agent 系统规则(如 AGENTS.md)或作为 Code Review 标准。
MUST= 必须,SHOULD= 应该,MAY= 可选。
### 1. 调用规范
- [MUST] 所有必要参数通过 `--flag` 或环境变量传入,禁止运行时交互式 prompt
- [MUST] 未提供必要参数时输出错误并以非零退出码退出;不降级为交互模式
- [SHOULD] 检测到非 TTY 环境(`$CI`、`!isatty()`)时自动禁用交互,不得挂起等待
- [SHOULD] 提供 `--stdin` 或 `--file` 读取复杂输入(JSON / YAML)
- [MUST] 全局 flag 命名前后一致(禁止 `--env` 和 `--environment` 混用)
- [MUST] 命令遵循统一的 verb-noun 或 noun-verb 模式;禁止同义词混用(remove / delete)
### 2. 输出规范
- [MUST] 提供 `--json` 输出模式
- [MUST] `--json` 输出必须包含 `status` 字段(`"success"` / `"error"`)
- [SHOULD] `--json` 输出包含关键 ID、URL、耗时等可程序消费的字段
- [MUST] 数据输出到 stdout;日志、进度、诊断输出到 stderr
- [SHOULD] 支持 `--verbose` / `--debug` 输出中间步骤和调用链信息(通过 stderr,不污染 stdout 可解析数据)
- [SHOULD] 支持 `NO_COLOR` 或 `--no-color`;默认不在 stdout 输出 ANSI 颜色码
- [SHOULD] 列表类命令的 `--json` 输出为 JSON 数组
- [MAY] 列表类命令额外支持 `--output table` / `--output csv`
### 3. 错误规范
- [MUST] 错误信息包含三个部分:问题描述 + 正确用法示例 + 获取缺失信息的命令
- [MUST] 使用非零退出码区分错误类型(建议:1=参数/用户错误、2=系统/运行时错误、3=权限不足)
- [MUST] `--json` 模式下错误也输出结构化 JSON(含 `code`、`message`、`suggestion`、`retryable` 字段)
- [MUST] `retryable` 字段告知调用方可否重试:`false` 表示参数缺失等永久错误;`true` 表示网络超时等瞬态错误
### 4. 安全与幂等
- [MUST] 破坏性操作必须提供 `--dry-run`
- [MUST] 破坏性操作默认要求确认;提供 `--yes` 跳过确认
- [SHOULD] 创建/部署类命令支持幂等键或基于参数去重;重复调用返回已有结果,标注 `"created": false`
- [SHOULD] 长时间操作支持 `--timeout <seconds>`;超时后明确返回错误,不静默挂起
- [SHOULD] 权限不足时在错误信息中输出所需权限名称和当前权限列表
### 5. 可发现性
- [MUST] 顶层 `--help` 只列子命令名称和一句话描述;不展开参数
- [MUST] 每个子命令 `--help` 末尾包含 `Examples:` 段
- [SHOULD] 顶层的每条子命令描述长度不超过 60 字符
- [SHOULD] 提供 `version` 子命令,且支持 `--json` 组合输出结构化版本信息
- [MAY] 提供 `completion --shell agent` 输出机器可读的命令树
### 6. 兼容性
- [MUST] 使用语义化版本号(SemVer)
- [SHOULD] `--json` 输出格式变更视为 breaking change(MAJOR 升级)
- [SHOULD] 废弃字段先标记 `deprecated`,至少保留一个主版本周期
- [SHOULD] 支持 `--api-version` 或 `$MYCLI_API_VERSION` 锁定接口版本
参考来源
- Eric Zakariasson, "Building CLIs for agents" (2026-03) — 面向 Agent 的 CLI 设计原则原始提出
- @vasuman, "AI Agents 101" (2026-01) — Agent 工具设计三原则:单一职责、明确状态、结构化返回
- @garrytan, "Thin Harness, Fat Skills" (2026-04) — CLI 作为确定性执行层的架构定位
- Compound Engineering Plugin — 多 Agent 协作中 CLI 工具的实际使用模式