结论
当前 Workflow 的确会在默认调用中阻塞主会话当前 turn,直到整个 Workflow 完成。
这不是偶发 bug,而是现在明确设计的默认值;但它与 OpenPI 已经确立的 Subagent 后台生命周期合同不一致,也削弱了交互会话中“后台工作不占住用户”的体验。
当前行为
基于当前 main@22e77d6:
extensions/workflows/prompt.ts:15-16 明确写明 background 默认 false,即 blocking with live progress;
extensions/workflows/index.ts:745 使用 (params.background ?? false) && ctx.hasUI;
extensions/workflows/index.ts:1693-1699 默认路径会 await completion,父工具调用直到 Workflow 完成才返回;
- 只有模型显式传
background: true 且 ctx.hasUI 时,才立即返回 run id,并在完成后回传消息;
- 非交互模式即使传
background: true 也会退回阻塞执行。
Subagent 的合同相反:
subagent_spawn 始终 fire-and-forget;
- spawn 立即返回 id;
- 结果完成后自动送回并在需要时重新唤醒父 Agent;
- 只有用户明确要求当前回复等完,或非交互自动化必须在同一次调用返回结果时,才使用
subagent_wait。
为什么值得改
Workflow 通常比单个 Subagent 更长、更容易包含 fan-out、pipeline、barrier 和多阶段验证。越长的任务越不应该默认占住交互父 turn。
当前默认值会产生几个实际问题:
- 用户在 Workflow 运行期间不能自然继续与主会话交互;
- 模型必须记得主动设置
background: true,否则一个小的参数遗漏就把长任务变成前台等待;
- Background Terminal、Subagent、Workflow 三类异步能力的默认心智模型不一致;
- 已有
workflow_status、workflow_stop、完成 follow-up、dashboard indicator 等完整后台生命周期,却没有成为交互模式的默认路径;
- “需要结果才能继续”会诱导模型保持当前 turn,而 Subagent 侧已经明确证明:依赖结果本身不是阻塞用户的理由,结果到达后重新唤醒即可。
建议合同
交互 Session
workflow(...)
→ 默认立即返回 run id
→ Workflow 后台运行
→ 父 Agent 可继续独立工作,或结束当前 turn
→ 完成后结果自动进入 Session,并按 idle/busy 规则重新唤醒
需要当前响应同步拿到结果时,应显式表达,例如:
- 保留兼容参数
background: false;或
- 将正向语义改成更清楚的
wait: true / mode: "blocking"。
不要因为父 Agent 的下一步依赖结果,就自动阻塞交互 turn。
非交互 / 自动化
非交互调用没有可靠的后续用户 turn,默认同步可能仍然合理。应单独定义,而不是机械地让所有环境都后台化:
interactive UI → 默认后台
print/RPC/automation → 默认阻塞,除非调用方明确具有结果接收合同
与 Subagent 保持一致,但不照搬实现
两者应共享以下原则:
- 默认不让长期子执行占住交互父 turn;
- 立即返回稳定 id;
- 状态可检查、可取消;
- 完成结果自动投递;
- 显式同步只用于用户要求或非交互同调用结果合同。
Workflow 仍保留自己的 artifact、replay、graph、acceptance 与多 Agent 生命周期,不需要改造成 Subagent。
调整默认值前,应确保 #71 的投递恢复机制足够可靠;否则扩大后台使用会放大一次性 sendMessage 失败的影响。两项可以分阶段实施,但验收应联动。
验收标准
非目标
- 不让父模型轮询
workflow_status;
- 不移除阻塞执行能力;
- 不把 Workflow 降级成单个 Subagent;
- 不依赖 Prompt 提醒模型每次手动写
background: true 来维持正确默认体验。
结论
当前 Workflow 的确会在默认调用中阻塞主会话当前 turn,直到整个 Workflow 完成。
这不是偶发 bug,而是现在明确设计的默认值;但它与 OpenPI 已经确立的 Subagent 后台生命周期合同不一致,也削弱了交互会话中“后台工作不占住用户”的体验。
当前行为
基于当前
main@22e77d6:extensions/workflows/prompt.ts:15-16明确写明background默认false,即 blocking with live progress;extensions/workflows/index.ts:745使用(params.background ?? false) && ctx.hasUI;extensions/workflows/index.ts:1693-1699默认路径会await completion,父工具调用直到 Workflow 完成才返回;background: true且ctx.hasUI时,才立即返回 run id,并在完成后回传消息;background: true也会退回阻塞执行。Subagent 的合同相反:
subagent_spawn始终 fire-and-forget;subagent_wait。为什么值得改
Workflow 通常比单个 Subagent 更长、更容易包含 fan-out、pipeline、barrier 和多阶段验证。越长的任务越不应该默认占住交互父 turn。
当前默认值会产生几个实际问题:
background: true,否则一个小的参数遗漏就把长任务变成前台等待;workflow_status、workflow_stop、完成 follow-up、dashboard indicator 等完整后台生命周期,却没有成为交互模式的默认路径;建议合同
交互 Session
需要当前响应同步拿到结果时,应显式表达,例如:
background: false;或wait: true/mode: "blocking"。不要因为父 Agent 的下一步依赖结果,就自动阻塞交互 turn。
非交互 / 自动化
非交互调用没有可靠的后续用户 turn,默认同步可能仍然合理。应单独定义,而不是机械地让所有环境都后台化:
与 Subagent 保持一致,但不照搬实现
两者应共享以下原则:
Workflow 仍保留自己的 artifact、replay、graph、acceptance 与多 Agent 生命周期,不需要改造成 Subagent。
与 #71 的关系
调整默认值前,应确保 #71 的投递恢复机制足够可靠;否则扩大后台使用会放大一次性
sendMessage失败的影响。两项可以分阶段实施,但验收应联动。验收标准
workflow_status查看、通过workflow_stop取消;非目标
workflow_status;background: true来维持正确默认体验。