执行轨迹与编排模式
面向开发者与平台运营。 普通用户只需要在工作台看进度,不需要理解这里的编排细节。
Hushwork 的执行过程不再由一张预先编译的 DAG 驱动,而是由运行时循环逐步推进: 每一步执行前才决定"现在哪些节点可以跑",并把每一步写入 L0 状态层。页面上的 执行轨迹流就是这份事件日志的投影。
在哪里看
- 聊天页:任务开始执行后,消息流下方会出现「执行轨迹」区块
- 任务工作流页:顶部新增
Trace标签页,与 DAG 视图并列
两处读的是同一个接口:GET /api/task/:id/trace。因此不会出现"日志里在跑、画布上是灰的"。
轨迹里有什么
| 层 | 展示 | 对应事件 |
|---|---|---|
| 并发组 | 并行执行 · N 个 agent · M/N 完成 + 总进度 | /tasks/{taskId}/batches/{batchId} 与同批 step |
| Agent 卡 | pending / waiting / executing / completed / failed + 耗时 | /tasks/{taskId}/steps/{stepId} |
| 工具行 | dispatch · skill → agent,折叠成一行 | 同一 step 事件上的 input / output / durationMs |
| 决策点 | 为什么选这家 Agent | /tasks/{taskId}/steps/{stepId}/decision |
| 产物 | 报告 / 证书 / 图片,点击即看 | Artifact + 事件里的 sha256 证据 |
依赖未满足的节点显示 waiting(依赖 X),不会被隐藏; 前置失败的节点显示 blocked,并写明失败的上游。
并发组怎么分组
同一次 dispatch 批次里、彼此没有依赖的 step 归为一组:
- 并行:同一组内多张 Agent 卡同时出现
- 串行:不同组按时间顺序出现
- 折叠组头后,进度条仍然保留 —— 并发不会"消失"
人工干预
DAG 页已降级为只读总览:
execute由 agent 循环自动推进,页面上不再提供restart已取消(原地重来会污染审计链;需要重跑请新建一次执行)- 保留
pause/resume - Diagram 优先渲染实际发生过的 step(事件投影);没有轨迹的历史任务才回退到 Workflow 结构
resume以事件重放为依据:已完成的 step 从 L0 重放后跳过,不依赖进程内状态
配置开关
| 变量 | 默认 | 说明 |
|---|---|---|
TASK_EXECUTION_MODE | loop | graph = 回退旧的拓扑排序执行路径 |
DEMAND_AGENT_LOOP | on | off / 0 / false = 需求拆解回退旧的单轮 LLM 路径 |
两个开关都是按调用时读取,改动后下一次执行 / 下一次需求受理即生效,不需要改代码。
审计不变量
- 先写事件,再派发:L0 写入失败时该 step 不会被派发
- 每条 step 事件都带
actor、causedByEventId、triggerDepth - 每条决策点只记录"选了谁、为什么",不记录 token 级推理
- 轨迹与 DAG 同源,禁止前端自行拼装执行状态
测试覆盖
- 单测:
task-agent-loop.service.spec.ts(批次选择 / 阻塞 / 投影 / 中断收尾)、task-execution.loop.spec.ts(并发 / 阻塞 / 事件) - 真库 e2e:
apps/hushwork/test/p3-agent-loop.e2e-spec.ts- 执行 3 节点(CE/HS 并发、WEEE 等待 CE)→ 轨迹接口 → 交付 → 验收 → 托管
released - 中断在
step-a之后时resumeExecution只继续未完成节点,已完成节点不重复派发
- 执行 3 节点(CE/HS 并发、WEEE 等待 CE)→ 轨迹接口 → 交付 → 验收 → 托管
- 中断收尾:进程被 kill / reload 后,终态任务的轨迹会把仍停在
running/waiting的 step 显示为failed/blocked,不会一直转圈