Minimal multi-agent kanban board
Project description
kanban
当前版本:v0.1.4-rc1。完整变更见 CHANGELOG.md。
一个最小可跑的多 Agent 看板,已经实现:
- 卡片与列状态建模、依赖与 WIP 规则
- 编排器按看板规则选择下一张卡(单一写入权威)
- 按角色路由的多 Agent 执行器(planner / worker / reviewer / verifier)
- 本地 dispatcher daemon + 单写锁 + 优雅退出
- 结构化执行事件与原始 transcript 留痕
kanban 是 agentao 项目的衍生项目,复用了 agentao 的多 Agent 定义方式
(Markdown + YAML frontmatter),并在其基础上补上看板状态流转、调度与持久化。
执行器默认是 MockAgentaoExecutor(离线状态机,适合 CI 与本地调试)。加
--executor agentao 才会真正调用四个角色的 sub-agent;daemon 启动时会在
INFO 日志里打印当前使用哪个 executor。
结构
kanban/
models.py # 卡片、状态、角色、AgentResult
store.py # BoardStore Protocol + InMemoryBoardStore
store_markdown.py # MarkdownBoardStore(TOML front-matter + events.log + raw transcripts)
orchestrator.py # 调度与状态流转(唯一状态写入者)
agents.py # ROLE_AGENTS 映射 + 定义文件加载器
daemon.py # 本地 dispatcher + .daemon.lock
executors/
base.py # 执行器接口
mock_agentao.py # 离线状态机
agentao_multi.py # 按角色路由的 agentao 多 Agent 执行器
cli.py # kanban CLI(含 daemon 子命令)
demo.py # 最小演示
defaults/ # 打包的 sub-agent 定义与默认 agent_profiles.yaml
docs/
multi-agent-implementation-plan.md
main.py # demo 入口
安装
按你想跑哪个 executor 挑一条路径。不要混装:ACP 路径依赖外部 CLI 和 API key,而纯 mock 路径什么都不需要。
先决条件(所有模式共用)
- Python ≥ 3.12
uv(包管理)- Git clone 后在仓库根目录
uv sync一次
git clone https://github.com/jin-bo/agentao-kanban.git
cd agentao-kanban
uv sync
agentao已发布到 PyPI(≥ 0.2.10),uv sync会直接从 PyPI 拉, 不再需要同级../agentao源码。只有同时在改 agentao 的开发者,才需要 在仓库根放一份本地uv.toml(已.gitignore)override:[sources] agentao = { path = "../agentao", editable = true }
路径 A:纯 mock 模式(默认,推荐首次上手)
MockAgentaoExecutor 是离线状态机,不调用任何 LLM,也不读 .agentao/。
装完 uv sync 即可跑:
uv run python main.py # 内存态演示,最短闭环
uv run kanban card add --title T --goal G --priority HIGH
uv run kanban list
uv run kanban run # 跑到 idle
uv run kanban daemon # 前台 dispatcher,Ctrl-C 退出
uv run kanban daemon --once --poll-interval 0.2 # 单轮调试
uv run kanban daemon --detach # 后台,日志写 <board>/daemon.log
到这一步就完了,不要继续装下面的东西。
路径 B:agentao sub-agent 模式
用 --executor agentao 调四个本地 sub-agent(planner / worker / reviewer /
verifier)。额外要求:
-
agentao包可用。uv sync已经从 PyPI 装好(≥ 0.2.10);只有同时在改 agentao 源码的开发者才需要按先决条件里的说明配uv.toml走本地 editable。 -
sub-agent 定义:默认从
kanban/defaults/*.md读,仓库已打包。若要本地 改 prompt:mkdir -p .agentao/agents cp kanban/defaults/*.md .agentao/agents/
.agentao/已.gitignore,不会被提交。 -
跑:
uv run kanban --executor agentao run uv run kanban --executor agentao daemon
路径 C:multi-backend + ACP 远端模式
--executor multi-backend 走 profile 路由,默认每个角色仍落到 subagent
backend(等同路径 B)。只有把卡上 agent_profile 手动 pin 到 gemini-*
profile,或让 router 选中,才会真正调 ACP 后端。此时额外要求:
-
准备 ACP 服务器配置。仓库的
docs/acp.sample.json是样板,拷到运行 目录:mkdir -p .agentao cp docs/acp.sample.json .agentao/acp.json
默认样板里的
gemini-worker/gemini-reviewer都是npx @google/gemini-cli@latest --acp。 -
准备外部 CLI 与凭据:
- Node.js +
npx可用(让npx @google/gemini-cli@latest可跑)。 - 导出
GEMINI_API_KEY(acp.json里的env用$GEMINI_API_KEY占位符,进程启动时展开)。
export GEMINI_API_KEY=... npx @google/gemini-cli@latest --version # 自检
- Node.js +
-
(可选)调整 profile 路由。默认配置
kanban/defaults/agent_profiles.yaml已经声明了gemini-worker/gemini-reviewerprofile 但不作为默认; 要按项目改,复制一份本地覆盖:mkdir -p .kanban cp docs/agent_profiles.sample.yaml .kanban/agent_profiles.yaml
-
跑:
uv run kanban --executor multi-backend daemon
若一张卡被路由到 ACP profile 但
.agentao/acp.json缺失 / 外部命令 起不来,该卡会以FailureCategory=infrastructure进入重试/BLOCKED; 其它仍走 subagent 的卡不受影响。
自检
装完推荐跑一次:
uv run pytest -q # 单元+集成测试
uv run kanban doctor # 板健康体检
每卡 Worktree 隔离(默认 auto)
当 board 位于 Git 仓库内时,worker 首次 claim 一张卡会自动创建独立
worktree(workspace/worktrees/<card-id>)和分支(kanban/<card-id>)。
worker / reviewer / verifier 都在这个 worktree 中执行,彼此不干扰。卡
到 DONE 或 BLOCKED 时自动 detach(目录释放、分支保留),分支等你合 PR
或手动 unblock。
--worktree 是 tri-state:
uv run kanban run # auto(git repo 内默认启用)
uv run kanban --worktree run # 硬要求 git repo,否则 SystemExit
uv run kanban --no-worktree run # 显式关闭,行为回到 v0.1.3
非 git 仓库下默认会在 stderr 打印一行 warning 后自动降级关闭,不影响 mock / 临时目录场景。
子命令:
uv run kanban worktree list # 列出活跃 worktree
uv run kanban worktree diff <card-id> # 基于持久化的 fork-point 出 diff
uv run kanban worktree prune # 清 merged/过期分支
uv run kanban worktree prune --retention-days 14
完整设计见 docs/worktree-isolation-design.md。
作为 MCP Server 暴露(kanban-mcp)
把看板当成 Claude Code / Codex / 任意 MCP client 的"调度中心":
# Claude Code:在仓库根注册一个 stdio MCP server,作用域是当前项目
claude mcp add kanban -- uv run --directory $(pwd) kanban-mcp \
--board workspace/board
# Codex 或其它 client 同理,改前缀即可:
# command = "uv", args = ["run", "--directory", "<repo>", "kanban-mcp", "--board", "workspace/board"]
启动参数:
| 参数 | 说明 |
|---|---|
--board DIR |
板路径,默认 $KANBAN_BOARD 或 workspace/board |
--executor {mock,agentao,multi-backend} |
tick/run 用哪个执行器,默认 mock |
--force |
跳过 daemon-lock 守卫(仅在 daemon 异常残留锁时使用) |
暴露的 tools(均直接调 BoardStore,不走 subprocess):
| Tool | 等价 CLI |
|---|---|
card_add(title, goal, priority?, acceptance?, depends?) |
kanban card add |
card_list(status?) |
kanban list |
card_show(card_id) |
kanban show |
card_move(card_id, status) |
kanban move |
card_block(card_id, reason) |
kanban block |
card_unblock(card_id, to?) |
kanban unblock |
events_tail(limit?, card_id?, role?, execution_only?) |
kanban events |
tick() |
kanban tick |
run(max_steps?) |
kanban run |
Resources(供 client 通过资源接口缓存读取):
kanban://board/snapshot— 当前{status: [titles]}快照kanban://card/{card_id}— 单卡完整 JSONkanban://events/recent— 最近 50 条事件 JSON 数组
写类 tool 在 daemon 持有 .daemon.lock 时会拒绝,文案与 CLI --force
路径一致;读类 tool / resource 不受守卫影响。
CLI Guide
README 保留概览和关键命令,完整的 CLI 使用指南放在 docs/kanban-cli-guide.md。
如果你想快速掌握:
- 建卡、补 context、维护 acceptance criteria
- daemon 运行时如何安全操作
- 多 worker 模式下如何看 claims / workers / events
- blocked、超时、stale claim 时怎么恢复
直接看这份指南。
运维命令(v0.1.1)
所有写命令都遵守 .daemon.lock;加 --force 才能在守护进程运行期写入
(仅用于应急恢复)。CLI 写入的 history 条目统一带 [system] 前缀,与
自动状态迁移保持一致。
编辑卡片
uv run kanban card edit <id> --title "新标题"
uv run kanban card edit <id> --goal "新目标" --priority HIGH
uv run kanban card edit <id> --set-status blocked --blocked-reason "缺数据"
uv run kanban card edit <id> --clear-blocked-reason
--set-status 是操作员覆盖,仅允许 inbox/ready/blocked/done(有 owner
期望的 doing/review/verify 不可直接设,用 requeue)。设为 blocked
时必须同时提供 --blocked-reason。
管理 context_refs
uv run kanban card context list <id>
uv run kanban card context add <id> --path docs/api.md --kind required --note "API 合约"
uv run kanban card context rm <id> --path docs/api.md
--kind 只接受 required 或 optional。同一 path 再次 add 走
upsert。
调整 acceptance criteria
uv run kanban card acceptance list <id>
uv run kanban card acceptance add <id> --item "生成 workspace/reports/summary.md"
uv run kanban card acceptance rm <id> --index 2 # 1-based
uv run kanban card acceptance clear <id>
从 BLOCKED 恢复
uv run kanban requeue <id> # 默认 → inbox,清空 blocked_reason
uv run kanban requeue <id> --to ready
uv run kanban requeue <id> --to ready --note "已补充数据集"
查看事件与 transcript
uv run kanban events # 最近 50 条(跨卡)
uv run kanban events <id> # 过滤到一张卡
uv run kanban events <id> --role worker # 只看执行事件(排除系统事件)
uv run kanban events --limit 20 --json # 机读 JSONL
uv run kanban traces <id> # 列出保留的原始 transcript
uv run kanban traces <id> --role worker
uv run kanban traces <id> --latest
--role 过滤期间,系统事件(状态迁移、手工编辑等)不会出现——要同时看
就不要加 --role。
健康体检
uv run kanban doctor # 人类可读报表
uv run kanban doctor --json # 机读报表
退出码:0 = 健康,1 = 只有 warning,2 = 至少一条 error。
JSON 输出字段冻结:checks[].{severity, rule, card_id, message}。当前
规则:
dep-missing(error) —depends_on指向不存在的卡blocked-no-reason(warning) — 卡在blocked但blocked_reason为空(防御性)done-no-verification(warning) —done卡outputs.verification为空stage-missing-upstream(error) —review/verify卡缺上游产出invalid-context-kind(warning) —context_refs[].kind不在{required, optional}unparseable-card(error) — 卡文件加载时被跳过
CLI 默认把状态持久化到 workspace/board/(每张卡一个 .md 文件,事件写
JSONL 到 events.log)。用 --board DIR 可切换目录。daemon 运行时持有
workspace/board/.daemon.lock;其他写命令会被拒绝,加 --force 才强制
(仅用于应急恢复)。陈旧锁(pid 已死)启动时自动清理。
Workspace 目录约定
workspace/ 已加入 .gitignore,是 kanban 运行态与 Agent 工作文件的统一家:
workspace/
board/ # 看板权威状态,orchestrator 独占写入,Agent 只读
raw/<card>/<role>-<ts>.md # kanban 管理的原始 transcript,保留最近 5 份
scratch/<card>/ # Worker 的逐卡草稿目录
reports/ # Worker 输出的人类可读交付物(Markdown)
data/ # 长期数据集
docs/ # 产出的稳定文档
scripts/ # 值得留存的脚本
Downloads/ # 外部资源
Agent 约定:
workspace/board/与workspace/raw/对所有角色只读。- Worker 草稿放
workspace/scratch/<card-id>/,正式交付物按reports/、data/、scripts/等目录分类;最终output里写明交付路径。 - Reviewer 全程只读;Verifier 只允许在
workspace/scratch/<card-id>/verify/建临时脚手架,并在返回前清理。 - Planner 写 acceptance criteria 时尽量点名
workspace/下的具体路径, Verifier 才能机械化地验证。
Agent 定义与 .agentao
仓库跟踪四份 sub-agent 定义作为模板源(Markdown + YAML frontmatter):
kanban/defaults/kanban-planner.mdkanban/defaults/kanban-worker.mdkanban/defaults/kanban-reviewer.mdkanban/defaults/kanban-verifier.md
frontmatter 里的 version: 字段会被执行器读出,写入 events.log 每一条
执行事件,便于回溯是哪个版本的 prompt 产出了哪次结果。
.agentao/ 被视为本地运行目录(缓存、数据库等),整个目录已 .gitignore
不提交。运行时加载规则:
- 若
<cwd>/.agentao/agents/*.md存在,优先使用(供开发者本地覆盖) - 否则回退到仓库内的
kanban/defaults/*.md
要按 agentao 的项目目录习惯管理提示词,可先复制一份本地覆盖:
mkdir -p .agentao/agents
cp kanban/defaults/*.md .agentao/agents/
v0.1.2 并发内核
v0.1.2 把单进程串行 dispatcher 拆成 scheduler / worker 两种角色,允许多
worker 在同一 board 上并发执行不同卡,同时保留「只有调度器写状态」这条
核心不变式。完整设计:docs/v0.1.2-concurrency-plan.md。
Daemon 角色
uv run kanban daemon # = --role all(scheduler + 1 worker 同进程)
uv run kanban daemon --role scheduler --max-claims 4
uv run kanban daemon --role worker --worker-id worker-1
uv run kanban daemon --role legacy-serial # v0.1.1 的串行路径,兼容用
scheduler持.daemon.lock,负责建 claim、commit 结果、回收过期 lease; 全板只能有一个。worker不持板锁,可开多个进程/机器;通过runtime/claims/<card>.json的原子O_EXCLsentinel CAS 互斥地抢 claim,执行后只写runtime/results/<card>-<attempt>.jsonenvelope,不再直接改卡状态。all是本地便利模式(同进程里跑一个 scheduler + 一个 worker),真并行 请跑独立进程。
运行时布局
workspace/board/
cards/ # 看板权威(不变)
events.log # 追加 runtime 生命周期事件
runtime/
claims/<card>.json # 单个 card 同时最多一条活 claim
results/<card>-<attempt>.json # worker 提交的 envelope,等调度器 commit
results/orphans/ # claim_id 不匹配的孤儿 envelope(保留审计)
workers/<worker-id>.json # worker 心跳存在文件
重试矩阵
失败按 FailureCategory 分类(worker / scheduler 在 envelope 上打标),
命中矩阵就重试,耗尽预算就 BLOCKED(原因带 [category=... attempts=...]):
| 类别 | 默认预算 | 语义 |
|---|---|---|
infrastructure |
2 | executor 抛异常 / LLM 5xx |
lease_expiry |
1 | scheduler 检到租约过期 |
timeout |
1 | 同上(lease 即 timeout) |
malformed |
0 | 响应无法解析,立即 BLOCKED |
functional |
0 | reviewer/verifier 业务驳回,立即 BLOCKED |
重试时新建 claim(attempt+1 + retry_of_claim_id 指回上次),
execution.retried 事件带整条链路。改默认:传
KanbanOrchestrator(retry_policy=RetryPolicy(infrastructure=0))。
运行时观测 CLI
uv run kanban claims # 所有活 claim: lease 剩余 / 心跳年龄 / 归属 worker
uv run kanban claims <card_id> # 单卡过滤
uv run kanban claims --json # 机读
uv run kanban workers # 活跃 worker: pid / uptime / 最近心跳
uv run kanban recover --stale # 一次性跑过期 claim 恢复,输出每卡处置(retried / blocked)
uv run kanban events <id> # 事件行按 event_type 分组打标([execution.retried] 等)
uv run kanban events <id> --json # 带 claim_id / worker_id / failure_category / retry_of_claim_id 等字段
claims 里 *EXPIRED* 表示租约已过但 scheduler 还没跑到恢复步(下一次
daemon --role scheduler 或 recover --stale 就会处理)。
下一步 (Phase 2)
- ACP 远端 worker、跨机部署(v0.1.3 已落地,见下节)
- 持久队列(替代
runtime/文件集),事件流化 - 观测面板、重试链时间线、资源占用曲线
v0.1.3 Multi-backend 路由 & ACP
v0.1.3 在 v0.1.2 的 scheduler/worker 内核之上加了按角色按卡选 backend
的路由层,并把 ACP 远端 worker 落地为一等 backend。
--executor multi-backend:按agent_profiles.yaml给每个角色挑 profile, profile 绑定subagent或acpbackend。默认配置见kanban/defaults/agent_profiles.yaml,本地覆盖放<cwd>/.kanban/agent_profiles.yaml。- ACP backend:外部 CLI (如
npx @google/gemini-cli@latest --acp) 通过.agentao/acp.json声明;样板见docs/acp.sample.json。API key 从环境 变量注入,配置文件只放命令与占位符。 - Router agent (
kanban-router):可按卡动态在候选 profile 间挑选,不会 覆盖卡 pin 或 planner 推荐;KANBAN_ROUTER=off全局关闭。 - 所有 profile/ACP/router 路径都从
--board推导的 project root 读取, 不会跟随 shell cwd。
安装步骤(含 .agentao/acp.json、GEMINI_API_KEY 等前置条件)见本 README
开头的「路径 C」。设计细节:docs/agent-router-design.md、
docs/agent-profile-acp-design.md。
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file agentao_kanban-0.1.4.tar.gz.
File metadata
- Download URL: agentao_kanban-0.1.4.tar.gz
- Upload date:
- Size: 103.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f1a4b88462b23f4f75f88d9afa49bee3e1aacbc6187e520296b2eff271806c04
|
|
| MD5 |
15001e7d5350186e633828be12bdccbf
|
|
| BLAKE2b-256 |
0c4d84a1b23ec52cf6d5d72f6c44812bcca0f7fa98b1568484c7d1a594b38b3c
|
Provenance
The following attestation bundles were made for agentao_kanban-0.1.4.tar.gz:
Publisher:
publish-pypi.yml on jin-bo/agentao-kanban
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
agentao_kanban-0.1.4.tar.gz -
Subject digest:
f1a4b88462b23f4f75f88d9afa49bee3e1aacbc6187e520296b2eff271806c04 - Sigstore transparency entry: 1336167320
- Sigstore integration time:
-
Permalink:
jin-bo/agentao-kanban@32ed8e9101cea5038d373ff9f794960717d4e923 -
Branch / Tag:
refs/tags/v0.1.4 - Owner: https://github.com/jin-bo
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@32ed8e9101cea5038d373ff9f794960717d4e923 -
Trigger Event:
push
-
Statement type:
File details
Details for the file agentao_kanban-0.1.4-py3-none-any.whl.
File metadata
- Download URL: agentao_kanban-0.1.4-py3-none-any.whl
- Upload date:
- Size: 125.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e5098e8820eaf2d2407a586cc08b9eb32a7631a5b5dca82e8df8cd314b1c19b7
|
|
| MD5 |
6be6c0b18023aeab36441bb447110fa5
|
|
| BLAKE2b-256 |
c862d988deb61318c9c8061f674e2df185b8e213e8ebe10c0bb78a3eaf082b92
|
Provenance
The following attestation bundles were made for agentao_kanban-0.1.4-py3-none-any.whl:
Publisher:
publish-pypi.yml on jin-bo/agentao-kanban
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
agentao_kanban-0.1.4-py3-none-any.whl -
Subject digest:
e5098e8820eaf2d2407a586cc08b9eb32a7631a5b5dca82e8df8cd314b1c19b7 - Sigstore transparency entry: 1336167421
- Sigstore integration time:
-
Permalink:
jin-bo/agentao-kanban@32ed8e9101cea5038d373ff9f794960717d4e923 -
Branch / Tag:
refs/tags/v0.1.4 - Owner: https://github.com/jin-bo
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@32ed8e9101cea5038d373ff9f794960717d4e923 -
Trigger Event:
push
-
Statement type: