首页
/ oh-my-openagent 的 `max_background_agents` 后台代理并发限制:一份从分支、原子提交到三门禁验证的完整执行计划

oh-my-openagent 的 `max_background_agents` 后台代理并发限制:一份从分支、原子提交到三门禁验证的完整执行计划

2026-09-04 21:34:51作者:廉皓灿Ida

本文以仓库中一份真实的功能执行计划文档为骨架,逐阶段拆解 oh-my-openagent 为后台代理(background agent)新增 max_background_agents 配置项的完整交付流程:Worktree 环境准备、两个原子提交的实现设计、PR 创建、CI / review-work / Cubic 三重门禁验证循环,以及合并与清理。读完后你将掌握该特性"为什么这样设计、改哪些文件、如何验证、如何收尾"的全链路细节,并能对照仓库源码理解每处设计决策的落点。

这份执行计划位于 execution-plan.md,是一份"可直接照做"的 PR 工作手册;同目录下的 code-changes.md 则给出了每个文件的具体改动代码,二者可配合阅读。

功能背景:给后台代理加一道"全局上限"

oh-my-openagent 允许主会话派生多个后台代理并行执行子任务。现有的并发控制是按模型维度的:每个模型(或 provider)各自有并发上限,超出的任务进入该 key 的排队队列。执行计划要解决的问题是:当用户同时使用多个模型时,各模型各自跑满,全局同时运行的后台代理总数不受控。为此计划新增一个跨模型/跨 provider 的全局配置项 max_background_agents(配置路径 background_task.maxBackgroundAgents),默认值 5,最小值 1。

仓库当前源码印证了这一前提:

  • 配置 Schema BackgroundTaskConfigSchema 目前包含 defaultConcurrencyproviderConcurrencymodelConcurrencymaxDepthmaxLiveDescendantsPerRoot、各类超时与熔断字段,尚无 maxBackgroundAgents 字段——说明该特性在本文快照中仍是待实施状态;
  • ConcurrencyManager 只维护 Map<key, count> 的按模型计数与等待队列,getConcurrencyLimit() 在未配置任何并发项时返回默认值 5(concurrency.ts 第 39 行)——计划中全局上限默认 5 与这一既有默认值刻意保持一致,避免行为突变;
  • BackgroundManager.launch() 目前先经 reserveSubagentSpawn 通过派生守卫,再创建 status: "pending" 的任务并按并发 key 入队。计划中的全局检查正是插在这一链路的前置位置。

Phase 0:环境准备——分支 + Worktree

执行计划的第一步是隔离开发环境,保证主工作树(main worktree)始终干净:

  1. dev 分支拉取最新代码并创建特性分支:

    git checkout dev && git pull origin dev
    git checkout -b feat/max-background-agents
    
  2. 在兄弟目录创建 worktree:

    mkdir -p ../omo-wt
    git worktree add ../omo-wt/feat-max-background-agents feat/max-background-agents
    
  3. 计划明确规定:后续所有工作都发生在 ../omo-wt/feat-max-background-agents/,绝不在主工作树中操作。这一约束在 Phase 4 的清理步骤中与之呼应。

Phase 1:实现——两个原子提交

Commit 1:在配置 Schema 中新增 max_background_agents

涉及文件(计划路径):

实现要点:

  • 新增字段定义为 maxBackgroundAgents: z.number().int().min(1).optional()
  • 默认值放在运行时处理(默认 5),而不是写进 Schema——这是遵循项目约定:Schema 中所有字段均为 optional,默认值由消费方(ConcurrencyManager)在运行时兜底;
  • 测试采用项目既有的 given/when/then 风格,覆盖四个场景:合法值、低于最小值(0)、未提供(应为 undefined)、非数字(应为 ZodError)。

Commit 2:在 BackgroundManager + ConcurrencyManager 中强制执行全局上限

涉及文件(计划路径):

  • src/features/background-agent/concurrency.ts — 增加全局计数与 getGlobalRunningCount()canSpawnGlobally() 等方法(对应当前仓库 concurrency.ts
  • src/features/background-agent/concurrency.test.ts — 全局上限的测试用例
  • src/features/background-agent/manager.ts — 在 launch()trackTask() 中检查全局上限(对应 manager.ts

实现要点:

  • ConcurrencyManager 已管理按模型并发,计划新增一个独立的全局计数器,而不改动现有队列机制:

    • private globalRunningCount: number = 0
    • private maxBackgroundAgents: number(来自配置,默认 5)
    • acquireGlobal() / releaseGlobal() 配对方法
    • getGlobalRunningCount() 用于可观测性
  • BackgroundManager.launch() 在创建任务前调用 concurrencyManager.canSpawnGlobally() 检查;trackTask()(外部任务注册入口)同样要过这道检查;

  • 任务完成、取消或出错时调用 releaseGlobal() 归还名额(配套的 code-changes.md 进一步指明释放点分布在 tryCompleteTask()cancelTask()session.error 事件处理与 prompt 错误处理器中,且 pending 状态的任务从不占用名额);

  • 触顶时抛出带指引的描述性错误:

    Background agent spawn blocked: ${current} agents running, max is ${max}.
    Wait for existing tasks to complete or increase background_task.maxBackgroundAgents.
    

    错误信息直接告诉用户"等现有任务完成"或"调大 background_task.maxBackgroundAgents",把排查路径写进了异常本身。

本地验证

计划要求两个提交完成后依次执行:

bun run typecheck
bun test src/config/schema/background-task.test.ts
bun test src/features/background-agent/concurrency.test.ts
bun run build

Phase 2:创建 PR

推送分支并创建以 dev 为基线的 PR:

git push -u origin feat/max-background-agents
gh pr create \
  --base dev \
  --title "feat: add max_background_agents config to limit concurrent background agents" \
  --body-file /tmp/pull-request-max-background-agents-$(date +%s).md

PR 正文以文件形式准备后用 --body-file 注入,时间戳命名避免本地文件冲突。

Phase 3:验证循环——三道门禁

执行计划的核心特色是把 PR 验证拆成三道独立门禁(Gate),全部通过才允许合并。

Gate A:CI

  • 等待 ci.yml 工作流完成;
  • gh pr checks <PR_NUMBER> --watch 实时盯结果;
  • 失败时:读日志、修复、推送、重新等待。

Gate B:review-work(5 个并行后台子代理)

运行 /review-work skill,它并行启动 5 个后台子代理做交叉审查:

  1. Oracle — 目标/约束核验(改动是否忠于 PR 目标);
  2. Oracle — 代码质量;
  3. Oracle — 安全性;
  4. Hephaestus — 动手执行 QA;
  5. Hephaestus — 从 GitHub/git 历史中挖掘上下文。

5 个必须全部通过;任何一个失败都要修复并重新推送。

Gate C:Cubic 机器人(cubic-dev-ai[bot])

  • 等待 Cubic bot 在 PR 上给出评审;
  • 必须输出 "No issues found";
  • 若发现问题:逐条处理反馈、推送、重新检查。

循环结构

三个门禁构成一个显式循环,直到全绿:

while (!allGatesPass) {
  if (CI fails) → fix → push → continue
  if (review-work fails) → fix → push → continue
  if (Cubic has issues) → fix → push → continue
}

值得注意的是,Gate B 本身就在"用这个仓库的后台代理机制来审查这个改动后台代理限制的 PR"——特性与验证手段形成了自我印证。

Phase 4:合并 + 清理

  1. Squash 合并并删除远端分支:

    gh pr merge <PR_NUMBER> --squash --delete-branch
    
  2. 移除 Phase 0 创建的 worktree,与开头形成闭环:

    git worktree remove ../omo-wt/feat-max-background-agents
    

文件影响面总览

计划给出的 File Impact Summary(计划路径 → 当前仓库对应路径):

文件(计划路径) 改动类型
src/config/schema/background-task.ts Modified — 新增 schema 字段
src/config/schema/background-task.test.ts Modified — 新增校验测试
src/features/background-agent/concurrency.ts Modified — 新增全局上限计数
src/features/background-agent/concurrency.test.ts Modified — 新增全局上限测试
src/features/background-agent/manager.ts Modified — 在 launch/trackTask 中强制执行全局上限

共 5 个文件、2 个原子提交,不新建任何文件(刻意沿用既有组织模式)。其中 src/ 前缀相对 omo-opencode 包根目录,在当前仓库快照中对应 packages/omo-opencode/src/ 前缀。

源码纵深:计划落点在当前仓库中的证据

把执行计划映射回当前仓库源码,可以看到每个设计决策都有明确的"接口缝":

  1. 按模型队列与全局计数分而治之concurrency.tsQueueEntry 采用 settled-flag 模式防止 release()cancelWaiters() 双重 resolve,release() 会优先把空闲槽位直接"移交"给队首等待者。这套机制只作用于单一 key,跨 key 语义(全局总数)无法由它表达,因此计划选择叠加一个简单计数器(globalRunningCount + acquireGlobal/releaseGlobal),而不重构既有队列——这也是 File Impact Summary 中 concurrency.ts 仅标注"Modified"、约 25 行的原因。
  2. 默认值 5 的一致性getConcurrencyLimit() 的兜底默认是 5(concurrency.ts#L39),全局上限沿用同一默认值,意味着未配置用户在新旧语义下的体感并发规模一致。
  3. 检查点与释放点配对launch()manager.ts#L579)创建任务时状态为 pending 并立即入队,计划让全局名额在任务注册时 acquireGlobal()、在 tryCompleteTask() / cancelTask() / session.error / prompt 错误处理中 releaseGlobal(),并明确 pending 从未 acquire 的任务在取消时不 release,保证计数不漂移。
  4. trackTask() 是第二道入口。除 launch() 外,外部创建的任务经 trackTask()manager.ts#L1216)注册,计划特意让它也过 canSpawnGlobally() 检查,堵住"绕过 launch 的旁路不受全局上限约束"的漏洞。
  5. 配置文档联动background_task 各配置项的使用方式在 docs/reference/configuration.mddocs/reference/omo-json.md 中有对应章节,新字段合入后这些文档即为 max_background_agents 的用户可见说明落点;测试侧则已有 background-task.test.ts 的 given/when/then 用例族可直接追加。

需要说明的适用前提:本快照中 BackgroundTaskConfigSchema 尚未包含 maxBackgroundAgentsconcurrency.ts 也不存在全局计数字段,因此本文描述的"实现"是执行计划所规划的目标状态,而非当前树中已合并的行为;文中所有 src/... 计划路径均按上述 packages/omo-opencode/src/... 映射理解。

登录后查看全文
热门项目推荐
相关项目推荐