CCB 多 Agent 协作开发 TODO API 踩坑记录

用 Python 写一个 TODO API,不过是教科书级别的练习题。增删改查,四个动词,几张表,几条路由,任何有经验的人闭着眼睛都能完成。真正有意思的,是这次借助 CCB 多 Agent 架构完成任务的过程——Claude Opus 做设计决策,OpenCode(Sonnet 4.6)负责执行落盘——暴露出来的那几处裂缝。

考古的价值不在出土了什么,在于那些断层告诉你哪里曾经发生过什么。

背景

任务:用 Python + FastAPI 写一个 TODO API,支持增删改查。使用 CCB(Claude Code Bridge)多 Agent 架构,Claude Opus 做设计决策,OpenCode(Sonnet 4.6)做代码执行。

坑 1:角色映射表未更新,Claude 自己动手写代码

CCB 配置文件 ~/.claude/rules/ccb-config.md 中的角色映射表还是旧的:

| executor | claude | Code implementation |
| reviewer | codex  | Scored quality gate  |

实际环境里已经没有 Codex,取而代之的是 OpenCode(Sonnet 4.6)。结果 Claude 按照 executor = claude 的配置,直接自己写文件,没有委托出去。

解决:更新角色映射表,将 executorreviewer 都指向 opencode,同时更新 .ccb/ccb.configopencode,gemini,claude

教训:换 provider 后,必须同步更新两个地方:

  1. ~/.claude/rules/ccb-config.md 的 Role Assignment 表
  2. 项目根目录 .ccb/ccb.config 的 provider 列表

配置文件是系统的自我认知。认知不更新,行为就在旧地图上漫游。这不是 bug,是系统在忠实地执行一份已经过期的现实描述。

坑 2:系统 Python 被 PEP 668 保护,pip install 直接失败

在 macOS 上直接运行 pip install -e ".[dev]" 报错:

error: externally-managed-environment
hint: See PEP 668 for the detailed specification.

macOS 自带的 Python 3.x 受系统保护,不允许直接安装第三方包。

解决:必须先创建虚拟环境:

1
2
3
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"

教训:Python 项目永远先建 venv,这一步应该写进 OpenCode 的任务指令里,而不是假设环境已准备好。

系统在划定边界。边界之内是它的领地,外来者需要另起炉灶。这道墙并不刁难人,它只是要求你在动手之前先搞清楚自己站在哪里。

坑 3:/tr 流程依赖 FileOpsREQ 协议,实际执行路径不通畅

/tr skill 的设计是通过 /file-op 发送 FileOpsREQ JSON 给 Codex 执行文件操作。但实际情况:

  1. /file-op skill 内部假设 executor 是 Codex
  2. FileOpsREQ 协议链路较长(Claude 设计 → 构建 JSON → /file-op → ask codex → Codex 解析 → 执行)
  3. 换成 OpenCode 后,中间环节不一定能无缝衔接

解决:跳过 FileOpsREQ 协议,直接通过 /ask opencode 发送完整的代码内容和执行指令。OpenCode 一次性完成文件创建、依赖安装、测试运行。

教训:协议越长越脆弱。对于明确的任务,直接把完整代码和指令塞进 /ask 比走 FileOps 协议更高效可靠。

驿站越多,消息走形的机会越多。这是很古老的道理,只是每一代人都要在新的形式下重新验证一遍。

坑 4:记忆系统中的 provider 信息过时

持久记忆 multi_agent_setup.md 里记录的还是旧配置(Copilot CLI、Codex),导致新 session 可能读到错误的角色分工信息。

解决:及时更新记忆文件和 MEMORY.md 索引,确保 provider 列表和角色映射与实际环境一致。

教训:换工具链后,除了改配置文件,还要更新 Claude 的持久记忆。否则下次 session 启动时会加载过时信息。

人会遗忘,系统不会——它只会原封不动地保存,连同那些早已作废的信念。定期清理记忆,是对自己和系统都负责的事。

坑 5:Gemini 中文写作质量差,角色错配

尝试将博客风格化改写任务委托给 Gemini(/ask gemini),要求「高尔泰式技术散文」风格。结果辞藻堆砌、比喻用力过猛(「荒芜的逻辑之野」「灵魂的构思」),离克制留白的要求差得很远。

原因:Gemini 的中文写作能力偏弱,无法把控微妙的文风要求,容易滑向浮夸。

解决:风格化写作任务不应交给 Gemini,改由 Claude 或 OpenCode 完成。Gemini 仅用于灵感发散和信息检索。

教训:角色分配要匹配能力边界。Gemini 适合当 inspiration(头脑风暴、备选方案),不适合做终稿输出,尤其是中文写作。

克制是一种稀缺能力。拿到一个「高尔泰式」的要求,最大的陷阱不是写不像,而是用力过猛地模仿一种表面特征,结果走成了它的反面。工具的边界,需要用一次失败来测量。

最终方案总结

有效的工作流是:

Claude(设计决策)
  ↓ 设计完整代码 + 执行指令
  ↓ /ask opencode "创建文件... 安装依赖... 跑测试..."
OpenCode(Sonnet 4.6 执行)
  ↓ 创建文件、pip install、pytest
  ↓ 返回结果
Claude(审查结果、更新状态)

关键点:

  • Claude 负责设计所有代码内容,OpenCode 负责落盘和执行
  • 任务指令要完整自包含(包括 venv 创建、依赖安装、测试命令)
  • /ask opencode 直接发送,比 FileOpsREQ 协议链路短、更可靠
  • 结果回来后 Claude 审查并更新任务状态

结果

  • 7 个文件一次性创建成功
  • 11/11 测试通过,覆盖率 94%
  • 全程 Claude 未直接写入任何源码文件,全部由 OpenCode 执行

五个坑,没有一个是新鲜的。配置漂移、环境假设、协议脆弱、记忆腐化、能力错配——这些问题在任何足够复杂的系统里都会出现,只是穿着不同时代的衣服。

测试全过,覆盖率 94%。剩下的 6%,留给那些还没发生的事。