Beads bd gate 指南:用异步门控(Gate)编排编码 Agent 工作流
【免费下载链接】beadsBeads - A memory upgrade for your coding agent项目地址: https://gitcode.com/GitHub_Trending/beads1/beads
导读
bd gate是 Beads 中用于异步协调工作流的核心命令族:它以"门控(Gate)"这一特殊 issue 类型表达等待条件,阻塞下游步骤直到外部条件(人工审批、定时器、GitHub Actions 运行、PR 合并、跨 rig 的 bead 关闭)被满足。本文将围绕 docs/cli-reference/gate.md 完整讲解 gate 的七个子命令与五种门控类型,并结合 cmd/bd/gate.go、cmd/bd/gate_discover.go 的源码与 cmd/bd/gate_test.go 中的测试,说明其底层判定逻辑。读完你将掌握:如何创建 gate 阻塞某 issue、如何用bd gate check自动评估并关闭已满足的 gate、如何用bd gate discover为 CI 门控自动发现 GitHub run ID,以及如何在多 Agent 场景中通过 waiters 实现"完工唤醒"。
Gate 是什么:异步等待条件
在 Beads 中,gate 是一种特殊的 issue(issue 类型为gate),作为异步等待条件阻塞工作流步骤。它的核心语义(见 cmd/bd/gate.go):
- gate 会在 formula 步骤带有
gate字段时被自动创建; - 必须被关闭(人工或通过 watcher),被阻塞的步骤才能继续;
- 被 gate 阻塞的 issue不会出现在
bd ready中,直到 gate 被 resolve。
从依赖图的角度看,"gate 是一个 issue",可以像普通 issue 一样被接入依赖图:docs/core-concepts/dependencies.md 演示了用bd dep add issue-2 <gate-id>让 issue-2 等待一个 gate。
五种 Gate 类型
| 类型 | 等待条件 | 自动判定方式 |
|---|---|---|
human | 人工确认 | 手动执行bd gate resolve <id>(Phase 1) |
timer | 时间到期 | 当前时间超过created_at + timeout(Phase 2) |
gh:run | GitHub Actions workflow 运行完成且成功 | gh run view <id> --json status,conclusion(Phase 3) |
gh:pr | PR 被合并 | gh pr view <id> --json state,title(Phase 3) |
bead | 另一个 rig 的 bead 关闭 | 通过路由查询目标 bead 状态(Phase 4) |
对于beadgate,await_id的格式为<rig>:<bead-id>(例如other-project:op-abc123)。从 cmd/bd/gate.go 的实现看,checkBeadGate会剥离<rig>:前缀,以bead-id作为路由查找键;若格式非法(前缀或 ID 为空)会保持 pending 并给出错误提示,TestCheckBeadGate_InvalidCrossRigFormat(cmd/bd/gate_test.go)专门验证了这一行为。
bd gate list:查看门控
列出当前 beads 数据库中所有 gate issue。默认只显示**打开(open)**的 gate,使用--all包含已关闭的。
bd gate list [flags]Flags:
-a, --all Show all gates including closed -n, --limit int Limit results (default 50) (default 50)源码细节:bd gate list支持可选 issue-id 参数(见 cmd/bd/gate.go)。不带参数时按IssueType=gate且排除StatusClosed过滤全库;带参数时只列出阻塞该 issue 的依赖 gate(filterIssueGates,通过GetDependencies取得依赖集后过滤出 gate 类型),避免误把全库 gate 当成目标 issue 的门控。列表输出会把打开与关闭的 gate 分开展示,并提示To resolve a gate: bd close <gate-id>。
bd gate show:查看单个门控详情
显示某个 gate issue 的详细信息,包括其 waiters。与bd show类似,但会校验该 issue 确实是 gate(IssueType != "gate"时报错,见 cmd/bd/gate.go)。
bd gate show <gate-id> [flags]输出字段(renderGateShow)包括:状态符号、gate ID、标题、Status、Await Type、Await ID(如有)、Timeout(如有)、Waiters 列表、Description。配合--json全局开关可输出结构化 JSON。
bd gate resolve:手动关闭门控
关闭一个 gate issue,解除等待该 gate 的步骤。其语义等价于bd close <gate-id>,只是名字更明确;可用--reason说明解决原因。
bd gate resolve <gate-id> [flags]Flags:
-r, --reason string Reason for resolving the gate对应human类型 gate 的默认关闭路径:store.CloseIssue(ctx, gateID, reason, actor, "")(见 cmd/bd/gate.go),成功后输出✓ Gate resolved: <id>。humangate 也出现在 docs/core-concepts/dependencies.md 的 Gate Types 表中,是唯一完全依赖人工判定的类型。
bd gate create:创建临时门控
创建一个临时 gate issue 阻塞另一个 issue,直到该 gate 被 resolve。被阻塞的 issue 在 gate 解决前不会出现在bd ready中。
bd gate create [flags]Flags:
--await-id string Condition identifier (run ID, PR number, etc.) --blocks string Issue ID to block (required) -r, --reason string Reason for the gate --timeout string Timeout duration (e.g., 2h, 30m) -t, --type string Gate type (human, timer, gh:run, gh:pr) (default "human") --title string Custom gate title (default: "Gate: <type>")示例:
bd gate create --blocks bd-abc bd gate create --type=human --blocks bd-abc --reason="Need design review" bd gate create --type=timer --blocks bd-abc --timeout=2h bd gate create --type=gh:pr --blocks bd-abc --await-id=42 bd gate create --blocks bd-abc --title="Gate: awaiting owner sign-off"底层实现要点(见 cmd/bd/gate.go):
--blocks为必填,缺失时直接报错(MarkFlagRequired);--timeout通过time.ParseDuration解析,支持2h、30m等 Go duration 格式;- 新 gate 的 title 默认为
Gate: <type>,若带await-id则为Gate: <type> <await-id>,也可用--title完全自定义; - 创建后会自动为 gate 与目标 issue 建立
DepBlocks类型的依赖边,使被阻塞 issue 在 gate 打开时保持非 ready; - 对
gh:run/gh:pr类型,repoMetadataForGate会从被阻塞 issue 的 metadata 中继承并校验 GitHub 仓库选择器(OWNER/REPO或HOST/OWNER/REPO),供后续 check 跨仓库查询使用(见 cmd/bd/gate.go); - 成功后输出
✓ Created gate <id> (type: ...),并提示Resolve with: bd gate resolve <id>。
bd gate check:评估并自动关闭已满足的门控
评估 gate 条件,自动关闭已满足的 gate。默认检查所有打开的 gate,可用--type按类型过滤。
bd gate check [flags]Flags:
--dry-run Show what would happen without making changes -e, --escalate Escalate failed/expired gates -l, --limit int Limit results (default 100) (default 100) -t, --type string Gate type to check (gh, gh:run, gh:pr, timer, bead, all)--type的取值与过滤语义(shouldCheckGate,见 cmd/bd/gate.go):
--type | 匹配范围 |
|---|---|
(空)或all | 全部类型 |
gh | 所有gh:前缀类型(gh:run+gh:pr) |
gh:run | 仅 GitHub Actions workflow 运行 |
gh:pr | 仅 PR 合并状态 |
timer | 仅定时器 |
bead | 仅跨 rig bead 门控 |
GitHub gate 通过ghCLI 查询状态:
gh:run执行gh run view <id> --json status,conclusion;gh:pr执行gh pr view <id> --json state,title。
判定规则(resolve / escalate / pending),来自 cmd/bd/gate.go 及checkGHRunStatusInRepoWithRunner(cmd/bd/gate.go)、checkGHPRWithRunner(cmd/bd/gate.go)、checkTimer(cmd/bd/gate.go):
| 类型 | 已满足(resolve) | 升级(escalate) | 挂起(pending) |
|---|---|---|---|
gh:run | status=completed且conclusion=success(skipped 也视为成功) | completed且conclusion为 failure / canceled / 其他非成功值;或 run 不存在 | 运行中(in_progress / queued / pending / waiting) |
gh:pr | state=MERGED | state=CLOSED(未合并关闭);或 PR 不存在 | state=OPEN |
timer | 当前时间 > created_at + timeout | 设计上永不开级(escalated恒为 false) | 未到期(报告剩余时间) |
bead | 目标 beadstatus=closed | 不适用 | 目标 bead 仍打开或查找失败 |
示例:
bd gate check # Check all gates bd gate check --type=gh # Check only GitHub gates bd gate check --type=gh:run # Check only workflow run gates bd gate check --type=timer # Check only timer gates bd gate check --type=bead # Check only cross-rig bead gates bd gate check --dry-run # Show what would happen without changes bd gate check --escalate # Escalate expired/failed gates输出与汇总:每个 gate 显示✓ resolved / ⚠ ESCALATE / ○ pending状态行,最后汇总Checked N gates: X resolved, Y escalated, Z errors;配合全局--json会输出结构化结果(checked / resolved / escalated / errors / dry_run,见printGateCheckSummary)。--dry-run只打印"would resolve / would escalate"而不落库;--escalate开启后,升级的 gate 会调用gt escalate(主题为Gate escalation: <id>,严重级别 HIGH)通知相关方(见escalateGate,cmd/bd/gate.go)。
bd gate add-waiter:注册完工唤醒
将某个 Agent 注册为 gate bead 上的 waiter。gate 关闭时,waiter 会通过bd gate wake收到唤醒通知。waiter 通常是 worker 的地址(如my-project/workers/agent-1)。
bd gate add-waiter <gate-id> <waiter> [flags]典型使用场景:bd done --phase-complete用它注册 gate 唤醒通知。实现上(cmd/bd/gate.go)会先校验该 issue 确实是 gate,再检查 waiter 是否已注册(已注册则幂等返回),最后把 waiter 追加写入 issue 的waiters字段。这一机制让多 Agent 流水线中的下游 Agent 可以"睡着",直到上游 gate 关闭被唤醒,而不是忙轮询。
bd gate discover:自动发现 GitHub run ID
为等待 CI/CD 完成的 gate 自动发现 GitHub workflow run ID。它找出await_type="gh:run"且没有 await_id(或 await_id 是非数字的 workflow 名称提示)的打开 gate,查询最近的 GitHub workflow runs,用启发式规则匹配,并把匹配到的 run ID 写回 gate 的await_id,使后续bd gate check轮询能查询该 run 的状态。
bd gate discover [flags]Flags:
-b, --branch string Filter runs by branch (default: current branch) -n, --dry-run Preview mode: show matches without updating -l, --limit int Max runs to query from GitHub (default 10) -a, --max-age duration Max age for gate/run matching (default 30m0s)匹配启发式(matchGateToRun,见 cmd/bd/gate_discover.go):
- Workflow 名称提示匹配(+200):当
await_id是非数字的 workflow 名时,只考虑该 workflow 的 run(workflowNameMatches兼容大小写不敏感精确匹配、.yml/.yaml后缀归一化); - Commit SHA 匹配(+100):run 的
headSha等于当前本地 git commit SHA; - 分支匹配(+50):run 的
headBranch等于当前分支(默认取当前 git 分支,getGitBranchForGateDiscovery,失败回退main); - 时间邻近度(+30/+20/+10):run 创建时间与 gate 创建时间相差小于 5 分钟得 30 分,小于 10 分钟得 20 分,小于 30 分钟得 10 分;
- 运行状态偏好(+5):
in_progress或queued的 run 更可能是当前这次。
总得分 ≥ 30 才接受匹配(有 workflow 提示时,仅 workflow 匹配 200 分即足够;无提示时需分支/commit 加分),否则视为无匹配。--max-age控制匹配的时间窗口上限,默认 30 分钟。
跨仓库(cross-repo)行为(matchGatesToRuns、branchFilterForRepo):当 gate 的metadata.repo指向其他仓库时,发现过程只查询该仓库的 runs,绝不会用当前仓库同名 workflow 的 run 去匹配;自动检测到的本地分支不会套用到外部仓库(用户显式传入的--branch除外),且无 workflow 提示的外部 gate 会被跳过查询,避免错误地把另一个仓库的 run ID 永久钉在 gate 上。
示例:
bd gate discover # Auto-discover run IDs for all matching gates bd gate discover --dry-run # Preview what would be matched (no updates) bd gate discover --branch main --limit 10 # Only match runs on 'main' branch完整实战:从 CI 门控到多 Agent 编排
场景一:等待 CI 通过再继续
# 1. 创建等待 CI 的 gate,阻塞 deploy 任务 bd gate create --type=gh:run --blocks bd-deploy-7 \ --await-id=ci.yml --reason="Wait for CI green on main" # 2. 在 CI 尚未产生 run 时自动发现并钉住 run ID bd gate discover --dry-run # 先预览 bd gate discover # 应用匹配 # 3. 定期评估,成功则自动关闭 bd gate check # CI 成功后自动 resolve bd gate check --escalate # CI 失败时升级告警 # 4. 人工兜底关闭 bd gate resolve bd-deploy-7.gate-abc123 --reason "Verified manually"场景二:定时冷却门控
bd gate create --type=timer --blocks bd-hotfix-9 --timeout=30m --reason "Cooldown" bd gate check --type=timer # 到期后自动 resolve场景三:PR 合并门控
bd gate create --type=gh:pr --blocks bd-issue-2 --await-id=42 bd gate check --type=gh:pr # PR 合并(MERGED)后自动放行场景四:多 Agent 阶段衔接(配合 waiters)
# Agent A 完成阶段,注册下游 Agent B 作为 waiter bd gate add-waiter bd-deploy-7.gate-abc123 "my-project/workers/agent-2" # gate 关闭后,Agent B 收到 bd gate wake 唤醒通知,无需轮询定期自动化建议
docs/core-concepts/dependencies.md 建议周期性运行bd gate check自动关闭已满足的 gate,例如 cron:
*/5 * * * * cd /path/to/repo && bd gate check常见问题与边界
- gh CLI 缺失:
gh:run/gh:pr/discover依赖ghCLI(源码通过exec.LookPath("gh")检查,见 cmd/bd/gate.go),未安装时报错gh CLI not found; - timer gate 没有 timeout:
checkTimer在Timeout == 0时返回错误no timeout set,保持 pending; - gate 不是 issue:
show/resolve/add-waiter均会校验IssueType,非 gate 类型直接报错; - bead gate 路由:跨 rig 的 bead gate 通过 bead ID 前缀在
routes.jsonl中路由解析(见 cmd/bd/gate.go),本地未命中时会按 local → prefix route → contributor 的顺序回退(routedBeadGateGetter); discover不支持 proxied-server 模式:源码中runGateDiscover在usesProxiedServer()时直接报错(cmd/bd/gate_discover.go)。
相关文档与源码
- CLI 参考:docs/cli-reference/gate.md、docs/CLI_REFERENCE.md
- 核心概念:docs/core-concepts/dependencies.md(Gate Types 表格、
bd create --type=gate的另一种创建方式与依赖接线) - 源码实现:cmd/bd/gate.go(gate 命令族与判定逻辑)、cmd/bd/gate_discover.go(run ID 发现与跨仓库匹配)
- 测试验证:cmd/bd/gate_test.go(类型过滤、bead 跨 rig 路由、
gh状态判定、workflow 发现持久化、metadata 校验等覆盖)
【免费下载链接】beadsBeads - A memory upgrade for your coding agent项目地址: https://gitcode.com/GitHub_Trending/beads1/beads
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考