Kanban 工作线程通道

工作线程通道(Worker lane) 是 kanban 分发器可以将任务路由到的一类进程。每个通道有一个身份(分配者字符串)、一个生成机制和一个关于生成后必须用任务做什么的契约。

本页就是这个契约。它面向两个受众:

  • 运维人员 选择哪些通道接入工单板(创建哪些配置,使用哪些分配者)
  • 插件/集成作者 想要添加新的通道形状(包装 Codex / Claude Code / OpenCode 的 CLI 工作线程、容器化审查工作线程、通过 API 拉取任务的非 Hermes 服务)

如果您正在编写工作线程代码本身——在通道内部运行的代理——kanban-worker 技能包含更深层的程序细节。

层次结构

Hermes Kanban  = 规范的任务生命周期 + 审计线索
Worker lane    =  一个已分配卡片的实现执行器
Reviewer       =  门控"完成"的人类或人类代理
GitHub PR      =  可上游化的产物(可选,用于代码通道)

Hermes Kanban 拥有生命周期真相——readyrunningblocked / done / archived。工作线程通道执行工作但从不拥有那个真相;它们所做的一切通过 kanban_* 工具(或对于非 Hermes 外部工作线程,通过 API)流回 kanban 内核。审查者门控从”代码更改已编写”到”任务已完成”的转换。

通道提供的内容

要成为 kanban 工作线程通道,集成必须提供三样东西:

1. 分配者字符串

分发器将 task.assignee 与 Hermes 配置名称(默认通道形状)或已注册的不可生成标识符(插件通道形状——参见下面的添加外部 CLI 工作线程通道)匹配。分配者未解析的任务以 skipped_nonspawnable 事件留在 ready 状态,以便工单板运维人员可以修复它们;它们不会被静默丢弃或由任意回退执行。

2. 生成机制

对于 Hermes 配置通道,分发器的 _default_spawn 在任务的固定工作空间内运行 hermes -p <assignee> chat -q <prompt>(或当 hermes 垫片不在 $PATH 上时的等效模块形式),设置以下环境变量:

变量携带内容
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 可调用对象,接收 taskworkspaceboard,并返回一个可选的 pid 用于崩溃检测。

3. 生命周期终结器

每个认领必须恰好以以下之一结束:

  • kanban_complete(summary=..., metadata=...) —— 任务成功,状态翻转为 done
  • kanban_block(reason=...) —— 任务等待人工输入,状态翻转为 blocked。当 kanban_unblock 运行时分发器重新生成
  • 工作线程进程退出而没有工具调用。内核回收它并发出 crashed(PID 死亡)或 gave_up(连续失败断路器跳闸)或 timed_out(超过 max_runtime)。这是失败路径;健康的工作线程不会在这里结束

kanban 内核强制执行这些恰好一个终止每个运行的条件。既不调用又正常退出的工作线程被视为崩溃。

输出和需要审查的约定

对于大多数更改代码的任务,工作线程完成时工作并不真正完成——它需要人类审查。kanban 内核不强制执行这个区别(“更改代码的任务”是模糊的,在每个代码工作线程上强制执行”阻塞而非完成”会破坏不需要审查的流程)。它是一个层叠在顶部的约定:

  • 阻塞而非完成reasonreview-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 阻塞模式的工作示例。

日志和审计线索

分发器将每工作线程 stdout/stderr 写入 <board-root>/logs/<task_id>.log。日志可从 kanban 元数据审计:

  • task_runs 行携带 log_path、退出码(可用时)、摘要和元数据
  • task_events 行携带每个状态转换(promotedclaimedheartbeatcompletedblockedgave_upcrashedtimed_outreclaimedclaim_extended
  • kanban_show 返回两者,因此读取任务的审查者(或后续工作线程)无需仪表盘访问即可获得完整历史

仪表盘以摘要、元数据块和退出状态徽章渲染运行历史。CLI 用户可以运行 hermes kanban tail <task_id> 实时追踪,或 hermes kanban runs <task_id> 查看历史尝试列表。

现有通道形状

Hermes 配置通道(默认)

今天每个 kanban 工作线程采用的形状:分配者是一个配置名称,分发器生成 hermes -p <profile>,工作线程自动加载 kanban-worker 技能加上 KANBAN_GUIDANCE 系统提示块,并使用 kanban_* 工具终止运行。除了定义配置外无需额外设置。

当您为集群创建配置时,选择与您希望编排者路由到的角色匹配的名称。编排者(当存在时)通过 hermes profile list 发现您的配置名称——没有系统假设的固定名册(参见 kanban-orchestrator 技能了解编排者端的契约)。

编排者配置通道

配置通道的一个特化:编排者是一个 Hermes 配置,其工具集包含 kanban 但排除 terminal / file / code / web 用于实现。它的工作是将高级目标通过 kanban_create + kanban_link 分解为子任务并退后。编排者技能编码了抗诱惑规则。

添加外部 CLI 工作线程通道

将非 Hermes CLI 工具(Codex CLI、Claude Code CLI、OpenCode CLI、本地编码模型运行器等)作为 kanban 工作线程通道接入还不是一条铺好的路。分发器的生成函数是可插拔的(spawn_fndispatch_once 上的一个参数),插件可以为非 Hermes 分配者注册自己的 spawn_fn,但周围的集成工作——将 CLI 的退出码包装为 kanban_complete / kanban_block 调用、将 CLI 的工作空间/沙箱约定映射到分发器的 HERMES_KANBAN_WORKSPACE env、处理认证和每 CLI 策略——仍然是每集成的设计工作。

如果您正在考虑添加 CLI 通道,请开一个 issue,描述具体的 CLI 和您试图启用的工作流。上面的契约是任何此类通道必须满足的约束;实现形状(每 CLI 一个插件 vs. 由配置参数化的通用 CLI 运行器插件)是开放的。

此问题的历史 issue 是 #19931 和已关闭但未合并的 Codex 特定 PR #19924——它们描述了原始架构提案但未落地运行器。

分发器处理的故障模式

因此通道作者不必重新实现这些:

  • 过期的认领 TTL —— 认领后从未心跳/完成/阻塞的工作线程在 DEFAULT_CLAIM_TTL_SECONDS(默认 15 分钟)后被回收——但仅当工作线程进程实际已死亡时。一个活着的工作线程(慢模型在一个无工具的 LLM 调用中花费 20 分钟以上)获得认领延长而不是被杀死;只有死亡的 PID 被回收。
  • 工作线程崩溃 —— 主机本地 PID 已消失的工作线程由 detect_crashed_workers 检测并回收;任务增加 consecutive_failures,并可能在断路器跳闸时自动阻塞。
  • 运行级重试 —— 当任务被重试时(后阻塞、后崩溃、后回收),工作线程可以在终止工具上使用 expected_run_id 参数,在其自己的运行已被取代时快速失败。
  • 每任务最大运行时间 —— task.max_runtime_seconds 对每运行的挂钟时间进行硬上限,无论 PID 是否存活。捕获了活 PID 扩展本会让其继续运行的真正死锁工作线程。
  • 滞留任务检测 —— 分配者在 kanban.stranded_threshold_seconds(默认 30 分钟)内从未产生认领的就绪任务会在 hermes kanban diagnostics 中显示为 stranded_in_ready 警告。严重性在阈值的 2 倍时升级为错误,6 倍时为严重。在一个信号中捕获拼写错误的分配者、已删除的配置和关闭的外部工作线程池——身份无关,无需维护每工单板白名单。

相关