22 · 一次任务的端到端源码追踪¶
一句话结论: 一次看似简单的“让 Agent 修改项目并提交产物”,实际穿过 Company/Issue、授权、预算、wakeup、checkout、workspace lease、adapter session、tool gateway、cost、live event、finalize 和 recovery 十多个状态边界。
1. 场景设定¶
假设 Board 在 Company PAP 下创建 Issue:
PAP-123 为产品项目补充一个 API 错误处理页面
assignee: CTO/Engineer Agent
project: web-app
workspace preference: isolated
tool profile: GitHub read + approved write
budget: company + agent monthly window
目标不是复述某次线上运行,而是沿当前源码快照还原一条合法执行路径。
2. 创建 Issue¶
sequenceDiagram
participant U as Board UI
participant R as issues route
participant A as Authorization
participant I as Issue Service
participant DB as PostgreSQL
participant E as Activity/Live
U->>R: POST /companies/:companyId/issues
R->>R: validate createIssueSchema
R->>A: actor can create in Company/project?
A-->>R: allow
R->>I: create issue + identifier
I->>DB: transaction / prefix counter / relations
I->>E: activity.logged
I-->>R: Issue DTO
R-->>U: 201 + PAP-123
identifier 来自 Company prefix/counter,origin 若为手工则保持 manual。UI mutation 成功后更新/失效 Issue list。
3. 创建时的隐藏约束¶
服务可能同时校验:
- project/goal 同 Company;
- parent Issue 同 Company/project policy;
- assignee Agent 可 invokable;
- responsible user 有资源权限;
- workspace preference 被 project policy 允许;
- source trust/low-trust settings;
- labels/attachments/document refs;
- create idempotency key(若 client 提供)。
所以“POST 成功”已经是一次跨域 transaction,而不是单表 insert。
4. Assignment 触发 Wakeup¶
Board 指派 Agent 或 Agent 通过上级委派时,Issue assignment service 可能发布 assignment wakeup:
Issue mutation
→ assignment activity
→ responsible user resolution
→ enqueueWakeup(source=assignment)
如果 Agent paused、budget blocked、Company hold 或无 actionable work,request 仍可能记录为 skipped/deferred,并带原因。
5. Wakeup 入队¶
flowchart TD
W["assignment wake"] --> N["canonical Issue + Actor + responsible user"]
N --> V["invokability + budget + pause hold"]
V -->|fail| SK["agent_wakeup_requests=skipped"]
V -->|pass| TX["transaction lock Issue / coalesce"]
TX --> Q["wakeup request=queued"]
Q --> RUN["heartbeat_run=queued"]
如果已有同一 Issue 的 active execution,可能进入 deferred_issue_execution 或 coalesced。队列不是内存数组,重启后仍可读取。
6. Claim Heartbeat Run¶
Agent queue 选择该 run,执行 CAS:
此时注册 active execution,后续 stop/recovery 可以定位它。另一个 worker 同时 claim 时只有一个成功。
7. 自动 Checkout Issue¶
assignment wake 允许且 Issue 仍 todo/可认领时,Heartbeat 调用 Issue service checkout:
- 验证 Agent assignable;
- 检查 tree hold/blocker/workspace finalize;
- 条件更新
assigneeAgentId + checkoutRunId + executionRunId; - 失败后区分幂等、stale adoption、409。
此刻任务获得的是数据库所有权,不是 Agent Prompt 中的“请你负责”。
8. 解析运行上下文¶
Heartbeat 读取并合并:
Company mission / goal ancestry
Project + project workspace policy
Issue + parent + comments + blocker
Agent identity + org instructions
Wake reason + current run
Responsible user + trust preset
Adapter config + model/profile
Skill selection + tool profile
不可信 Issue/comment 内容被标注/清理;Paperclip runtime protocol 和 governance constraints 由 Server 生成,而不是让 Issue 文本覆盖。
9. 选择并准备 Workspace¶
本例 Issue 指定 isolated,Server 根据 Project primary workspace 和 Environment:
- 找/建 execution workspace;
- 记录 strategy/base ref;
- acquire environment lease;
- local 创建 worktree 或 derived dir,远端使用 provider realization;
- 写 workspace prepare operation;
- 运行 setup;
- materialize instructions/skills;
- 配置 runtime services 和 tool gateway。
任何一步失败都会让 Run 有明确 setup failure,不能直接让 Agent 在未知 cwd 启动。
10. 解析 Secrets 与 Tools¶
Adapter 获得的不是长期 GitHub token,而是:
- run-scoped Paperclip JWT;
- named gateway URL/token;
- tool profile 允许的 catalog;
- secret refs 在运行时投影的 header/env;
- issue/project/responsible-user attribution。
Agent 请求 create_pull_request 时,仍需经过 Gateway policy/approval;Prompt 中写“请提交 PR”不具备权限。
11. Adapter 启动¶
Registry 解析 codex_local 或 claude_local module,adapter:
- 读取 config schema;
- 解码该 task session;
- 检查 workspace/cwd compatibility;
- 建立 CLI args/env/instructions;
- 尽早上报 PID/process group;
- 开始发送 stdout/structured event。
Server 将事件写入 run log/event,并通过 Company live WebSocket 发布。
12. UI 如何看到过程¶
sequenceDiagram
participant S as Server
participant WS as Live WebSocket
participant P as LiveUpdatesProvider
participant Q as Query Cache
participant V as Issue Detail
S->>WS: heartbeat.run.status(running)
WS->>P: JSON LiveEvent
P->>Q: patch active/live run
P->>Q: batch invalidate heartbeat/issue queries
Q-->>V: render running + current tool
S->>WS: heartbeat.run.progress
WS->>P: progress event
P->>Q: immediate snippet/tool patch
页面只开一个 Company socket;事件丢失时,重连会 refetch live runs/详情。
13. Agent 调用 MCP Tool¶
sequenceDiagram
participant A as Agent Runtime
participant G as Tool Gateway
participant P as Profile/Policy
participant H as Human
participant U as GitHub MCP
A->>G: create_pull_request(params)
G->>P: catalog + profile + policy
P-->>G: require_approval
G-->>A: 409 + actionRequestId
G->>H: issue thread confirmation / attention
H->>G: approve
A->>G: retry + approvedActionRequestId
G->>P: hash/schema/scope revalidation
G->>U: call with projected credential
U-->>G: PR result
G-->>A: guarded result
Approval 的参数 hash 防止 Agent 把批准的安全调用替换成另一个 destructive 参数。
14. Agent 产出与 liveness¶
假设 Agent 返回:
- 修改了代码;
- 创建了 draft PR;
- 写了 Issue comment;
- 还有一个待 reviewer 的下一步。
Run 可能是 succeeded,但 liveness 为 needs_followup 或 advanced,Issue 进入 in_review,并创建/唤醒 reviewer path。不能因为 process exit 0 就自动 done。
如果 Agent 只写了“我完成了”却没有代码/PR/测试证据,liveness/issue policy/watchdog 可以把它标成 empty/plan_only 或要求继续。
15. Cost 与 Budget¶
Adapter result 归一化 token/provider/biller/cents,Server:
- append cost event;
- 更新 spend read model;
- evaluate policy window;
- 生成 warning/hard incident;
- 如跨 hard limit,暂停 Agent、阻断未来 wake;
- publish activity/live update。
Run 已完成的成本不会因 budget 后续暂停而被删除。
16. Finalization 顺序¶
adapter result
→ run terminal status + liveness + usage/session
→ issue continuation/review/lock decision
→ workspace finalize operation
→ sync/export work product refs
→ release environment lease
→ stop/reuse runtime services
→ clear active execution registry
→ start next queued run
Run terminal 早于 lease release,防止下一个 run 复用环境时 recovery 仍把上一 run 看成 live。
17. 成功路径后的证据¶
Board 最终可以看到:
- Issue status/assignee/checkout run;
- run transcript/log/progress/usage/cost;
- Activity timeline;
- document revision;
- PR/preview/artifact work product;
- workspace/branch/provider reference;
- approval/tool audit;
- follow-up/reviewer path。
这些是不同读模型,不能只用一个“完成截图”代替。
18. 故障分叉 A:Adapter 启动前失败¶
例如 binary 缺失:
Run claim 成功
→ workspace prepare 可能成功
→ adapter test/execute 失败
→ run=failed(setup class)
→ release lease/cleanup workspace
→ Issue 保留 owner 或转 recovery
→ activity + actionable notice
是否 retry 取决于配置是否可修复,不能无限重试同一缺失 binary。
19. 故障分叉 B:进程被杀/Server 重启¶
旧 Run running + PID/process metadata
→ startup hot-restart reconcile
→ process/provider identity check
→ adopted / finalized_while_down / lost
→ terminalize or retry/recovery
→ clear/retain Issue lock with evidence
UI 重连后通过 REST 对账,不能只依赖旧 WebSocket event。
20. 故障分叉 C:workspace finalize 失败¶
即使 adapter result succeeded:
- Run 可以是 succeeded;
- workspace operation 是 failed/pending;
- Work Product 可能标记 incomplete/unhealthy;
- 下游 blocker 不应立即满足;
- recovery/retry 处理 sync/cleanup;
- Board 看到明确 notice。
这正是执行成功、交付成功、依赖满足三者分离的价值。
21. 故障分叉 D:预算越界¶
多个 run 并发时可能都在阈值前启动。成本落账后:
- 第一条 crossing event 创建 incident;
- policy/Agent 持久化 paused/block;
- queued wake 被 skipped;
- 可取消的 run 进入 interrupt;
- Board 可选择 keep paused 或 raise budget/resume。
系统不承诺对已经消耗的 provider 成本回滚,只保证未来执行不再无界增长。
22. 最终状态的判定¶
一个可靠的“完成”至少要满足:
Issue transition allowed
+ required review/approval satisfied
+ execution evidence present
+ workspace finalize settled
+ expected work product/document/artifact recorded
+ no unresolved blocker
+ run/lease/lock coherent
不同 work mode 可调整证据要求,但不能绕过 Company scope、authorization、budget 和 audit。
23. 这条链暴露的架构原则¶
- 状态机优先:每一步都可被数据库、事件和 recovery 解释。
- 控制面/执行面分离:模型 runtime 可换,治理事实不换。
- 证据优先:完成是可验证产物,不是文本宣称。
- 失败可继续:每个中断点都有 retry、recovery、review 或人工路径。
- 租户与责任贯穿:Company、Agent、Run、responsible user 在每一层被携带。
24. 复用这条模式时的最小清单¶
[ ] tenant/company scope
[ ] separate intent, attempt, session
[ ] atomic ownership CAS
[ ] durable queue + idempotency
[ ] runtime adapter capability contract
[ ] workspace/environment/lease lifecycle
[ ] short-lived run credentials
[ ] preflight auth/budget/approval
[ ] terminal-before-resource-release
[ ] liveness + recovery scanner
[ ] activity/cost/output evidence
[ ] REST truth + realtime hints
这也是本文全部章节的压缩版。
源码入口¶
- Issue:
server/src/routes/issues.ts、server/src/services/issues.ts - Wake/Run:
server/src/services/heartbeat.ts - Adapter:
packages/adapter-utils/、packages/adapters/ - Workspace:
server/src/services/execution-workspaces.ts、workspace-realization.ts - Auth:
server/src/middleware/auth.ts、services/authorization.ts - Governance:
services/budgets.ts、approvals.ts、tool-gateway.ts - UI:
ui/src/context/LiveUpdatesProvider.tsx - Recovery:
server/src/services/recovery/