模型
Coograph 会把活分给六个代理,而它们的需求相差一个数量级。explore 读得多、判断少;debugger 读得少、判断全靠它。六个都跑在同一个模型上,要么为读的部分多花钱,要么让思考的部分力不从心。
Claude Code 一直支持给每个代理、每次调用单独指定模型。Coograph 现在用上了,而且会先问你。
五个工具,而模型清单是你的。 Claude Code、Cursor、VS Code Copilot、Codex CLI 和 OpenCode 都能给每个代理单独指定模型,所以 Coograph 会把映射写到那个工具读的地方。它做不到的是猜你手上有哪些模型:这五个工具要的模型 id 各不相同。所以由你声明一份清单,建议就按你的模型、你的价格来算。Aider 和 Cline 是完全另一回事 —— 见下面的覆盖范围。
它从不替你决定
全新安装带的是 models.mode: unset。那不是一套默认映射,而是没有映射:每个代理都继承你当前会话的模型,和以前完全一样。
项目里的第一个工单会问一次,在调查之后、提案之前——因为那是第一次真正了解这活长什么样的时刻:
Coograph 可以让每个代理跑在不同模型上。你想所有代理用同一个模型、存一套映射,还是每个工单都问一次?
你的答案写进 openspec/config.yaml,然后无论你选了什么,这个问题都不会再出现。每个工单都问一遍,正是那种会让好功能因为错误原因被关掉的摩擦。
四种模式
| 模式 | 行为 |
|---|---|
unset | 出厂状态。下一个工单问一次,之后再也不问。 |
off | 每个代理继承会话模型,永远不再提出建议。 |
preset | 静默套用已保存的映射,只有异常工单才会冒出建议。 |
per-task | 每个工单都先给出建议再使用。 |
# openspec/config.yaml
models:
mode: preset
preset:
explore: haiku
search: haiku
verifier: sonnet
reviewer: opus
debugger: opus
planner: opus
retro: opus
sync 从不覆盖 config.yaml,所以你的选择能扛过模板更新。
两条命令
/coograph-suggest-multi-models 给出一套映射,针对项目或针对手头这个工单。每一行都写明代理、模型、一句基于你这次改动的理由,以及相对会话模型的预计成本差。你可以改任何一行、整体接受、或者拒绝。在你接受之前什么都不会写。它也是重新开启一个已关闭项目的入口。
/coograph-disable-multi-models 一步把 mode 设成 off。不会再问你一遍确认,因为这条命令只干这一件事。已保存的映射会留着,所以再打开时不用从零开始。
每次运行都告诉你是哪个模型干的
一次委派运行结束时会有一行:
models: reviewer=opus (mapping), explore=haiku (mapping)
它在每种模式下都打印。off 和 unset 时它显示 (inherited) 并写出你的会话模型。这一行就是关键:没有它,你分不清映射是生效了还是被悄悄忽略了,而一个看不见的功能和一个坏掉的功能没有区别。
你的模型清单
一份映射只有在它写的模型你的工具能加载时才有意义,而没有两个工具的写法是一样的。Cursor 要 composer-2。OpenCode 要 provider/model-id。Copilot 只认它自家厂商的模型。由我们发一张 Anthropic 别名表,对大多数人是错的,对其余的人是错得您无声无息。
所以清单是你的。每个别名绑定到你的工具能加载的 id,加上大致的每百万 token 价格——正是后者让建议能用你的口径而不是我们的口径报出成本差:
# openspec/config.yaml
models:
mode: preset
catalog:
cheap: { id: claude-haiku-4-5, in: 1, out: 5 }
mid: { id: claude-sonnet-5, in: 2, out: 10 }
capable: { id: claude-opus-5, in: 5, out: 25 }
preset:
explore: cheap
search: cheap
verifier: mid
reviewer: capable
debugger: capable
上面那些 id 是例子,不是默认值。Coograph 一份清单都不附带。
没有清单,什么都不变。 在 Claude Code 上,四个内置别名照旧能用。在其他工具上,建议会请你先声明一份清单,而不是编一个加载时会报错的 id。它从不从 API key、已装的 SDK 或你正在用的工具去推测清单。
preset 里出现一个清单没定义的别名,是错误,不是猜测:它会说出是哪个别名,然后停下。
哪个代理配哪一档
角色映射到你的别名,所以重要的是形状而不是名字:
| 代理 | 档位 | 理由 |
|---|---|---|
explore、search | 最便宜 | 大量阅读与归纳。token 量大、判断少,能省最多。 |
verifier | 中档 | 跑命令、把结果对照既定标准检查。机械性工作。 |
debugger | 强档 | 找根因正是便宜模型靠猜、把省下的钱又烧回去的地方。 |
reviewer | 强档 | 抓到一个真缺陷,就把差价赚回来很多倍。 |
planner | 强档 | 量小、杠杆高,它决定了后面一切的形状。 |
retro | 强档 | 读一份确定性报告并据此论证。 |
建议会随活的性质调整。一个文件、改法显而易见的改动,不需要昂贵的审查;并发 bug、数据迁移、鉴权路径或任何碰钱的东西,结论正好相反。最高档通常是中档的好几倍价,只有真正困难、长周期的活才值得。
值得知道的代价
提示缓存是按模型隔离的。六个代理分到四个模型,就是六个缓存命名空间而不是一个,而一次短的代理运行,缓存未命中损失的可能比按 token 省下的还多。这正是便宜模型只配给读得多的代理的原因:它们跑得够久,能摊薄这笔开销。这也是为什么一条提出三个或更多模型的建议会明说这一点。
还有两条限制,直说:建议是根据工单文字和文件数量猜的,所以有时会猜错——这就是为什么不经你接受什么都不会套用。还有上面那张价格表会过期;命令本身会重申记录日期,并说明这些是估算。
覆盖范围
有五个工具会把活分给 Coograph 的代理,所以按角色选模型在那里是一个真实的设置。每个工具要求写的地方不同,Coograph 就写到那里:
| 工具 | 映射写到哪里 |
|---|---|
| Claude Code | Agent 调用上的 model 参数 |
| Cursor | .cursor/agents/ 或 .claude/agents/ 下子代理 markdown 的 model: frontmatter |
| VS Code Copilot | .github/agents/*.agent.md 的 model: frontmatter |
| Codex CLI | ~/.codex/agents/ 下的 TOML 代理定义,还能带推理强度 |
| OpenCode | opencode.json 里的代理,id 用 provider/model-id 形式 |
你没有映射的角色会继承,不会被钉死。
写不了的映射会被拒绝,而不是拿个差不多的顶上。 VS Code Copilot 只能解析它自家厂商的模型,所以清单里写了别的 id 会被驳回,并说明是哪个 id、受什么限制。写一个接近的值、等工具加载时才报错,比直接说不更糟。
Aider 和 Cline
不支持,也不在计划内 —— 因为根本没有可支持的东西。
Coograph 在这两个工具里是以规则的形式跑的。只有一个代理,它包干所有活,所以没有角色可以配模型。Aider 的 --editor-model 和 --weak-model,以及 Cline 分开的 Plan 和 Act 模型,都是那些工具自己的流水线阶段。把 Coograph 的 reviewer 挂到 Aider 的 editor 槽位上,不是把七个角色有损地压成三个;运行时压根儿就没有一个 reviewer 可压。
如果你用这两个,选一个模型自己设就行。这就是全部答案,把它说成“即将支持”只会暗示一份永远不该到来的工作。