ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

解密oh-my-opencode:Categories任务路由如何把请求分派给不同Agent?

解密oh-my-opencode:Categories任务路由如何把请求分派给不同Agent?

1. 从一次请求分派失败说起:oh-my-opencode 的 Categories 到底在做什么

如果你正在用 oh-my-opencode(现在仓库已更名为 oh-my-openagent)搭多 Agent 协作流,大概率遇到过这种场景:明明在配置里写了delegate_task,任务却跑到了错误的模型上,或者干脆卡在某个 Agent 里反复重试。问题往往不在 Agent 本身,而在 Categories 这一层任务路由网关。

oh-my-opencode 的核心设计思路是"角色逻辑与物理模型解耦"。它不让一个模型或一个大 Agent 包揽所有活,而是拆成两层:Categories 负责把任务语义映射到具体模型和超参数,Agents 负责各司其职地执行。你可以把 Categories 理解成公司前台的分诊台——访客(任务)进门后不直接冲进某个办公室,而是先说明来意(Category 标识),前台根据来意把人引到对应部门(模型),并附上这个部门的工作规范(temperature、输出预算、Fallback 链)。

这套机制解决的实际问题是:多 Agent 协作时,不同任务对模型能力的要求差异极大。架构决策需要高推理预算和低温度,代码检索需要极低首字延迟,文档编排需要结构化表达。如果所有请求都打给同一个模型,要么贵得离谱,要么慢得让人抓狂。Categories 就是那个按需派发的调度层。

本文面向正在配置或排障 oh-my-opencode 多 Agent 路由的开发者,拆解从请求入口到各 Agent 职责边界的完整分派链路,给出可复制的 Categories 路由配置片段、逐 Agent 职责对照表,以及一次本地请求分派验证动作。读完你能自己确认路由命中是否符合预期,并在出错时快速定位是 Category 映射问题还是 Agent 权限问题。

2. TaoToken 前置:给 Categories 路由准备可用的模型接入层

Categories 路由再精巧,最终还是要落到具体的模型 API 上。oh-my-opencode 的 categories 配置里,每个 Category 都要绑定一个模型标识,而这个模型标识背后需要有一个稳定的接入端点。我试过直接填各家厂商的原生地址,切换和容灾时改配置很麻烦,后来统一走 TaoToken 的接入层,Base URL 和 Key 集中管理,Fallback 链切换时只改模型 ID 就行。

TaoToken 在这里的角色是模型接入网关,不是替代 oh-my-opencode 本身。oh-my-opencode 负责 Agent 编排和 Category 路由决策,TaoToken 负责把路由选中的模型请求稳定地送出去。两者是上下游关系:Categories 决定"用哪个模型",TaoToken 保证"这个模型能调通"。

你需要准备三样东西,这也是后面所有配置的基础三件套:

  • Base URL:https://taotoken.net/api,所有模型请求的统一入口
  • API Key:在控制台创建,用于鉴权
  • Model ID:每个 Category 绑定的具体模型标识,比如claude-opus、claude-sonnet、claude-haiku这类

获取 Key 的入口在控制台的 API Keys 页面,创建后复制保存。如果你还没决定用哪些模型,可以先到模型对话页面确认各模型的可用性和响应特征,再回到配置里绑定。对于长期跑编码和 Agent 任务的场景,Coding Plan 提供了更稳定的配额方案,适合把 Categories 路由长期挂上去跑。

这里要强调一个排障时最容易忽略的点:Categories 配置里的模型 ID 必须和 TaoToken 侧支持的模型标识一致。很多人路由不命中,不是 Category 逻辑写错了,而是模型 ID 拼写和实际可用标识对不上,请求发出去直接 404 或 401。配置前先在模型对话里确认一遍标识,能省掉大量排查时间。

3. 可复制的 Categories 路由配置:JSON 片段与逐 Agent 职责对照

oh-my-opencode 的 categories 配置通常写在项目根目录的配置文件里,格式是 JSON。下面这段是我实际在用的配置片段,路径和字段名保持与仓库原文一致,你可以直接复制后按自己的模型标识替换。

{ "categories": { "ultrabrain": { "model": "claude-opus", "temperature": 0.1, "max_tokens": 8192, "fallback": ["claude-sonnet", "claude-haiku"] }, "deep": { "model": "claude-sonnet", "temperature": 0.2, "max_tokens": 16384, "fallback": ["claude-opus"] }, "visual-engineering": { "model": "claude-sonnet", "temperature": 0.2, "max_tokens": 8192, "fallback": ["claude-opus"] }, "quick": { "model": "claude-haiku", "temperature": 0.0, "max_tokens": 2048, "fallback": ["claude-sonnet"] }, "writing": { "model": "claude-sonnet", "temperature": 0.3, "max_tokens": 8192, "fallback": ["claude-opus"] }, "artistry": { "model": "claude-sonnet", "temperature": 0.7, "max_tokens": 8192, "fallback": ["claude-opus"] }, "unspecified-high": { "model": "claude-sonnet", "temperature": 0.2, "max_tokens": 8192, "fallback": ["claude-opus"] }, "unspecified-low": { "model": "claude-haiku", "temperature": 0.1, "max_tokens": 2048, "fallback": ["claude-sonnet"] } } }

这段配置的关键在于每个 Category 的fallback链。当首选模型遇到 429 或超时,系统会按序切换。注意 fallback 里的模型 ID 同样要能在 TaoToken 侧调通,否则容灾链形同虚设。

配置写好后,Agent 在delegate_task时只需指定 category 标识,不用关心背后是哪个厂商的模型。系统会自动注入对应的 temperature、max_tokens,并在首选模型不可用时走 fallback。

下面是逐 Agent 的职责与推荐 Category 绑定对照表,这张表是排障时判断"任务该走哪条路由"的核心依据:

Agent层级权限边界核心职责推荐 Category
Sisyphus编排规划层全系统读写、Bash、子任务分派主入口,拆解工作流,并发拉起只读 Agentdeep
Prometheus编排规划层只读分析、交互追问、生成计划文件需求面试式提问,生成计划到.sisyphus/plans/ultrabrain 或 deep
Metis编排规划层只读分析红方挑刺,推演破坏性改动与边缘用例ultrabrain 或 artistry
Momus编排规划层只读打分与规则校验计划准入守门人,缺测试断言直接驳回ultrabrain
Atlas编排规划层清单状态读写、子任务调度拆 Todo Checklist,断点恢复quick 或 deep
Hephaestus专家攻坚层全系统读写、终端执行、独立编辑长程自主编码,修改-运行-测试-排错闭环deep
Oracle专家攻坚层严格只读,无终端无编辑高阶诊断,连续排错失败 2 次以上唤起ultrabrain
Explore只读情报层严格只读(本地文件系统)ast-grep/LSP/ripgrep 检索,并发 5~10 实例quick
Librarian只读情报层严格只读(外部网络)MCP 抓取第三方库 API 变更与文档quick
Multimodal Looker只读情报层严格只读(多模态解析)截图/设计稿解析为盒模型参数与配色建议visual-engineering

这张表里最容易配错的是 Oracle 和 Explore。Oracle 是严格只读的,如果你给它绑了deep这种带写权限的 Category,虽然模型能调通,但 Agent 的权限边界会阻止它执行编辑操作,表现为"诊断输出正常但后续动作全部失败"。Explore 绑quick是为了压低首字延迟,绑成ultrabrain会让检索任务变得又慢又贵。

4. 验证请求分派:一次本地路由命中确认动作

配置写完后不能直接上生产,先做一次本地请求分派验证,确认路由命中与 Agent 响应符合预期。这个动作的核心是:发一个明确属于某个 Category 的任务,观察它是否被路由到正确的模型,以及 Agent 是否在权限边界内正常响应。

第一步,确认配置文件被正确加载。在项目根目录执行:

cat .oh-my-opencode/config.json | python3 -m json.tool

如果 JSON 格式有误,这一步会直接报解析错误。格式没问题的话,你会看到格式化后的 categories 配置。

第二步,发一个quick类别的检索任务,验证低延迟路由:

oh-my-opencode delegate --category quick --task "用 ripgrep 找出项目中所有 export function 的定义位置"

预期结果是 Explore Agent 被唤起,以并发实例执行检索,返回压缩后的 Markdown 摘要。如果你看到返回里包含文件路径和函数名列表,说明quick路由命中,Explore 的只读权限也正常。

第三步,发一个ultrabrain类别的诊断任务,验证高推理路由:

oh-my-opencode delegate --category ultrabrain --task "分析当前模块的并发竞态风险,给出根因假设"

预期结果是 Oracle 或 Metis 被唤起,输出结构化的根因分析。注意观察响应时间——ultrabrain绑的是高推理模型,响应会比quick慢,这是正常的。如果秒回且内容浅薄,大概率是路由没命中,请求落到了unspecified-low的兜底模型上。

第四步,检查路由日志确认实际命中的模型。oh-my-opencode 会在日志里记录每次分派的 category 和最终模型:

tail -n 50 .oh-my-opencode/logs/router.log | grep -E "category|model|fallback"

日志里应该能看到类似category=quick model=claude-haiku fallback=false的记录。如果fallback=true,说明首选模型当时不可用,走了容灾链,这时候要回头检查 TaoToken 侧首选模型的可用性。

验证通过的标准是三条:Category 标识与任务语义匹配、Agent 在权限边界内响应、日志里的模型 ID 与配置一致。三条都满足,路由链路就是通的。

5. 常见错排查:401、local proxy failed、reading choices 与 OAuth 报错

路由配好后跑起来,报错基本集中在几类。下面按真实报错对照排查,每条都给出定位路径。

401 Unauthorized:这是鉴权失败,和 Category 路由逻辑无关。先检查 TaoToken 的 API Key 是否过期或被撤销,再到控制台的 API Keys 页面确认 Key 状态。如果 Key 正常,检查配置文件里 Base URL 是否写成了https://taotoken.net/api,少写/api或写成带 UTM 的地址都会导致鉴权端点不对。注意 Base URL 不要加 UTM 参数,那是给文档链接用的,API 端点保持干净。

local proxy failed:这个报错通常出现在 Agent 尝试通过本地代理转发请求时。oh-my-opencode 本身不强制走代理,如果你在环境变量里设了HTTP_PROXY或HTTPS_PROXY,而代理服务没起来,就会报这个。排查方法是先清掉代理环境变量再跑一次:

unset HTTP_PROXY HTTPS_PROXY oh-my-opencode delegate --category quick --task "test"

如果清掉后正常,说明是代理配置问题,不是路由问题。

reading choices 报错:这个报错说明请求发出去了,但响应体里没有choices字段,通常是模型返回了错误结构或空响应。常见原因是 Category 绑定的模型 ID 在 TaoToken 侧不存在,请求被路由到了一个无效端点。回到模型对话页面确认该模型标识是否可用,然后修正配置里的model字段。另一个可能是max_tokens设得过大,超过了模型上限,调小后重试。

OAuth 相关报错:如果你用的是 Claude Code 或 Codex 这类需要 OAuth 的接入方式,报错往往出在 token 刷新环节。检查auth.json里的 token 是否过期,以及 Base URL 是否指向了正确的端点。对于 Codex 的auth.json,三件套要写全:Base URL 填https://taotoken.net/api,Key 填控制台创建的 API Key,Model ID 填 Category 里绑定的模型标识。缺任何一个都会导致 OAuth 流程走不通。

排障的通用顺序是:先确认三件套(Base URL + Key + Model ID)齐全且正确,再看 Category 映射是否命中,最后查 Agent 权限边界是否阻止了操作。大部分"路由不生效"的问题,根因都在三件套里的某一项对不上。

6. 把 Categories 路由用顺:从配置到长期运行的接入建议

Categories 路由配通之后,日常使用中还有几个能提升稳定性的点。第一,fallback 链不要只写一个备选,至少两级,首选模型遇到 429 时能自动降级到次选,避免任务中断。第二,quick类别的max_tokens不要设太大,检索类任务输出本来就短,设大了反而增加延迟。第三,定期检查路由日志里的fallback=true比例,如果某个 Category 频繁走容灾,说明首选模型不稳定,该换绑定了。

如果你要把这套路由长期挂在编码和 Agent 任务上,建议走 Coding Plan 的配额方案,比按量计费更可控。接入文档里有完整的 Base URL、Key 和 Model ID 配置说明,配合本文的 Categories 配置片段,能快速把多 Agent 协作流搭起来。需要确认模型能力时,模型对话页面可以直接测试各模型对同一任务的响应差异,帮你决定每个 Category 该绑哪个模型。

最后提醒一个实操细节:oh-my-opencode 原仓库已更名为 oh-my-openagent,配置文件的路径和字段名以新仓库为准。如果你从旧文档复制配置,先核对一遍字段名是否还叫categories,避免因为仓库更名导致的配置不生效。路由链路本身的设计没变,Categories 依然是那个意图驱动的分派网关,Agent 依然按编排、攻坚、情报三层各司其职。把这两层的关系理清,多 Agent 协作的排障就有了清晰的抓手。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进