Beads 中的 ready 工作流:用bd ready查找无阻塞任务并原子认领
【免费下载链接】beadsBeads - A memory upgrade for your coding agent项目地址: https://gitcode.com/GitHub_Trending/beads1/beads
导读
本文围绕 Beads 的 skill 文档 plugins/beads/skills/beads/commands/ready.md 展开,讲解编码 Agent 如何通过 beads MCP 服务器的ready工具,从依赖图中找出真正可以动手(无阻塞依赖)的任务,并将其清晰地呈现给用户;当用户选定任务后,如何通过claim工具原子地开始工作。读完本文,你将掌握bd ready的 blocker-aware 语义、输出格式、常用过滤参数,以及bd ready --claim的原子认领原理,并理解与bd blocked、bd create的配合方式。
一、ready 的核心语义:什么是"可以动手"的任务
ready工具的作用是找出"没有阻塞依赖、当前就可以开始"的任务。这里的"ready"不是简单的状态判断,而是blocker-aware(感知阻塞者)的语义:一个 issue 即使处于 open 状态,只要它存在一条仍为 open 的blocks类型依赖(即依赖链上还有未关闭的阻塞者),它就不算 ready。
这一点在 Beads 源码中有明确印证。internal/workapi/ready.go中的BuildReadyFilter是bd ready语义的唯一权威定义,它强制:
- 只包含 open 状态的 issue(
Status: types.StatusOpen),不包含 in_progress——这与bd list --ready展示的是同一个集合; - 默认排除in_progress、blocked、deferred 和 hooked 的 issue;
- 通过
GetReadyWork这条 blocker-aware 查询来找出真正可认领的工作。
issueops/readycounter.go中对 ReadyCounter 角色的注释也点明了 ready 谓词的本质:
"The ready predicate is BLOCKER-AWARE: it reads the dependency graph and the wisp tier, and no CountRequest can describe it."
也就是说,"有多少 ready 工作"这个问题无法用对单张表的谓词计数来回答,必须读取依赖图和 wisp 层级——这正是ready与普通列表/计数命令的本质区别。
二、Agent 使用 ready 的标准流程
根据 ready.md,Agent 的标准动作序列是:
- 调用
ready工具,获取当前所有无阻塞依赖的任务; - 以清晰格式呈现给用户,每条任务至少包含四项信息:
- Issue ID(任务 ID)
- Title(标题)
- Priority(优先级)
- Issue type(任务类型)
- 询问用户选择:如果有 ready 任务,请用户指定要处理哪一个;
- 用户选定后调用
claim工具原子地开始工作; - 没有 ready 任务时:建议检查
blocked任务(看看卡在哪里、能否推动解决),或者用create工具新建一条 issue。
这套流程把"找活 → 呈现 → 确认 → 认领 → 兜底"串成一条完整的 agent 工作链,让编码 Agent 在每次会话开始或上下文恢复后,都能迅速定位自己该做什么。
三、呈现 ready 任务的关键字段
Agent 调用ready后拿到的结果中,每个任务都带有以下字段,呈现给用户时应当完整展示:
| 字段 | 含义 | 说明 |
|---|---|---|
| Issue ID | 任务 ID | 用于后续bd show <id>取详情、bd update <id> --claim认领 |
| Title | 标题 | 任务的一句话描述 |
| Priority | 优先级 | P0–P4,仅作为标签/排序依据,不是状态图标 |
| Issue type | 任务类型 | task、bug、feature、epic、decision、merge-request 等 |
从 cmd/bd/ready.go 的displayReadyList可以看到,CLI 在 pretty 模式下每行输出为[优先级] [类型] ID: 标题,并附上 Estimate(预估分钟)、Assignee(负责人)等附加信息;plain 模式则输出编号列表。Agent 面向用户呈现时,应保证 ID、Title、Priority、Issue type 四项齐全,便于用户做出选择。
四、blocker-aware 查询:ready 与 blocked 的关系
ready与blocked是一对互补视图。根据 blocked.md:
Blocked issues have one or more dependencies with type "blocks" that are still open. Once all blocking dependencies are closed, the issue becomes ready and will appear in
bd ready.
即:一条 issue 只要有任意一条blocks类型的依赖仍处于 open,它就是 blocked;当所有阻塞依赖都被关闭后,它自动变为 ready,出现在bd ready的结果中。
在 cmd/bd/ready.go 中,两条命令共用同一套 label 过滤逻辑(blockedFilterFromFlags),保证两侧视图对--label、--label-any、--exclude-label的解释完全一致,不会因为命令不同而漂移。
测试 cmd/bd/ready_test.go 中有专门用例验证这一语义:test-still-blocked同时依赖一个已关闭的阻塞者(test-closed-blocker-1)和一个仍 open 的阻塞者(test-open-blocker),因此依然 blocked;而test-ready-via-closed-blockers的全部阻塞依赖都已关闭,于是进入 ready 集合。这直观地说明:只要还有一条 open 的阻塞依赖,任务就保持 blocked。
五、bd ready 命令行全览:过滤与排序参数
虽然 skill 文档面向 MCP 工具调用,但 MCP 的ready工具与 CLI 的bd ready共享同一套过滤器构建逻辑(workapi.BuildReadyFilter)。CLI 支持的主要参数如下(定义见 cmd/bd/ready.go):
| 参数 | 别名 | 默认值 | 说明 |
|---|---|---|---|
--limit | -n | 100 | 最多显示条数,0 表示不限(workapi.DefaultReadyLimit) |
--offset | 0 | 跳过前 N 条(仅 proxied-server 模式支持) | |
--priority | -p | 0 | 精确按优先级过滤 |
--assignee | -a | 按负责人过滤 | |
--unassigned | -u | false | 只显示未分配的任务 |
--sort | -s | priority | 排序策略:priority(默认)、hybrid、oldest |
--label | -l | 标签过滤(AND:必须全部包含),可搭配--label-any | |
--label-any | 标签过滤(OR:至少包含一个) | ||
--exclude-label | 排除含任意这些标签的 issue | ||
--label-pattern | 标签 glob 过滤,如tech-* | ||
--label-regex | 标签正则过滤,如tech-(debt\|legacy) | ||
--type | -t | 按类型过滤(task/bug/feature/epic/decision/merge-request,别名 mr/feat/mol/dec/adr) | |
--mol | 只显示指定 molecule 内的步骤 | ||
--parent | 过滤某 bead/epic 的后代 | ||
--mol-type | 按 molecule 类型过滤:swarm、patrol、work | ||
--pretty | true | 树形展示(状态/优先级符号) | |
--plain | false | 纯编号列表展示 | |
--include-deferred | false | 包含未来 defer_until 的 issue | |
--include-ephemeral | false | 包含 ephemeral(wisp)记录 | |
--gated | false | 找出可 gate-resume 分发的 molecule | |
--exclude-type | 排除指定类型(逗号分隔或重复使用) | ||
--explain | false | 展示依赖感知的 ready/blocked 原因分析 | |
--claim | false | 原子认领第一个匹配过滤条件的 ready issue | |
--brief | false | 省略大字段(描述/设计/验收标准/笔记/payload/waiters),需--json | |
--metadata-field | 元数据等值过滤(key=value,可重复) | ||
--has-metadata-key | 过滤具有该元数据 key 的 issue | ||
--json | 结构化 JSON 输出(全局 flag) |
其中两个组合限制值得注意:
--claim不能与--assignee、--gated、--mol、--explain、--brief、--offset组合(冲突检查见 cmd/bd/ready_input.go 的gatherReadyInput与briefModeConflict);--brief需要--json,且不能与--claim、--gated、--mol、--explain组合。
排序策略说明
--sort支持三种策略,均作用于 ready 集合:priority(按优先级排序,为默认值)、hybrid、oldest(按创建时间最旧优先)。若传入非法值,BuildReadyFilter会返回ErrValidation包装的错误,提示合法取值为hybrid, priority, oldest(见 internal/workapi/ready.go)。
六、bd ready --claim:原子认领的原理
bd ready --claim是 ready 工作流的关键动作,它把"选择 → 认领 → 水合(hydrate)"三步放进同一个事务:
"Selection, the compare-and-set and the hydration share ONE transaction, so the row cannot move between being chosen and being reported."
—— issueops/readyclaimer.go
也就是说,认领时不会出现"选中的任务在报告前被别的 Agent 抢走"的竞态。其底层接口是ReadyClaimer.ClaimNext,一次只认领一条,且:
- 认领的候选集合与
bd ready列表展示的集合完全一致(共享ReadyRequest类型),保证"列表展示过的任务才可能被认领"; - 认领成功后,赢得的那一行会在事务内完成水合(关系数量等),返回的
IssueWithCounts描述的是认领提交那一刻的真实状态; - 没有可认领任务时返回
nil,而不是错误——空 ready 队列是排空后的稳态,轮询 Agent 无需通过解析错误来发现"没有活干"; - 认领不会记录历史条目(当没有可认领项时),而认领成功的行会获得恰好一个 lease(租约),这是心跳续期、租约过期回收机制能够恢复任务的句柄;
- ephemeral(wisp)行默认不在认领范围内,除非请求显式设置
IncludeEphemeral;认领 ephemeral 行不会授予 lease,也不会写历史,因此将 ephemeral 工作交给无人监督的 Agent 时,回收责任需要调用方自己承担。
CLI 层面对应实现在 cmd/bd/ready.go:--claim走activeStore.ReadyClaimer(),认领成功打印✓ Claimed issue: <id>: <title>;空结果时输出No ready work to claim。同时--claim是写操作,在嵌入模式下会触发自动提交(dolt autocommit),并设置SetLastTouchedID供后续命令追踪。
ready 集合的规模统计:ReadyCounter
当bd ready --json返回的页面恰好满页时,CLI 会通过ReadyCounter.CountReady再跑一次计数,回答"总共还有多少 ready 工作"(即Showing X of N中的 N)。ReadyCounter与Reader、ReadyClaimer是三个独立的角色接口(见 issueops/readycounter.go),它的契约承诺:
CountReady(r).Total == len(Reader.Ready(r with Limit=0).Items)
即计数与列表是同一个谓词的同一组答案。因此计数请求拒绝携带Limit/Offset——基数没有"页"的概念,带 Limit 会变成"前 N 个中有多少",带 Offset 则会悄悄从集合大小里扣掉跳过的行(见 internal/workapi/ready.go 的BuildReadyCountFilter)。
七、没有 ready 任务时怎么办:blocked 与 create 兜底
按 skill 文档,当 ready 列表为空时,Agent 应当引导用户走两条兜底路径:
1. 检查 blocked 任务(bd blocked)
bd blocked是bd ready的互补视图,展示所有被阻塞的任务,并给出阻塞来源:
🚫 Blocked issues (2): [P1] issue-3: Implement login page Blocked by 2 open dependencies: [issue-1, issue-2]对应实现见 cmd/bd/ready.go。bd blocked也支持--parent、--label、--label-any、--exclude-label过滤,与 ready 视图共用同一套 label 归一化逻辑。
查看 blocked 的价值在于:
- 理解工作为何卡住(哪个依赖还没完成);
- 识别关键路径项(被最多任务依赖的阻塞者);
- 规划依赖解决顺序(先关闭阻塞者,后续任务自动解锁进入 ready)。
bd blocked --explain(bd ready --explain的姊妹能力)还能输出依赖感知的原因分析:每个 ready 项标注"为何 ready"(如"所有阻塞依赖已关闭")、每个 blocked 项标注具体被谁、以何种状态阻塞,并检测依赖环(A → B → A)。
2. 新建任务(bd create)
如果确实没有现成可做的工作,Agent 可以用create工具新建一条 issue,例如把用户的新想法登记为 task,或把一个大目标登记为 epic,从而让队列重新有内容可认领。
八、ReadyFlag 作用域:bd list --ready 与 bd ready 的一致性
除独立命令外,bd list --ready也使用同一套 blocker-aware 语义(见 cmd/bd/ready.go 的命令注释:"'bd list --ready' uses the same blocker-aware ready-work semantics")。两个入口共享workapi.BuildReadyFilter与ReadyFilterFromIssueFilter,保证结果集合不会因入口不同而漂移。
同时,--ready与普通列表过滤器的组合受到严格约束:ValidateReadyFlagScope(见 issueops/reader_ready_scope.go)会拒绝那些 blocker-aware 查询无法携带的过滤条件——例如--id、--title、--spec、各种时间范围(--created-after等)、--deferred、--overdue、--pinned、--priority-min/max、游标等。原因很直接:ready 查询只携带列表词汇的一部分,如果静默丢弃这些条件,就会"返回所有 ready issue 而不是用户点名要的那些",因此宁可报错也绝不悄悄降级。而类型、标签、负责人、父级、元数据等投影能携带的字段则被完整保留。
九、Agent 集成要点:从 MCP ready 到会话协议
将ready工具放进 agent 会话协议,形成稳定节奏:
- 会话开始/上下文恢复后:先跑
bd ready(或 MCPready)获取当前可做任务清单,向用户展示 ID、标题、优先级、类型; - 用户选定后:立即
bd update <id> --claim(或 MCPclaim)原子认领,避免与其他 agent/会话竞争同一任务; - 工作中:用
bd show <id>取完整上下文,用bd update记录笔记(这些笔记在上下文压缩/会话重启后依然存活,是 Beads 持久记忆的核心价值); - 完成后:
bd close <id> --reason "..."关闭任务,其下游阻塞任务自动解锁进入 ready; - 队列为空时:检查
bd blocked分析卡点,或bd create新建任务,然后回到第 1 步。
Beads 的 skill 文档 plugins/beads/skills/beads/SKILL.md 中的 Session Protocol 正是这一循环的浓缩:bd ready→bd show→bd update --claim→ 记笔记 →bd close→bd dolt push。
十、小结
ready工具/bd ready命令是 Beads 工作队列的"取件口":它以 blocker-aware 语义扫描依赖图,只返回真正无阻塞、可立即开始的任务;bd ready --claim通过单一事务保证认领的原子性与一致性;bd blocked与bd create则构成空队列时的闭环兜底。对编码 Agent 而言,掌握这套流程就等于拥有一个跨会话、可恢复、不会重复认领的持久任务队列。
相关文件索引:
- Skill 文档:ready.md、blocked.md、SKILL.md
- CLI 实现:cmd/bd/ready.go、cmd/bd/ready_input.go
- 过滤器构建:internal/workapi/ready.go
- 角色接口:issueops/readyclaimer.go、issueops/readycounter.go、issueops/reader_ready_scope.go
- 测试用例:cmd/bd/ready_test.go
【免费下载链接】beadsBeads - A memory upgrade for your coding agent项目地址: https://gitcode.com/GitHub_Trending/beads1/beads
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考