工人泳道 是看板调度器可以路由任务的一类进程。每个泳道都有一个身份标识(受理人字符串)、一种启动机制,以及一份关于启动后必须如何处理任务的协议。
本页面即是该协议。它面向两类受众:
- 操作人员(Operators):负责挑选哪些泳道接入看板(创建哪些配置文件、使用哪些受理人)。
- 插件/集成作者:希望添加新的泳道形式(例如封装了 Codex / Claude Code / OpenCode 的 CLI 工人、容器化的审查工人,或通过 API 拉取任务的非 Hermes 服务)。
如果你正在编写工人代码本身——即在泳道 内部 运行的智能体——那么 kanban-worker 技能(skill)提供了更深层次的程序细节。
Hermes Kanban = canonical task lifecycle + audit trailWorker lane = implementation executor for one assigned cardReviewer = human or human-proxy that gates "done"GitHub PR = upstreamable artifact (optional, for code lanes)Hermes Kanban 掌握生命周期的真相 —— ready → running → blocked / done / archived。工人泳道负责执行工作,但永远不掌握该真相;它们所做的一切都会通过 kanban_* 工具(或者对于非 Hermes 外部工人,通过 API)流回看板内核。审查者负责把控从“代码变更已编写”到“任务完成”的转变。
泳道提供的内容
Section titled “泳道提供的内容”要成为一个看板工人泳道,集成必须提供以下三样东西:
1. 一个受理人字符串 (Assignee string)
Section titled “1. 一个受理人字符串 (Assignee string)”调度器会将 task.assignee 与 Hermes 配置文件名称(默认泳道形式)或注册的不可派生标识符(插件泳道形式 —— 参见下文的 添加外部 CLI 工人泳道)进行匹配。受理人无法解析的任务将保持在 ready 状态,并触发 skipped_nonspawnable 事件,以便看板操作员进行修复;这些任务不会被默默丢弃,也不会由任意的备选方案执行。
2. 一种启动机制 (Spawn mechanism)
Section titled “2. 一种启动机制 (Spawn mechanism)”对于 Hermes 配置文件泳道,调度器通过 _default_spawn 在任务固定的工作空间内运行 hermes -p <assignee> chat -q <prompt>(或当 $PATH 中没有 hermes 垫片时的等效模块形式),并设置以下环境变量:
| 变量名 | 携带内容 |
|---|---|
| HERMES_KANBAN_TASK | 工人正在操作的任务 ID |
| HERMES_KANBAN_DB | 每个看板唯一的 SQLite 文件的绝对路径 |
| HERMES_KANBAN_BOARD | 看板别名 (slug) |
| HERMES_KANBAN_WORKSPACES_ROOT | 看板工作空间树的根目录 |
| HERMES_KANBAN_WORKSPACE | 该任务工作空间的绝对路径 |
| HERMES_KANBAN_RUN_ID | 当前运行的 ID(用于生命周期门控) |
| HERMES_KANBAN_CLAIM_LOCK | 认领锁定字符串 (<host>:<pid>:<uuid>) |
| HERMES_PROFILE | 工人自身的配置文件名称(用于 kanban_comment 的作者归属) |
| HERMES_TENANT | 租户命名空间(如果该任务有租户) |
对于非 Hermes 泳道(通过插件注册),插件会提供自己的 spawn_fn 可调用对象,该对象接收 task、workspace 和 board 参数,并返回一个用于崩溃检测的可选 PID。
3. 一个生命周期终止符 (Lifecycle terminator)
Section titled “3. 一个生命周期终止符 (Lifecycle terminator)”每一次认领必须以以下情况之一明确结束:
- kanban_complete(summary=…, metadata=…) — 任务成功,状态翻转为
done。 - kanban_block(reason=…) — 任务等待人工输入,状态翻转为
blocked。当执行kanban_unblock时,调度器会重新派生工人。 - 工人进程在没有工具调用的情况下退出。内核会回收它并发出
crashed(PID 死亡)、gave_up(触发连续失败断路器)或timed_out(超过最大运行时间max_runtime)信号。这是失败路径;健康的工人不应在此结束。
看板内核强制要求每次运行必须由上述情况之一终止。既没有调用工具又正常退出的工人将被视为已崩溃(crashed)。
产出与“需要评审”惯约
Section titled “产出与“需要评审”惯约”对于大多数代码变更任务,工作在工人完成的那一刻并算不上真正的 完成——它需要一名人类评审员。看板内核并不强制执行这种区别(“代码变更任务” 定义较模糊,且对每个代码工人强制执行 “以阻塞代替完成” 会破坏那些不需要评审的流程)。这是一种叠加在系统之上的惯约:
- **以阻塞(Block)代替完成,并在
reason(原因)前缀加上review-required:**:这样仪表板和hermes kanban show就会将该行显示为等待评审。 - 先将结构化元数据放入
kanban_comment(评论)中:因为kanban_block仅携带人类可读的reason。评论是持久的标注通道——每一个与审计相关的字段(changed_files、tests_run、diff_path或 PR URL、decisions)都属于这里。 - 评审员要么批准并解除阻塞(这会携带包含后续跟进评论的上下文重新派生工人);要么通过另一条评论要求更改,下一个工人运行周期通过
kanban_show的上下文即可看到这些内容。
kanban-worker 技能中包含了 kanban_complete(真正的终结性任务——如拼写修复、文档更改、研究报告)和 review-required 阻塞模式的实践案例。
日志与审计追踪
Section titled “日志与审计追踪”调度器会将每个任务的工人标准输出/错误(stdout/stderr)写入 <board-root>/logs/<task_id>.log。日志可以通过看板元数据进行审计:
task_runs(任务运行)行携带log_path、退出代码(如果可用)、摘要和元数据。task_events(任务事件)行携带每一次状态转换(promoted、claimed、heartbeat、completed、blocked、gave_up、crashed、timed_out、reclaimed、claim_extended)。kanban_show返回上述两者,因此读取任务的评审员(或后续工人)无需访问仪表板即可获取完整历史记录。
仪表板会渲染带有摘要、元数据块和退出状态徽章的运行历史。CLI 用户可以运行 hermes kanban tail <task_id> 进行实时跟踪,或运行 hermes kanban runs <task_id> 查看历史尝试列表。
现有泳道形式
Section titled “现有泳道形式”Hermes 配置文件泳道(默认)
Section titled “Hermes 配置文件泳道(默认)”目前每个看板工人采用的形式:受理人是一个配置文件名称,调度器派生 hermes -p <profile>,工人自动加载 kanban-worker 技能以及 KANBAN_GUIDANCE 系统提示词块,并使用 kanban_* 工具终止运行。除了定义配置文件外,无需额外设置。
当你为你的集群创建配置文件时,请选择与你希望编排器(orchestrator)路由到的 角色 相匹配的名称。编排器(如果存在)会通过 hermes profile list 发现你的配置文件名称——系统不预设固定的名册(有关合约的编排器端,请参阅 kanban-orchestrator 技能)。
编排器配置文件泳道
Section titled “编排器配置文件泳道”配置文件泳道的一种特殊化:编排器是一个 Hermes 配置文件,其工具集包含 kanban 但不包含用于实现的 terminal / file / code / web。它的工作是将高级目标通过 kanban_create + kanban_link 分解为子任务并退居幕后。编排器技能编码了这些 “防诱惑” 规则。
添加外部 CLI 工人泳道
Section titled “添加外部 CLI 工人泳道”将非 Hermes 的 CLI 工具(如 Codex CLI、Claude Code CLI、OpenCode CLI、本地编码模型运行器等)接入作为看板工人泳道目前尚非现成的路径。调度器的派生函数是可插拔的(spawn_fn 是 dispatch_once 的一个参数),插件可以为非 Hermes 的受理人注册自己的 spawn_fn,但相关的集成工作——如将 CLI 的退出代码包装进 kanban_complete / kanban_block 调用、将 CLI 的工作空间/沙箱惯例映射到调度器的 HERMES_KANBAN_WORKSPACE 环境变量、处理身份验证及各 CLI 特有的策略——仍属于需要逐一设计的集成工作。
如果你正考虑添加 CLI 泳道,请提交一个 Issue 来描述具体的 CLI 以及你尝试启用的工作流。上文所述的“协议”是任何此类泳道必须满足的约束;具体的实现形式(是为每个 CLI 开发一个插件,还是开发一个通过配置参数化的通用 CLI 运行器插件)仍处于开放讨论状态。
与之相关的历史 Issue 为 #19931,以及已关闭但未合并的 Codex 专用 PR #19924 —— 它们描述了最初的架构提案,但并未最终落地运行器。
调度器处理的故障模式
Section titled “调度器处理的故障模式”为了让泳道作者无需重复实现这些功能,调度器处理了以下情况:
- 过期认领 TTL (Stale claim TTL) — 如果一个工人认领了任务,但从未发送心跳(heartbeat)、完成(complete)或阻塞(block),则在
DEFAULT_CLAIM_TTL_SECONDS(默认 15 分钟)后会被回收——但前提是该工人进程确实已经死亡。对于存活的工人(如正在进行长达 20 分钟以上、无工具调用的 LLM 推理的慢速模型),其认领会被延长而非杀掉;只有检测到 PID 消失时才会被回收。 - 崩溃的工人 (Crashed worker) — 宿主机本地 PID 消失的工人会被
detect_crashed_workers检测到并进行收尾;任务的consecutive_failures(连续失败次数)会递增,并可能在断路器跳闸时自动进入阻塞状态。 - 运行级重试 (Run-level retry) — 当任务重试时(阻塞后、崩溃后、回收后),工人在终止工具上可以使用
expected_run_id参数,以便在自身运行已被取代时快速失败。 - 单任务最大运行时间 (Per-task max runtime) —
task.max_runtime_seconds强制限制了单次运行的挂钟时间(wall-clock time),无论 PID 是否存活。这能捕获那些因 PID 存活检测而可能被不断延长的真正死锁的工人。 - 滞留任务检测 (Stranded-task detection) — 如果一个处于
ready状态的任务其受理人在kanban.stranded_threshold_seconds(默认 30 分钟)内从未产生认领,则在hermes kanban diagnostics中会显示为stranded_in_ready警告。严重程度在 2 倍阈值时升级为错误(error),在 6 倍时升级为紧急(critical)。这一信号能统一捕获拼写错误的受理人、已删除的配置文件以及宕机的外部工人池——它不区分身份,无需手动维护各看板的白名单。
- Kanban 概览 — 面向用户的介绍。
- Kanban 教程 — 结合仪表板的演练。
- kanban-worker — 工人进程加载的技能。
- kanban-orchestrator — 编排器端。