gongji-skills 是共绩算力的开源 Agent 工具库,每个 skill 里都带一份 api/*.md 接口文档(共 63 个文件),供 Agent 构造 API 请求时参考。这些文档是从 Apifox 手工导出的快照,有一个根本问题:接口更新了,快照不会跟着变。
我们提交了 PR #2([https://github.com/suanleme/gongji-skills/pull/2],diff +2031/−5,12 个文件),把文档获取方式改成了 read-through 实时查询。这篇文章讲清三件事:为什么这么改、被放弃的方案是什么样的、以及我们如何验证”Agent 真的会用”。
- 会过期:共绩侧接口变更后,Agent 按旧文档构造请求可能直接出错;
- 同步成本高:每次接口变更都要手工重新导出 63 个文件、提交发版;
- 体积大:63 个文档占了仓库绝大部分体积,而一次 Agent 会话往往只用其中一两个接口。
第一版方案(PR #1,已放弃并关闭)是”同步式”:写一个 fetch_apifox.py 把 Apifox 批量拉回本地,重写全部 63 个 api/*.md 加 manifest。问题在于 Agent 读到的还是本地文件——要拿到最新内容,每次仍要有人跑同步脚本、提交、发版。“实时读最新”的目标根本没达成,diff 却高达 +7278/−24372。
最终方案(PR #2)是”read-through”:每个 skill 新增一个自带脚本 scripts/apidoc.py,Agent 需要文档时直接运行它,从 Apifox 官网分享页所用的公开 JSON 接口实时拉取并渲染成 markdown。
对比项 | 同步式(放弃) | read-through(采用) |
|---|---|---|
Agent 读到什么 | 本地快照文件 | Apifox 实时内容 |
接口更新后生效时间 | 等人跑同步脚本 + 发版 | 即刻生效 |
diff 规模 | +7278 / −24372 | 约 +650 行 |
脚本只用 Python 标准库(urllib / json / argparse),零第三方依赖,Python 3.6+ 可跑,和原 skill 的运行前提完全一致:
python scripts/apidoc.py list
python scripts/apidoc.py get task-create
python scripts/apidoc.py search 计费几个设计决策:
- 每 skill 一份:与既有的
scripts/call.sh、scripts/call_encrypt.py同级并列,单装某个 skill 也不会缺文件; - 容错优先:网络请求指数退避重试 3 次;API 树 10 分钟缓存(存系统临时目录,不污染仓库);退出码约定明确——0 成功 / 2 网络失败(提示回退读静态文档)/ 3 参数错 / 4 未找到;
- 静态文档保留:63 个
api/*.md原样保留作离线回退,不删除不重写,回滚只需 revert。
功能测试相对常规:5 个 skill × 9 项断言共 49 项功能冒烟(真网直连 Apifox)、2 项跨 skill 隔离(deployment 的短名在 job 里查不到,别名不串)、2 项容错回退(不可达主机重试 3 次后 exit 2 并提示回退),全部通过。
真正有说服力的是失忆 Agent 验证(clean-room 测试)。改造的成败关键在于:一个没有任何上下文的 Agent,拿到 skill 后会主动跑实时查询吗?测试方法:启动一个全新子 Agent——它不知道这次改造、不知道 apidoc.py 的存在——只给它 suanli-job skill 目录和”构造创建 Job 请求体”的任务,并提前删除 API 树缓存(任何查询必须走真网络)。
实测行为路径:
- 读 SKILL.md,看到”完整字段优先实时查 Apifox”的指引;
- 主动运行
apidoc.py get /task/job/create,缓存文件在测试时刻重新生成,证实为真网络拉取; - 同时读静态
api/job-create.md,与实时输出互为印证(两者一致); - 产出完全正确的请求体:Spot 默认模式、
estimated_exec_sec仅 Spot 必填、mod_param的两种 oneOf 模式,还主动剔除了 Apifox 示例中夹带的回显字段(status等不在 requestBody schema 内)。
结论:Agent 读一遍 SKILL.md 就会走实时查询,无需任何额外提示。静态文档也没有被浪费——Agent 两条路都走、互为印证,正是"实时优先 + 静态回退"双轨设计的预期行为。
- 所用的是 Apifox 分享页的公开接口,非正式对外承诺的 API,若其结构变更需要适配脚本(改动集中在一个渲染函数内);
- API 树缓存 10 分钟:接口更新后
list/search最长 10 分钟内还是旧树,但get详情永远实时,可用--refresh强制刷新; - 若共绩侧更换 Apifox 分享链接,需同步改 5 个脚本头部的 SHARE_ID 常量。
这次改造的本质是给”Agent 的知识来源”做减法:与其维护一份庞大的快照并承担同步成本,不如把查询动作本身交给 Agent,让它在需要时拿到永远是最新的答案。+650 行换来”发版不再需要同步文档”,这笔账怎么算都划算。
PR 已开,欢迎审阅:[https://github.com/suanleme/gongji-skills/pull/2]。如果你也在维护带接口文档的开源 Agent 工具库,read-through 是一个值得参考的模式。