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_complete 的 created_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。如果报告为 blocked 或 archived,请立即停止 — 你不应该继续运行。
工作区可能存在残留 artifacts。 特别是 dir: 和 worktree 工作区可能包含之前运行留下的文件。阅读评论线程 — 它通常解释了为什么你要再次运行以及工作区当前的状态。
当有可用指导工具时,不要依赖 CLI。 kanban_* 工具适用于所有终端后端(Docker、Modal、SSH)。从你的终端工具中调用 hermes kanban <verb> 会在容器化后端中失败,因为那里未安装 CLI。如有疑问,请使用工具。
CLI 回退(用于脚本编写)
每个工具都有供人类操作员和脚本使用的等效 CLI 命令:
kanban_show↔hermes kanban show <id> --jsonkanban_complete↔hermes kanban complete <id> --summary "..." --metadata '{...}'kanban_block↔hermes kanban block <id> "reason"kanban_create↔hermes kanban create "title" --assignee <profile> [--parent <id>]- 等等。
在代理内部使用工具;CLI 是供终端前的人类使用的。