文章总结: 文章探讨了AIAgent时代CLI工具的设计挑战,指出传统CLI假设用户为人类成为障碍。通过对比MCP与CLI的token成本,证明CLI具有9-13倍成本优势。提出八条工程规则,包括结构化输出、幂等性设计、退出码控制流等,并提供Python实现框架。最后讨论了记忆文件与Skills的协同工作机制,为Agent友好的CLI工具设计提供了全面解决方案。 综合评分: 88 文章分类: AI安全,安全工具,解决方案,安全开发,应用安全
Agent-Friendly CLI 工具设计指南
原创
rayh4c rayh4c
先进攻防
2026年3月12日 14:05 北京
当 AI Agent 成为开发工具链的一等公民,我们需要重新思考 CLI 工具的设计哲学。
写在前面
2026 年初,Claude Code 和 Gemini CLI 等 Agentic 工具已经悄然进入不少开发团队的日常工作流。然而,一个被长期忽视的技术债务逐渐浮出水面:
现有 CLI 工具的设计假设用户是人类。
这个假设看似理所当然,却在 AI Agent 时代成为了最大的障碍。本文将从真实案例出发,深入剖析 CLI 工具的 Agent 适配问题,并提供完整的工程解决方案。
问题的本质:当 Agent 遇上传统 CLI
GitHub CLI 的典型案例
执行 gh issue list 时的默认输出:
#123 Bug: Login fails open 2 days ago
#122 Feature: Dark mode open 5 days ago
对人类友好,但对 AI Agent 是噩梦:
- 列宽不固定:标题长度不同导致列对齐变化
- 时间格式模糊:“2 days ago” 需要计算当前时间
- 缺少明确分隔符:空格数量不确定,正则表达式容易失效
添加 --json 后:
[
{
"number": 123,
"title": "Bug: Login fails",
"state": "open",
"createdAt": "2026-03-10T10:00:00Z"
}
]
问题迎刃而解:结构明确、类型清晰、时间精确。Agent 可以零成本解析。
架构层面的根本差异
传统 CLI 架构:
用户输入 → 业务逻辑 → 格式化输出(表格) → 终端显示
这是一个线性流程,数据在业务逻辑层就被格式化为人类可读的表格形式,Agent 难以解析。
Agent 友好架构:
用户输入 → 业务逻辑 → 结构化数据 → 分支渲染
- 分支一:JSON 渲染器(供 Agent 使用)
- 分支二:表格渲染器(供人类使用)
这种架构在业务逻辑层输出纯粹的结构化数据,然后根据不同的使用场景选择不同的渲染器。
这里的核心在于:需要在设计之初就将“数据”与“展示”分离,而不是事后打补丁。
Token 经济学:MCP vs CLI 的成本真相
MCP 的 Schema Injection 开销
Model Context Protocol 通过 JSON-RPC 暴露工具定义。以 GitHub Copilot MCP Server 为例:
- 暴露 43 个工具
- 每个工具的 schema 平均 1,200-1,800 tokens
- 累计消耗 50,000-80,000 tokens
- 占 GPT-4o 128k 上下文窗口的 40-60%
这意味着,还没开始真正的对话,就已经消耗了一半的上下文窗口。
CLI 的零 Schema 成本
gh issue create \
--repo owner/repo \
--title "Bug: 登录失败" \
--label bug
为什么 CLI 不需要 schema?因为 LLM 在预训练阶段已经见过大量 gh 命令示例(来自 GitHub CI 配置、Stack Overflow、技术博客),模型已经“知道”参数和返回格式,无需运行时注入 schema。
这就像是一个经验丰富的工程师,不需要每次都查阅文档,就能熟练使用常用工具。
实测数据对比
国外某团队 2026 年 3 月的 benchmark(Claude Sonnet 4):
任务一:创建 Issue
- MCP 方式:Schema 注入 52,000 + 对话 8,500 = 总计 60,500 tokens(9.3x)
- CLI 方式:Schema 注入 0 + 对话 6,500 = 总计 6,500 tokens(1x)
任务二:列出 PR
- MCP 方式:Schema 注入 52,000 + 对话 12,000 = 总计 64,000 tokens(13.3x)
- CLI 方式:Schema 注入 0 + 对话 4,800 = 总计 4,800 tokens(1x)
任务三:复杂工作流
- MCP 方式:Schema 入 156,000 + 对话 45,000 = 总计 201,000 tokens(11.2x)
- CLI 方式:Schema 注入 0 + 对话 18,000 = 总计 18,000 tokens(1x)
数据很直观:MCP 的 token 成本是 CLI 的 9-13 倍。
可靠性对比
实测 25 次调用 GitHub Copilot MCP Server:
- 成功:18 次
- 失败:7 次(ConnectTimeout)
- 成功率:72%
CLI 本地进程调用:成功率 100%
MCP 采用 Client-Server 架构,引入了端口冲突、进程崩溃、启动延迟等问题。CLI 通过 fork() + exec() 完成,无网络依赖,稳定性更高。
八条工程规则
基于 Anthropic 工具编写指南、GitLab glab 的 agent-friendly proposal 和社区实践,我们总结出八条核心规则。
规则 1:结构化输出是第一优先级
import sys, json
# ✅ 正确:数据输出到 stdout,日志输出到 stderr
print(json.dumps(data), file=sys.stdout)
print("正在处理...", file=sys.stderr)
# 进阶:支持 JSON Lines(流式输出)
for item in items:
print(json.dumps(item))
# 使用扁平结构,避免深层嵌套
{"project_name": "项目A", "created_at": "2026-03-10T10:00:00Z"}
# 类型一致性:统一使用 ISO 8601
{"created": "2026-03-10T10:00:00Z"}
规则 2:非交互模式与幂等性
def confirm(message):
if non_interactive or not sys.stdin.isatty():
return True # 自动确认
response = input(f"{message} (y/n): ")
return response.lower() == 'y'
# 幂等性设计
def ensure_project(name):
if project_exists(name):
return {"status": "exists", "id": get_project_id(name)}
else:
return {"status": "created", "id": create_project(name)}
Agent 只需一条命令 mytool ensure project-123 --json,无需先检查再创建,大大简化了工作流程。
规则 3:退出码作为控制流信号
class ExitCode:
SUCCESS = 0
GENERAL_ERROR = 1
INVALID_ARGS = 2
NOT_FOUND = 3
PERMISSION_DENIED = 4
CONFLICT = 5
TIMEOUT = 124
# 结合 JSON 错误对象
{
"error": {
"code": "RESOURCE_CONFLICT",
"message": "项目已存在",
"suggestion": "使用 --force 覆盖",
"is_retryable": false
}
}
Agent 可以根据退出码和错误信息自动修复,实现智能重试和错误恢复。
规则 4:干运行与预览机制
$ mytool delete --selector "type=test" --dry-run --json
{
"operation": "delete",
"affected_items": [
{"id": "proj_1", "name": "test-api"}
],
"impact": "2 个项目将被删除,1 个部署将失效"
}
Agent 可以基于 impact 字段智能判断操作风险,决定是否继续执行。
规则 5:工具能力的自描述
$ glab --agent-info
{
"version": "1.35.0",
"capabilities": {
"json_output": true,
"dry_run": true,
"batch_operations": true
},
"recommended_flags": ["--json", "--non-interactive"],
"exit_codes": {
"0": "成功",
"3": "资源不存在",
"5": "资源冲突"
}
}
Agent 首次调用时获取完整能力清单,无需依赖 MCP schema。
规则 6:错误信息的可操作性
{
"error": {
"code": "AUTH_FAILED",
"message": "认证失败:访问令牌已过期",
"actions": [
"运行 'mytool login' 重新认证",
"或设置 MYTOOL_TOKEN 环境变量"
],
"is_retryable": false
}
}
Agent 可以根据 actions 字段自动执行修复操作,实现自愈能力。
规则 7:批量操作与选择器
# ❌ 传统方式:3 次调用
$ mytool delete project-1
$ mytool delete project-2
$ mytool delete project-3
# ✅ Agent-friendly:1 次调用,token 降低 60-70%
$ mytool delete --selector "type=temp,age>7d" --json
{
"deleted": ["project-1", "project-2", "project-3"],
"count": 3
}
通过批量操作,不仅减少了 API 调用次数,还大幅降低了 token 消耗。
规则 8:Unix 哲学与管道组合
# 单一职责,通过管道组合
mytool list --json \
| jq '.[] | select(.status == "active")' \
| jq 'sort_by(.created_at)' \
| mytool to-csv \
| aws s3 cp - s3://bucket/data.csv
保持工具的单一职责,通过 Unix 管道实现复杂功能的组合,这是经典的 Unix 哲学在 AI 时代的延续。
实现框架:Python + Typer
下面是一个完整的实现示例,展示如何将八条规则落地到实际代码中:
from typer import Typer, Option
from pydantic import BaseModel
import json, sys
app = Typer()
class Project(BaseModel):
id: int
name: str
status: str
created_at: str
class ExitCode:
SUCCESS = 0
NOT_FOUND = 3
CONFLICT = 5
@app.command()
def list_projects(
json_output: bool = Option(False, "--json"),
selector: str = Option(None, "--selector")
):
"""列出所有项目"""
try:
projects = fetch_projects()
if selector:
projects = filter_projects(projects, selector)
if json_output:
print(json.dumps({"projects": projects, "total": len(projects)}))
else:
print(f"共 {len(projects)} 个项目")
for p in projects:
print(f" #{p.id} {p.name} ({p.status})")
sys.exit(ExitCode.SUCCESS)
except Exception as e:
if json_output:
print(json.dumps({"error": {"code": "INTERNAL_ERROR", "message": str(e)}}))
sys.exit(1)
@app.command()
def ensure_project(
name: str,
json_output: bool = Option(False, "--json")
):
"""幂等的项目创建操作"""
existing = find_project_by_name(name)
if existing:
result = {"status": "exists", "project": existing.dict()}
else:
new_project = create_project(name)
result = {"status": "created", "project": new_project.dict()}
if json_output:
print(json.dumps(result))
else:
print(result["status"])
sys.exit(ExitCode.SUCCESS)
@app.command(name="agent-info")
def agent_info():
"""输出 Agent 元数据"""
info = {
"version": "1.0.0",
"capabilities": {
"json_output": True,
"dry_run": True,
"batch_operations": True
},
"recommended_flags": ["--json", "--non-interactive"],
"exit_codes": {
"0": "成功",
"3": "资源不存在",
"5": "资源冲突"
}
}
print(json.dumps(info, ensure_ascii=False, indent=2))
if __name__ == "__main__":
app()
Agent 生态:记忆文件与 Skills 的协同
在 Agent-friendly CLI 的生态中,有两个关键概念常被混淆:记忆文件(Memory Files)和 Skills(技能)。它们各司其职,共同降低 Agent 的使用成本。
记忆文件:Agents.md / CLAUDE.md
记忆文件是放置在项目根目录的静态文档,用于记录项目的注意事项、常见错误和处理策略。
核心特点:
- 被动读取:Agent 在执行任务前自动读取,无需显式调用
- 经验沉淀:记录项目特定的坑点、限制条件、错误处理方式
- 项目级配置:每个项目一份,针对特定项目的注意事项
典型的文件名包括 Agents.md、CLAUDE.md、AIDER.md 等。
适用场景:
- 项目有特殊的环境要求或限制条件
- 某些操作容易出错,需要提前告知 Agent
- 有特定的错误处理策略需要 Agent 遵守
示例:在项目根目录创建Agents.md
# 项目注意事项
## 环境限制
- 本项目依赖 Python 3.11+,低版本会导致类型检查失败
- 数据库连接池最大 10 个连接,并发操作时注意控制
- Redis 缓存 TTL 设置为 5 分钟,不要假设数据永久存在
## 常见错误
### 1. 部署失败:端口被占用
**现象**:部署时报错 "Address already in use"
**原因**:测试环境的旧进程未正确清理
**解决**:执行 `./scripts/cleanup.sh` 清理僵尸进程后重试
### 2. 测试超时
**现象**:集成测试在 CI 中超时
**原因**:外部 API mock 服务启动慢
**解决**:在测试前添加 30 秒等待,或使用 `--skip-integration` 跳过
### 3. 数据库迁移冲突
**现象**:多人同时提交迁移文件导致冲突
**原因**:迁移文件命名冲突
**解决**:提交前先 pull 最新代码,重新生成迁移文件
## 操作规范
### 危险操作检查清单
执行生产环境操作前必须:
1. 确认当前分支是 `main`
2. 执行 `make verify` 通过所有检查
3. 通知 #ops 频道,获得至少一人确认
4. 使用 `--dry-run` 预览影响范围
### 回滚策略
如果部署后 5 分钟内错误率超过 1%:
1. 立即执行 `./scripts/rollback.sh`
2. 在 #incident 频道报告
3. 不要尝试"快速修复",先回滚再分析
记忆文件带来三个核心价值:
- 避免重复踩坑:新 Agent 或新成员不会遇到已知问题
- 统一处理策略:所有 Agent 面对错误时采取一致的应对方式
- 降低风险:危险操作有明确的检查清单
Skills:工具使用说明与工作流
Skills 是可复用的工具使用说明、技巧和工作流程,教会 Agent 如何正确使用特定工具。
核心特点:
- 主动调用:Agent 根据任务需求选择并执行 Skill
- 跨项目复用:一个 Skill 可以在多个项目中使用
- 工具导向:聚焦于“如何使用工具”而非“项目特定问题”
两者的本质区别:记忆文件记录项目坑点(项目级),Skills 教工具用法(全局级)。
Skill 示例(SKILL.md 格式):
---
name: github-cli-guide
description: GitHub CLI (gh) 使用指南,包含常用操作和错误处理
version: 1.0.0
allowed-tools: Bash
---
# GitHub CLI 使用指南
## 核心原则
- 所有自动化场景必须使用 `--json` 参数
- 使用 `--repo` 明确指定仓库,避免依赖当前目录
## 常用操作
### 创建 Issue
gh issue create \
--repo owner/repo \
--title "Bug: 登录失败" \
--json number,url
### 批量操作
gh issue list --json number --jq '.[].number' | \
xargs -I {} gh issue close {}
## 错误处理
- 退出码 2:认证失败,运行 `gh auth login`
- 退出码 4:资源不存在,确认仓库名和权限
协同工作:记忆文件 + Skills
最佳实践是将两者结合使用:Skills 教工具用法(通用知识),记忆文件提醒项目坑点(项目经验)。
示例:
Skill 定义通用部署流程:
---
name: production-deployment-basic
description: 基础的生产环境部署流程
---
# 生产环境部署
### 步骤 1: 预检查
mytool check --env production --json
### 步骤 2: 部署
mytool deploy --env production --json
Agents.md 提醒项目特定问题:
# 部署注意事项
## 已知问题
- 生产环境的 Redis 连接池只有 5 个,部署时会短暂断开
- 部署窗口:工作日 22:00-23:00,避开业务高峰
## 错误处理
- 如果预检查报 "Redis connection timeout",等待 30 秒重试
Agent 执行时:从 Skill 学会命令,从 Agents.md 知道 Redis 超时和时间窗口限制。
实施建议
CLI 工具开发者:
- 提供官方 Skills:在文档中提供工具的使用说明和最佳实践
- 提供 Skill 模板:在
examples/skills/目录提供典型工作流示例 - 保持 Skill 更新:工具更新时,同步更新 Skill 中的命令示例
项目团队:
- 维护 Agents.md:记录项目特定的坑点、限制和错误处理策略
- 创建团队 Skills 库:将常用工具的使用技巧和工作流封装为 Skills
- 持续沉淀经验:遇到新问题时及时更新 Agents.md
工程价值:
- Skills:教会 Agent 如何使用工具(通用能力,可跨项目复用)
- 记忆文件:提醒 Agent 项目特定问题(项目经验,避免重复踩坑)
- 两者结合:Agent 既掌握工具使用方法,又了解项目特殊情况
MCP 的适用场景
CLI 并非银弹。以下场景应使用 MCP:
多租户与 OAuth 认证
SaaS 产品中 AI 助手需代表不同用户访问 GitHub。MCP 在协议层面实现按用户的 token 管理,支持细粒度权限和审计日志。
动态工具发现
企业内部 200+ 工具,每个用户只能访问 10-20 个。MCP Server 根据用户身份动态返回可用工具列表。
实时数据流
MCP 支持 Server-Sent Events,可以推送实时更新,无需轮询。
选择指南
| 场景 | 推荐方案 | 原因 | | — | — | — | | 本地开发 | CLI | 零配置,可靠性高 | | CI/CD | CLI | 无需额外服务 | | SaaS AI 功能 | MCP | 多租户隔离 | | 企业 AI 助手 | MCP | 动态权限控制 | | 实时数据处理 | MCP | 事件推送 |
简单来说:单用户环境用 CLI,多用户环境用 MCP;静态工具集用 CLI,动态工具集用 MCP。
总结
Agent-friendly CLI 不是简单加个 --json 参数,而是一个系统工程:
核心要点
- 架构层面:从设计之初就将“数据”与“展示”分离
- Token 经济学:CLI 比 MCP 节省 9-13 倍的 token 成本
- 可靠性:本地进程调用 vs 网络连接(100% vs 72%)
- 八条规则:结构化输出、非交互模式、退出码、干运行、自描述、可操作错误、批量操作、管道组合
- Skills 生态:通过 Agents.md 降低 Agent 学习成本
实施建议
新项目:
- 从第一天就遵循八条规则
- 使用现代框架(如 Typer + Pydantic)
- 编写完整的 Agents.md 文档
现有项目:
- 优先级 1:实现
--json和--non-interactive参数 - 优先级 2:标准化退出码体系
- 优先级 3:添加
--agent-info自描述端点
最后的思考
工具的设计哲学正在发生根本性转变。过去我们为人类设计工具,现在我们需要为“人类 + AI Agent“设计工具。
这不是简单的功能增强,而是一次范式转移。
那些率先适应这一转变的工具,将在 AI 时代获得更广泛的采用和更长久的生命力。
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:先进攻防 rayh4c rayh4c《Agent-Friendly CLI 工具设计指南》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。











评论