Agent-FriendlyCLI工具设计指南

admin 2026-03-12 22:32:28 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 文章探讨了AIAgent时代CLI工具的设计挑战,指出传统CLI假设用户为人类成为障碍。通过对比MCP与CLI的token成本,证明CLI具有9-13倍成本优势。提出八条工程规则,包括结构化输出、幂等性设计、退出码控制流等,并提供Python实现框架。最后讨论了记忆文件与Skills的协同工作机制,为Agent友好的CLI工具设计提供了全面解决方案。 综合评分: 88 文章分类: AI安全,安全工具,解决方案,安全开发,应用安全


cover_image

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.mdCLAUDE.mdAIDER.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. 不要尝试"快速修复",先回滚再分析

记忆文件带来三个核心价值:

  1. 避免重复踩坑:新 Agent 或新成员不会遇到已知问题
  2. 统一处理策略:所有 Agent 面对错误时采取一致的应对方式
  3. 降低风险:危险操作有明确的检查清单

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 工具开发者:

  1. 提供官方 Skills:在文档中提供工具的使用说明和最佳实践
  2. 提供 Skill 模板:在 examples/skills/ 目录提供典型工作流示例
  3. 保持 Skill 更新:工具更新时,同步更新 Skill 中的命令示例

项目团队:

  1. 维护 Agents.md:记录项目特定的坑点、限制和错误处理策略
  2. 创建团队 Skills 库:将常用工具的使用技巧和工作流封装为 Skills
  3. 持续沉淀经验:遇到新问题时及时更新 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 参数,而是一个系统工程:

核心要点

  1. 架构层面:从设计之初就将“数据”与“展示”分离
  2. Token 经济学:CLI 比 MCP 节省 9-13 倍的 token 成本
  3. 可靠性:本地进程调用 vs 网络连接(100% vs 72%)
  4. 八条规则:结构化输出、非交互模式、退出码、干运行、自描述、可操作错误、批量操作、管道组合
  5. Skills 生态:通过 Agents.md 降低 Agent 学习成本

实施建议

新项目:

  • 从第一天就遵循八条规则
  • 使用现代框架(如 Typer + Pydantic)
  • 编写完整的 Agents.md 文档

现有项目:

  • 优先级 1:实现 --json 和 --non-interactive 参数
  • 优先级 2:标准化退出码体系
  • 优先级 3:添加 --agent-info 自描述端点

最后的思考

工具的设计哲学正在发生根本性转变。过去我们为人类设计工具,现在我们需要为“人类 + AI Agent“设计工具。

这不是简单的功能增强,而是一次范式转移

那些率先适应这一转变的工具,将在 AI 时代获得更广泛的采用和更长久的生命力。


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:先进攻防 rayh4c rayh4c《Agent-Friendly CLI 工具设计指南》

评论:0   参与:  0