Agent 时代的工具设计:从 Google Workspace CLI 看 Agent-Friendly 接口原则
通过 Google Workspace CLI 案例,阐述 Agent-Friendly 接口设计原则。
Agent 时代的工具设计:从 Google Workspace CLI 看 Agent-Friendly 接口原则
真正适合 Agent 的工具,不是“把一堆 API 暴露出来”,而是把能力、约束、文档和安全一起包装成模型能稳定使用的系统。
1. 先看问题:为什么 Agent 很难把企业工具用顺
1.1 一个真实场景
想象一个很常见的办公场景。
周一早上,你对内部 Agent 说了一句:
“帮我把今天 3 场会议相关材料整理出来,补一个会前准备会,顺手给客户发确认邮件。”
这句话对人类来说很自然,但对系统来说,其实同时涉及至少 4 类能力:
Calendar:查会议、建日程Drive:找资料、列文件Docs/Sheets:读取上下文信息Gmail:起草并发送邮件
如果工具体系设计得不好,Agent 接下来就会掉进一连串工程问题里:
- 它要不要用 SDK,还是自己拼 HTTP?
- 不同服务的认证、参数、错误结构是不是一致?
- 哪个接口是只读,哪个接口有副作用?
- 请求发出去之前,能不能先预演?
- 返回那么大的 JSON,模型到底该看哪几个字段?
这也是为什么很多团队会有一种错觉:模型已经很聪明了,但一接企业工具就变笨了。
问题往往不在模型,而在工具。
1.2 传统工具为什么对 Agent 不友好
站在人类开发者视角,传统 SDK 和 REST API 已经“够用”;但站在 Agent 视角,它们往往并不友好。
-
第一,入口碎片化。 Drive 一套 SDK,Gmail 一套 SDK,Calendar 又是一套接口风格。人可以靠经验切换,Agent 每次都要重新学习。
-
第二,文档是给人写的,不是给模型写的。 官方文档通常很完整,但并不适合在一次推理里快速消费。模型真正需要的是:这个工具什么时候用、参数怎么填、风险是什么。
-
第三,返回太大。 一个列表接口动不动几十个字段。对人只是“有点啰嗦”,对 Agent 就是直接侵占上下文窗口。
-
第四,安全能力缺位。 很多工具调用就是“调用即生效”。一旦模型被错误上下文带偏,副作用操作就会直接落地。
可以把这个问题简化成下面这张图:
问题的本质不是“接口太多”,而是Agent 面前没有一个统一、可理解、可约束的操作面。
1.3 gws 给出的答案
Google Workspace CLI(gws)之所以值得研究,不是因为它是“又一个 CLI”,而是因为它把上面这些问题系统性地拆掉了。
一句话概括:
它用一份运行时 Discovery 元数据,统一生成 CLI、Schema、自省能力和技能文档,让人和 Agent 都面对同一套可执行接口。
它的几个核心特征非常适合 Agent:
- 统一入口:所有服务都走同一套命令语法
- 自省能力:不确定参数时,可以先查
schema - 上下文友好:支持通过
fields裁剪返回内容 - 安全试探:支持
--dry-run - 技能封装:不是只暴露 API,还额外提供 Helper、Persona、Recipe
最核心的命令模式非常简单:
gws <service> <resource> <method> [flags]
例如:
gws drive files list --params '{"pageSize": 10, "fields": "files(id,name)"}'
gws calendar events insert --json '{"summary": "Team Standup"}' --dry-run
gws schema calendar.events.insert
如果把它和传统方式放在一起看,差异会更直观:
| 维度 | 传统方式 | gws |
|------|----------|-------|
| 入口 | 多个 SDK / 多套 REST 风格 | 一个统一 CLI 入口 |
| 学习成本 | 每个服务重新理解 | 学一套语法覆盖多服务 |
| 参数获取 | 靠翻文档或示例猜 | 可先查 schema |
| 结果处理 | 默认全量返回 | 可通过 fields 精简 |
| 风险控制 | 调用即生效 | 支持 --dry-run |
| 面向 Agent 的文档 | 基本没有 | 有技能文档和工作流封装 |
2. 再讲技术:gws 是怎么做到的
回到开头那个场景:如果要让 Agent 稳定完成一次“查会议 + 找资料 + 发邮件”的跨系统任务,底层工具至少要解决三件事——能力发现、参数确定、风险控制。gws 的技术实现,基本就是围绕这三件事展开的。
2.1 先给地图:它不是一个 CLI,而是一套元数据驱动系统
理解 gws,最重要的是先看到全局地图。
它的核心不是手写了一堆命令,而是把 Google Discovery Document 当成唯一真相源。然后围绕这份元数据,同时生成 4 类能力:
这件事为什么重要?
因为一旦元数据成了控制面,上层能力就不用各自维护一份真相:
- 命令树不需要手写
- 参数定义不需要手工同步
- 技能文档不需要重复抄 API 文档
- 新增服务时也不必改一堆分支逻辑
对大厂平台来说,这一点非常关键:不要把变化扩散到 SDK、文档、Prompt 和脚本里;要尽量把变化收敛到元数据层。
2.2 两阶段解析:先认服务,再生成命令树
gws 的入口在 main.rs,实现思路很巧妙:它不是一次把参数全解析完,而是分两步。
第一步,先判断你要操作哪个服务。
程序会先扫描命令行,识别出 drive、calendar、gmail 这类 service;如果是 schema、auth、generate-skills 这种静态命令,就直接走固定分支。
第二步,拿到服务后,再去拉 Discovery 文档并动态生成命令树。
Discovery JSON 会在 discovery.rs 里被解析成 RestDescription、RestResource、RestMethod 等结构,然后交给 commands.rs 动态构建 clap::Command 树,再重新解析完整参数。
整个过程可以理解成:
这个设计的价值在于:接口不是编译期写死的,而是运行时“长出来”的。
这也是它能做到“服务新增了,CLI 基本就跟着有了”的根本原因。
2.3 执行器做的,不只是“发请求”
真正把命令落到 HTTP 请求上的,是 executor.rs。这部分是我觉得最能体现工程成熟度的地方。
它做的不是简单包装 reqwest,而是把 Agent 友好性做进了执行链路里:
- 解析输入:把
--params、--json、--upload统一转成结构化数据 - 本地校验:根据 Discovery Schema 校验必填项和 body 结构
- 构建请求:自动处理 URL、query、认证头、分页、上传等细节
- 支持预演:
--dry-run下只输出请求预览,不真正调用 API - 处理结果:支持分页、格式化、必要时做内容 sanitize
这条链路很重要,因为它把很多原本要靠模型“自己记住”的事情,下沉到了执行层。
对于 Agent 来说,这意味着两件事:
- 它需要记住的协议细节更少了
- 它在本地就能发现更多错误,而不是等远端 API 报错后再猜
如果只用一句话总结这一层:
优秀的工具不是让模型承担更多责任,而是让执行器承担更多工程复杂度。
2.4 schema 和 Skills:让 Agent 从“猜”变成“查”
很多工具对 Agent 不友好,不是因为能力不够,而是因为不可解释。
模型不知道:
- 这个方法到底需要什么参数
- 请求体有哪些字段
- 哪些字段是必填
- 某个目标到底该调用原始 API,还是该走高频封装
gws 用两层设计解决了这个问题。
第一层:schema 自省
schema.rs 提供了一个非常关键的能力:
gws schema drive.files.list
gws schema calendar.events.insert
gws schema drive.File
这等于给 Agent 提供了一个“查接口的接口”。
对于模型来说,这比喂一大段文档更有效,因为它可以在不确定时先问系统,而不是靠上下文猜。
第二层:技能分层
generate_skills.rs 又在原始 API 之上,多做了一层 Agent 友好的能力压缩。它不是只生成一份 API 列表,而是分成 4 层:
- Service Skill:这个服务有哪些原子能力
- Helper:把高频动作压成更短路径,比如
+send、+agenda - Persona:按角色组合能力
- Recipe:把多步流程包装成工作流模板
可以把它理解成下面这张图:
这套结构的意义,不是“文档更漂亮了”,而是模型决策成本更低了。
同样是“帮我准备会议”,Agent 没必要每次都从底层 API 开始拼命令;它应该优先看到更短、更稳定、更符合业务意图的能力入口。
2.5 安全设计:默认把输入和输出都当成不可信
如果说上面几层解决的是“好不好用”,那安全层解决的是“敢不敢让 Agent 真用”。
gws 的安全思路很值得借鉴:不要把工具当成一条直通后端的裸通道。
它至少做了 4 件事:
- 输入校验:
validate.rs会限制 API 标识、资源名、目录路径等,避免路径逃逸和恶意拼接 - 结构校验:真正发请求前,会根据 Schema 验证 body 和参数
- 凭据保护:
credential_store.rs使用AES-256-GCM加密本地凭据,并尽量借助 OS keyring - 内容防护:开启
--sanitize时,还会对返回内容做 Model Armor 检测,降低 prompt injection 风险
这背后反映的是一个观念变化:
过去我们默认“API 返回的就是数据”;但在 Agent 时代,外部返回内容本身也可能是攻击载荷。
所以真正成熟的工具链路应该是:
先校验输入,再验证结构,再支持预演,再执行请求,最后检查输出。
3. 对我们的启示:企业内部工具该怎么为 Agent 重做一遍
如果把 gws 只当成一个 Google 项目来看,意义并不大。它真正值得我们带走的,是一套更适合 Agent 时代的平台设计方法。
我建议至少记住下面 6 条。
3.1 给 Agent 一个统一操作面,不要让它面对 N 套协议
内部平台常见的问题不是能力不够,而是入口太多:HTTP、RPC、脚本、页面操作、团队自建 SDK 并存。
对人来说这叫“复杂”;对 Agent 来说,这叫“无法稳定学习”。
所以第一件事不是继续加工具,而是统一入口和命名方式。这个入口可以是 CLI,可以是 MCP,也可以是内部 Tool Gateway,但它至少应该做到:
- 参数风格一致
- 错误语义一致
- 权限边界一致
3.2 Schema First,不要让模型靠猜参数工作
如果一个工具只有自然语言描述,没有机器可读的 Schema,它短期也许能跑 Demo,长期一定不稳定。
真正适合 Agent 的接口,应该同时提供:
- 参数定义
- 请求/响应 Schema
- 必填项和默认值
- 可查询的 introspection 能力
一句话:文档是给人看的,Schema 是给系统用的。
3.3 返回结果要能裁剪,不要默认把全量 JSON 扔给模型
很多平台默认返回“大而全”的数据,这在人类系统里只是体验问题,在 Agent 系统里就是成本和稳定性问题。
因此值得优先补的能力包括:
fields/selectlimit/pageTokensummary/compact view
让模型少看一点,往往比让模型更聪明一点更有用。
3.4 高风险操作必须支持预演、确认和审计
delete、publish、send、transfer 这类动作,不应该让 Agent 直接黑盒执行。
至少要有三道保护:
- 预演:先看将要执行什么
- 确认:高风险动作有人机回环
- 审计:调用链路可追踪、可复盘
如果没有这些保护,再聪明的 Agent 也只是更高效地制造事故。
3.5 工具要分层,不要逼模型每次都从原始 API 开始
在真实业务里,工具至少应该分三层:
- Raw Tool:保证能力覆盖
- Helper Tool:承接高频动作
- Workflow Tool:承接多步业务流程
这是因为用户目标往往不是“调用某个 API”,而是“完成某件事”。
如果平台只给原子 API,不给高频封装,复杂度最终还是会回到模型身上。
3.6 面向 Agent 的文档,不该是 API 文档的搬运版
很多团队现在做 Agent 接入,还是把 Swagger、Confluence、内部 wiki 直接塞进提示词。这种方式很快就会碰到两个问题:
- 信息太多,模型抓不住重点
- 文档结构适合人浏览,不适合模型决策
更合适的文档应该回答这几个问题:
- 什么时候用这个工具?
- 什么时候不要用?
- 输入参数和最小示例是什么?
- 输出结构是什么?
- 风险和副作用是什么?
如果能做到自动生成,就更好,因为只要靠人工维护,文档迟早会漂移。
4. 结尾:启示
对于公司里做内部平台、MCP、Agent Tool 或统一接入层,建议先把下面三件事做好:
- 先统一元数据:把参数、Schema、权限、副作用标签结构化
- 再补自省和预演:让 Agent 能先查、先看、再执行
- 最后做高频封装:把常见任务抽成 Helper 和 Workflow,而不是只暴露底层 API
这三件事做好之后,你会发现一个很重要的变化:
Agent 的提升,不再只来自模型更聪明,而是来自工具终于变得可理解、可约束、可复用。
这也是 gws 最值得研究的地方。
它不是简单地把 Google Workspace API 包了一层 CLI,而是在认真回答一个更大的问题:
Agent 时代,平台能力应该如何被重新包装,才能真正进入生产。