Run:从需求到交付的编排单元
Run 把「对话 → 需求拆解 → 审批 → 执行 → 交付 → 结算」收敛成一个可恢复、可审计的对象。 相关页面:门面 Agent 与 AgentRuntime、状态层、履约与托管。
1. 为什么需要 Run
改造前,一次需求会经历:
对话 → 一次性拆解 → 静态 DAG → 逐节点执行它的问题是:
- 多轮输入不是同一个 loop;
- 拆解一旦译错,整张图都错;
- 执行、审批、结算各自持有状态;
- 对话页只能看到节点级状态,看不到工具、审批、产物;
- 支付确认没有入口。
现在:
用户多轮输入 ⇄ Run → 审批 → 执行 → 交付 → 结算
│
└── 每一步写 L0;UI / 恢复 / 审计读同一份事件Run 是编排与审计单元;Task 是业务归属;Workflow 是只读投影;DialogueSession 是私有对话。
2. 生命周期
intake → clarifying → planning → awaiting_plan_approval
│ approve + commit
▼
executing
│ ├─ waiting_external
│ ├─ awaiting_tool_approval
│ ├─ paused
│ └─ delivering → settling → completed
└─ failed / cancelled / expired- 终态不复活;重跑 = 新建 Run。
waiting_external是长事务:不占 worker / runtime 并发槽,靠事件恢复。paused记录pausedFrom,恢复回到原状态。- 恢复只依赖 L0;进程重启不会丢状态。
3. 一次需求的完整流程
3.1 拆解
需求拆解复用 AgentRuntime,通过四个只读工具推进:
| 工具 | 作用 |
|---|---|
search_skills | 检索 Skill catalog,前 8 条附 top agent |
match_agents | 按 skill + subDomain 匹配 top-3 agent |
propose_plan | 检索 + 匹配 + 依赖 + 报价;{ query } 一次完成 |
ask_user | 信息不足时追问,记录 Interaction |
规则优先:关键词命中则完全不调模型;循环失败回退单轮 LLM / 关键词。
3.2 审批
- 计划级审批始终存在:金额、agent、
planHash、过期时间。 - 多级审批:
policySettings.run.requiredApprovers控制批准人数;approvedBy累积,达到人数才 approved。 - 工具级审批按
policySettings.run.toolApprovalThreshold触发;执行中单笔超阈值时暂停。 - 审批决定写 L0;拒绝 / 过期 / 撤销会取消 Run 并退款。
3.3 支付
POST /api/runs/:id/commit { approvalId }这是唯一花钱入口:
- 校验 approved 审批、runId、planHash、金额、过期时间;
- 金额 > 0:开托管 + fund;
- 金额 = 0:不建托管,写
freecommit,直接进入执行; - 同一
runId + planHash幂等。
微信模式(RUN_PAYMENT_PROVIDER=wechat):
POST /api/run-payment/wechat下单(JSAPI / Native);- 回调
POST /api/run-payment/wechat/notify验签/解密后调用 commit; - 直连 commit 会被拒绝,避免绕过付款;
- RunPanel 在 wechat 模式显示 WeChat Pay 卡(Native 展示
code_url),支付回调后自动继续执行。
3.4 执行
TaskExecutionService 按依赖选择 ready 批次,并发执行:
- 每个 step / batch / decision 写 L0,并自动带
runId; - 派发前做工具级审批检查;超阈值时不派发,Run 进入
awaiting_tool_approval; - 审批通过后
POST /api/task/:id/resume恢复; - 第三方
INPUT_REQUIRED→ Runwaiting_external;用户POST /api/task/:id/external-input补充后恢复(重新派发同一 step,带external_task_id);RunPanel 显示状态条和补充输入卡; - RunPanel 顶部还显示当前 task 的指标条(runs / success / p95 / pending);
- 内部门面 agent 的 tool 调用也写
tool.finished; - 外部 A2A 供应商未上报时只记录
step.updated;上报toolCalls时写tool.finished。
3.5 交付
Agent 回传产物后,ArtifactService 登记并写 artifact.ready;对话页直接显示产物卡。验收与结算继续走履约 / 托管。
4. 事件流
L0 state_events
→ StateEventBus(Redis pub/sub;无 Redis 时进程内)
→ Run SSE(GET /api/runs/:id/events?afterSeq=)
→ 对话页 RunPanel事件类型:
run.* · approval.* · interaction.* · tool.finished · step.updated · batch.updated · artifact.ready · run.plan_committed
- 客户端断线重连用
afterSeq; - 总线只做“叫醒”,事件按 L0
seq读取,保证顺序与幂等; - Redis 不可用时 5 秒兜底,不阻塞写入。
5. API
| 方法 | 路径 | 说明 |
|---|---|---|
GET | /api/runs/:id | Run 快照 + 当前等待项 |
GET | /api/runs/:id/events | SSE 事件流 |
GET | /api/runs/metrics | 用户/任务/时间范围指标 |
POST | /api/runs/:id/messages | 用户输入 / 恢复 |
GET | /api/runs/:id/approvals | 列出审批 |
GET | /api/runs/:id/interactions | 交互记录(提问 / 回答) |
POST | /api/runs/:id/approvals/:approvalId | 批准 / 拒绝 |
POST | /api/runs/:id/approvals/:approvalId/revoke | 撤销审批(取消 + 退款) |
POST | /api/runs/:id/commit | 提交计划(唯一花钱入口) |
POST | /api/runs/:id/cancel | 取消 |
POST | /api/runs/:id/pause | 暂停 |
POST | /api/runs/:id/resume | 恢复 |
POST | /api/runs/:id/external-events | 第三方状态回传 |
POST | /api/task/:id/external-input | 用户补充第三方所需输入 |
POST | /api/run-payment/wechat | 微信支付下单(JSAPI/Native) |
POST | /api/run-payment/wechat/notify | 微信支付回调 |
6. 边界
- 托管是状态机 + 划转指令;默认
manual,开启RUN_PAYMENT_PROVIDER=wechat时走 prepay/notify。 autonomous受控自动启动默认关闭;开启RUN_AUTONOMOUS_AUTOSTART后只在 commit 后自动启动执行,不自动审批/付款。- Run 全链路 e2e 已覆盖审批 → commit → 执行 → 验收 → 结算。
- 第三方长事务由 60 秒扫描器自动过期(
RUN_EXPIRY_SWEEP=off可关)。 - 第三方
INPUT_REQUIRED已支持暂停/补充/恢复;当前重新派发新 A2A task,带external_task_id供供应商关联。 - A2A 供应商标准协议不暴露内部工具;上报
toolCalls时平台写tool.finished。 - Run 指标 API 已提供;可视化面板尚未提供。