跳到主要内容

Kanban Worker

Hermes Kanban worker 的陷阱、示例和边缘情况。生命周期本身会作为 KANBAN_GUIDANCE(来自 agent/prompt_builder.py)自动注入到每个 worker 的系统提示中;当你想要了解特定场景的更详细信息时,可以加载此技能。

技能元数据

来源捆绑(默认安装)
路径skills/devops/kanban-worker
版本2.0.0
平台linux, macos, windows
标签kanban, multi-agent, collaboration, workflow, pitfalls
相关技能kanban-orchestrator

参考:完整 SKILL.md

信息

以下是 Hermes 在触发此技能时加载的完整技能定义。这是技能激活时代理看到的指令。

Kanban Worker — 陷阱与示例

你看到此技能是因为 Hermes Kanban 调度器使用 --skills kanban-worker 将你生成为 worker —— 它为每个被调度的 worker 自动加载。生命周期(6 个步骤:orient → work → heartbeat → block/complete)也存在于自动注入到你系统提示中的 KANBAN_GUIDANCE 块中。此技能提供更深入的细节:良好的交接形式、重试诊断、边缘情况。

工作区处理

你的工作区类型决定了你在 $HERMES_KANBAN_WORKSPACE 中应如何行为:

类型说明工作方式
scratch全新的临时目录,仅供你使用自由读写;任务归档时会被垃圾回收。
dir:<path>共享持久化目录其他运行将读取你写入的内容。将其视为长期状态。路径保证为绝对路径(内核会拒绝相对路径)。
worktree解析路径处的 Git worktree如果 .git 不存在,首先从主仓库运行 git worktree add <path> ${HERMES_KANBAN_BRANCH:-wt/$HERMES_KANBAN_TASK},然后 cd 进入并正常工作。在此提交工作。

租户隔离

如果设置了 $HERMES_TENANT,则任务属于租户命名空间。在读取或写入持久化内存时,使用租户前缀标记内存条目,以防止上下文在不同租户间泄露:

  • 好:business-a: Acme 是我们最大的客户
  • 坏(泄露):Acme 是我们最大的客户

良好的摘要 + 元数据形式

kanban_complete(summary=..., metadata=...) 交接是下游 worker 读取你所做工作的方式。有效的模式:

编码任务:

kanban_complete(
summary="shipped rate limiter — token bucket, keys on user_id with IP fallback, 14 tests pass",
metadata={
"changed_files": ["rate_limiter.py", "tests/test_rate_limiter.py"],
"tests_run": 14,
"tests_passed": 14,
"decisions": ["user_id primary, IP fallback for unauthenticated requests"],
},
)

需要人工审查的编码任务(review-required):

对于大多数更改代码的任务,直到人工审查者查看后,工作才算真正完成。使用 block 而非 complete,并将 reason 前缀设为 review-required: ,以便仪表板将该行显示为需要审查。首先将结构化元数据(更改的文件、测试计数、diff/PR URL)放入评论中,因为 kanban_block 仅携带人类可读的原因——评论是持久的注释渠道。审查者要么批准并运行 hermes kanban unblock <id>(这将重新生成你并附带评论线程以进行任何后续操作),要么通过另一条评论要求更改。

import json

kanban_comment(
body="review-required handoff:\n" + json.dumps({
"changed_files": ["rate_limiter.py", "tests/test_rate_limiter.py"],
"tests_run": 14,
"tests_passed": 14,
"diff_path": "/path/to/worktree", # or PR url if pushed
"decisions": ["user_id primary, IP fallback for unauthenticated requests"],
}, indent=2),
)
kanban_block(
reason="review-required: rate limiter shipped, 14/14 tests pass — needs eyes on the user_id/IP fallback choice before merging",
)

仅在任务真正终止时使用 kanban_complete —— 例如单行拼写错误修复、没有功能后果的文档更改,或者工件本身就是撰写的研究任务。

研究任务:

kanban_complete(
summary="3 competing libraries reviewed; vLLM wins on throughput, SGLang on latency, Tensorrt-LLM on memory efficiency",
metadata={
"sources_read": 12,
"recommendation": "vLLM",
"benchmarks": {"vllm": 1.0, "sglang": 0.87, "trtllm": 0.72},
},
)

审查任务:

kanban_complete(
summary="reviewed PR #123; 2 blocking issues found (SQL injection in /search, missing CSRF on /settings)",
metadata={
"pr_number": 123,
"findings": [
{"severity": "critical", "file": "api/search.py", "line": 42, "issue": "raw SQL concat"},
{"severity": "high", "file": "api/settings.py", "issue": "missing CSRF middleware"},
],
"approved": False,
},
)

塑造 metadata 的形式,以便下游解析器(审查者、聚合器、调度器)无需重读你的散文即可使用它。

声明你实际创建的卡片

如果你的运行产生了新的 kanban 任务(通过 kanban_create),请在 kanban_completecreated_cards 中传递这些 id。内核会验证每个 id 是否存在且由你的配置文件创建;任何虚假 id 都会导致完成失败,并列出错误信息,被拒绝的尝试会永久记录在任务的事件日志中。仅列出你从成功的 kanban_create 返回值中捕获的 id —— 切勿从散文中虚构 id,切勿粘贴 earlier runs 的 id,切勿声明其他 worker 创建的卡片。

# GOOD — capture return values, then claim them.
c1 = kanban_create(title="remediate SQL injection", assignee="security-worker")
c2 = kanban_create(title="fix CSRF middleware", assignee="web-worker")

kanban_complete(
summary="Review done; spawned remediations for both findings.",
metadata={"pr_number": 123, "approved": False},
created_cards=[c1["task_id"], c2["task_id"]],
)
# BAD — claiming ids you don't have captured return values for.
kanban_complete(
summary="Created remediation cards t_a1b2c3d4, t_deadbeef", # hallucinated
created_cards=["t_a1b2c3d4", "t_deadbeef"], # → gate rejects
)

如果 kanban_create 调用失败(异常、tool_error),则卡片未创建 —— 不要为其包含虚假 id。重试创建,或省略该 id 并在摘要中提及失败。散文扫描过程还会捕获你自由格式摘要中无法解析的 t_<hex> 引用;这些不会阻止完成,但会在仪表板的任务上显示为建议性警告。

能快速得到回复的阻塞原因

坏:"stuck" —— 人类没有上下文。

好:用一句话命名你需要的具体决策。将更长的上下文留作评论。

kanban_comment(
task_id=os.environ["HERMES_KANBAN_TASK"],
body="Full context: I have user IPs from Cloudflare headers but some users are behind NATs with thousands of peers. Keying on IP alone causes false positives.",
)
kanban_block(reason="Rate limit key choice: IP (simple, NAT-unsafe) or user_id (requires auth, skips anonymous endpoints)?")

阻塞消息是出现在仪表板/网关通知器中的内容。评论是人类打开任务时阅读的更深层次上下文。

值得发送的心跳

良好的心跳名称应体现进度:"epoch 12/50, loss 0.31""scanned 1.2M/2.4M rows""uploaded 47/120 videos"

不良的心跳:"still working"、空备注、亚秒级间隔。最多每隔几分钟一次;对于耗时约 2 分钟以下的任务,完全跳过心跳。

重试场景

如果你打开任务时,kanban_show 返回 runs: [...] 且其中包含一个或多个已关闭的运行记录,则你处于重试状态。先前运行的 outcome / summary / error 会告诉你哪里出了问题。不要重复相同的路径。典型的重试诊断如下:

  • outcome: "timed_out" — 之前的尝试达到了 max_runtime_seconds。你可能需要将工作分块或缩短执行时间。
  • outcome: "crashed" — 内存溢出(OOM)或段错误(segfault)。减少内存占用。
  • outcome: "spawn_failed" + error: "..." — 通常是配置文件问题(缺少凭据、错误的 PATH)。通过 kanban_block 向人类求助,而不是盲目重试。
  • outcome: "reclaimed" + summary: "task archived..." — 操作员在之前的运行期间归档了该任务;你可能根本不应该运行,请仔细检查状态。
  • outcome: "blocked" — 之前的尝试被阻塞;解除阻塞的评论此时应该已出现在线程中。

通知路由

你可以通过在 ~/.hermes/config.yaml 中添加 notification_sources 来配置网关,以接收跨配置文件的 Kanban 任务通知。

  • notification_sources: ['*'] 接受来自所有配置文件的订阅。
  • notification_sources: ['default', 'zilor-ppt']"default,zilor-ppt" 将订阅限制为指定的配置文件。
  • 省略该键则保持默认行为(配置文件隔离)。

禁止事项

  • 不要调用 delegate_task 作为 kanban_create 的替代方案。delegate_task 用于 你的 运行内部的短期推理子任务;kanban_create 用于跨越单个 API 循环生命周期的跨代理交接。
  • 不要调用 clarify 向人类提问。你是无头模式运行 — 没有实时用户来回答。调用将超时(默认约 120 秒),任务将静默地停留在 running 状态,没有任何需要输入的信号。请改用 kanban_comment(提供上下文)+ kanban_block(reason=...)(表示需要决策)— 任务在看板上显示为被阻塞,操作员会看到它,并在评论中用答案解除阻塞,然后你带着线程内容重新生成。
  • 除非任务正文明确说明,否则不要修改 $HERMES_KANBAN_WORKSPACE 之外的文件。
  • 不要创建分配给你自己的后续任务 — 应分配给合适的专家。
  • 不要完成你实际上并未完成的任务。改为将其阻塞。

常见陷阱

任务状态可能在调度与你启动之间发生变化。 在调度器认领任务到你的进程实际启动之间,任务可能已被阻塞、重新分配或归档。务必首先调用 kanban_show。如果报告为 blockedarchived,请立即停止 — 你不应该继续运行。

工作区可能存在残留 artifacts。 特别是 dir:worktree 工作区可能包含之前运行留下的文件。阅读评论线程 — 它通常解释了为什么你要再次运行以及工作区当前的状态。

当有可用指导工具时,不要依赖 CLI。 kanban_* 工具适用于所有终端后端(Docker、Modal、SSH)。从你的终端工具中调用 hermes kanban <verb> 会在容器化后端中失败,因为那里未安装 CLI。如有疑问,请使用工具。

CLI 回退(用于脚本编写)

每个工具都有供人类操作员和脚本使用的等效 CLI 命令:

  • kanban_showhermes kanban show <id> --json
  • kanban_completehermes kanban complete <id> --summary "..." --metadata '{...}'
  • kanban_blockhermes kanban block <id> "reason"
  • kanban_createhermes kanban create "title" --assignee <profile> [--parent <id>]
  • 等等。

在代理内部使用工具;CLI 是供终端前的人类使用的。