乐于分享
好东西不私藏

如何为 AI Agent 设计 CLI 工具

如何为 AI Agent 设计 CLI 工具

背景

传统 CLI 假设使用者是坐在终端前的人类——能按方向键、能读懂模糊提示、能从上下文推断下一步。但当 CLI 的调用者变成 AI Agent 时,这些隐式假设全部失效。Agent 不能处理交互式 prompt,不能从模糊错误中恢复,不能猜测未文档化的行为。

CLI 设计规范在当前节点的紧迫性由三个趋势驱动:

  1. Agent 调用取代人类调用成为主流场景 —— Claude Code、Codex CLI、Cursor 等 Agent 已常态化通过 CLI 与工具交互,CLI 不再是人类专属界面
  2. Skill/Plugin 生态爆发 —— Skill 本质上就是「CLI 工具 + Agent 使用说明」,CLI 质量直接决定 Agent 的能力天花板
  3. 传统 CLI 的隐式契约全面失效 —— TTY 检测、交互式 prompt、模糊错误信息在 Agent 语境下都是致命缺陷,必须显式化

从架构上看,CLI 工具是 Agent 的行动接口(Action Interface)。模型不直接执行工具,而是通过编排层(orchestration layer)发起调用请求。编排层负责:

  1. 参数验证:检查 flag 是否合法
  2. 权限门控:验证 Agent 是否有权执行该操作
  3. 执行与捕获:运行命令,捕获 stdout/stderr 和退出码
  4. 结果反馈:将结构化输出返回给模型用于下一步推理

一个设计良好的 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 --helpCommands:  deploy    Deploy application to target environment  build     Build container image  config    Manage configuration  status    Show deployment status# 第二层:子命令给出聚焦选项和示例$ mycli deploy --helpOptions:  --env     Target environment (staging, production)  --tag     Image tag (default: latest)  --force   Skip confirmation  --dry-run Preview changes without executingExamples:  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 listmycli config list 也存在。一致的命名模式降低 Agent 的探索成本。

# 统一的 resource-verb 模式mycli service listmycli service get <id>mycli service create --name <name>mycli service delete <id> --yesmycli deploy listmycli 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 stagingError: deployment failed# 正确:给出修正路径$ mycli deploy --env stagingError: 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.3deployed v1.2.3 to staging (deploy_id: dep_abc123)# 重复执行:返回已有结果而非创建重复$ mycli deploy --env staging --tag v1.2.3already 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-runWould deploy v1.2.3 to production:  - Stop 3 running instances  - Pull image registry.io/app:v1.2.3  - Start 3 new instances  - Run health checksNo changes made.# 确认执行$ mycli deploy --env production --tag v1.2.3 --yesDeployed 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-version flag 或 MYCLI_API_VERSION 环境变量
  • 废弃字段先标记 deprecated,至少保留一个主版本周期
  • mycli version --json 返回版本信息供 Agent 检测兼容性

超时与取消

Agent 需要知道命令是否会长时间运行,以及如何安全取消。

设计要点:

  • 长时间操作支持 --timeout flag
  • 超时后返回明确的超时错误码(而非静默挂起)
  • 异步操作返回 job ID,提供 mycli job status <id> 查询进度
  • 支持 mycli job cancel <id> 安全取消
# 异步操作模式$ mycli deploy --env production --tag v2.0.0 --asyncJob started: job_abc123Check 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 --yesError: 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` 锁定接口版本

参考来源

  • https://x.com/i/article/2036387800119975936 - Eric Zakariasson, "Building CLIs for agents" (2026-03)
  • https://x.com/vasuman/status/2011923440769659132 - @vasuman, "AI Agents 101" (2026-01)
  • https://x.com/i/article/2042922188924424198 - @garrytan, "Thin Harness, Fat Skills" (2026-04)
  • https://github.com/EveryInc/compound-engineering-plugin - Compound Engineering Plugin