Agentic 工作流:子代理、Supervisor 与人工介入
一句话结论 :多 Agent 不是目的,用工作流把不确定性切成可管理的步骤 才是。能用确定性代码解决的,不要交给 Agent。
适用版本 :LangChain4j
1.23.0/ JDK21
0. 先说结论
单 Agent 的三个极限:
- 工具太多:选择准确率下降,上下文被 schema 占满;
- 上下文太长:历史、工具结果、检索内容互相干扰;
- 不可控:一步错,后面全错,难以恢复。
多 Agent 的价值不是"更智能",而是:
- 把任务拆成可验证的子任务;
- 让每个 Agent 只带自己需要的上下文;
- 在步骤之间做校验、重试、人工介入。
1. 单 Agent 的极限
| 问题 | 表现 | 多 Agent 是否解决 |
|---|---|---|
| 工具过多 | 选错工具/不调用 | 部分解决(按域拆分) |
| 上下文过长 | 忽略关键信息 | 解决(隔离上下文) |
| 步骤不可控 | 一步错步步错 | 解决(工作流/校验) |
| 成本高 | 每步都带全量上下文 | 解决(按需加载) |
| 延迟高 | 串行工具调用 | 部分解决(并行) |
多 Agent 不是银弹;它把"提示词复杂度"换成了"编排复杂度"。
1.1 一个单 Agent 失控的案例
背景:一个客服 Agent 接了 20 个工具(订单、退款、物流、发票、知识库......)。
现象:
- 经常选错工具;
- 一次请求反复调用 5--6 次;
- 上下文被工具 schema 占满;
- 退款工具被误触发。
修复:
- 按域拆成"订单 Agent / 退款 Agent / 知识库 Agent";
- Supervisor 只负责路由;
- 退款 Agent 的高风险工具加审批;
- 每个子 Agent 只带自己的工具。
结果:工具选择更准、上下文更短、权限更清晰。
1.2 什么时候不该上多 Agent
| 场景 | 选择 |
|---|---|
| 步骤固定、可代码化 | 普通代码 |
| 单域、少量工具 | 单 Agent |
| 低延迟要求 | 单 Agent/规则 |
| 没有校验手段 | 先做评估 |
| 团队没有编排经验 | 先从顺序工作流开始 |
多 Agent 是"复杂度工具",不是"能力工具"。
1.3 多 Agent 的收益边界
| 收益 | 何时成立 |
|---|---|
| 质量提升 | 子任务确实需要不同上下文/工具 |
| 可控性 | 步骤可校验/可恢复 |
| 成本下降 | 避免全量上下文重复 |
| 延迟下降 | 子任务可并行 |
如果收益不成立,多 Agent 只是"更贵的单 Agent"。
1.4 多 Agent 的组织隐喻
把多 Agent 当团队:
- 每个 Agent 有职责;
- 有输入/输出契约;
- 有汇报关系;
- 有审批/升级路径;
- 沟通有成本。
团队不是人越多越好,Agent 也是。
1.5 一个判断清单
- 单 Agent 的工具数量 > 10?
- 子任务需要不同上下文?
- 步骤可以独立验证?
- 失败可以重试/补偿?
- 有预算与人工出口?
有任意一项答"否",先不要上多 Agent。
2. Agentic 工作流原语
| 原语 | 用途 | 例子 |
|---|---|---|
| Sequence | 顺序执行 | 检索 → 写作 → 校对 |
| Parallel | 并行执行 | 多专家同时分析 |
| Loop | 循环直到满足条件 | 写作 → 评分 → 重写 |
| Supervisor | 动态路由/汇总 | 主管分派子任务 |
java
// 伪代码:以 1.23.0 的 Agentic API 为准
UntypedAgent pipeline = AgenticServices.sequenceBuilder()
.subAgents(researcher, writer, editor)
.outputKey("final")
.build();
outputKey 把子代理结果放入共享上下文,供后续步骤使用。
2.1 顺序/并行/循环的适用边界
| 原语 | 适合 | 不适合 |
|---|---|---|
| Sequence | 有明确先后依赖 | 可并行的独立子任务 |
| Parallel | 子任务独立、需要汇总 | 有共享写操作 |
| Loop | 质量迭代/重试 | 无终止条件 |
| Supervisor | 动态路由 | 代理过多/描述模糊 |
选择原语前先画依赖图。依赖是数据/控制,不是"感觉"。
2.2 工作流编排的选择树
text
步骤固定? → 是 → 代码/Sequence
否 → 子任务独立? → 是 → Parallel
否 → 需要迭代? → 是 → Loop
否 → 需要动态路由? → 是 → Supervisor
先选最简单的原语,不够再升级。
2.3 Supervisor 的替代方案
| 方案 | 适用 |
|---|---|
| 规则路由 | 意图明确、数量少 |
| Decision Model | 分类/置信度 |
| 固定工作流 | 步骤稳定 |
| Supervisor | 开放任务 |
先试规则/固定工作流,不行再上 Supervisor。
3. 工作流架构
#mermaid-svg-NQY96R4Q11gV7spR{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-NQY96R4Q11gV7spR .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-NQY96R4Q11gV7spR .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-NQY96R4Q11gV7spR .error-icon{fill:#552222;}#mermaid-svg-NQY96R4Q11gV7spR .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-NQY96R4Q11gV7spR .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-NQY96R4Q11gV7spR .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-NQY96R4Q11gV7spR .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-NQY96R4Q11gV7spR .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-NQY96R4Q11gV7spR .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-NQY96R4Q11gV7spR .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-NQY96R4Q11gV7spR .marker{fill:#333333;stroke:#333333;}#mermaid-svg-NQY96R4Q11gV7spR .marker.cross{stroke:#333333;}#mermaid-svg-NQY96R4Q11gV7spR svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-NQY96R4Q11gV7spR p{margin:0;}#mermaid-svg-NQY96R4Q11gV7spR .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-NQY96R4Q11gV7spR .cluster-label text{fill:#333;}#mermaid-svg-NQY96R4Q11gV7spR .cluster-label span{color:#333;}#mermaid-svg-NQY96R4Q11gV7spR .cluster-label span p{background-color:transparent;}#mermaid-svg-NQY96R4Q11gV7spR .label text,#mermaid-svg-NQY96R4Q11gV7spR span{fill:#333;color:#333;}#mermaid-svg-NQY96R4Q11gV7spR .node rect,#mermaid-svg-NQY96R4Q11gV7spR .node circle,#mermaid-svg-NQY96R4Q11gV7spR .node ellipse,#mermaid-svg-NQY96R4Q11gV7spR .node polygon,#mermaid-svg-NQY96R4Q11gV7spR .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-NQY96R4Q11gV7spR .rough-node .label text,#mermaid-svg-NQY96R4Q11gV7spR .node .label text,#mermaid-svg-NQY96R4Q11gV7spR .image-shape .label,#mermaid-svg-NQY96R4Q11gV7spR .icon-shape .label{text-anchor:middle;}#mermaid-svg-NQY96R4Q11gV7spR .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-NQY96R4Q11gV7spR .rough-node .label,#mermaid-svg-NQY96R4Q11gV7spR .node .label,#mermaid-svg-NQY96R4Q11gV7spR .image-shape .label,#mermaid-svg-NQY96R4Q11gV7spR .icon-shape .label{text-align:center;}#mermaid-svg-NQY96R4Q11gV7spR .node.clickable{cursor:pointer;}#mermaid-svg-NQY96R4Q11gV7spR .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-NQY96R4Q11gV7spR .arrowheadPath{fill:#333333;}#mermaid-svg-NQY96R4Q11gV7spR .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-NQY96R4Q11gV7spR .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-NQY96R4Q11gV7spR .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-NQY96R4Q11gV7spR .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-NQY96R4Q11gV7spR .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-NQY96R4Q11gV7spR .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-NQY96R4Q11gV7spR .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-NQY96R4Q11gV7spR .cluster text{fill:#333;}#mermaid-svg-NQY96R4Q11gV7spR .cluster span{color:#333;}#mermaid-svg-NQY96R4Q11gV7spR div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-NQY96R4Q11gV7spR .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-NQY96R4Q11gV7spR rect.text{fill:none;stroke-width:0;}#mermaid-svg-NQY96R4Q11gV7spR .icon-shape,#mermaid-svg-NQY96R4Q11gV7spR .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-NQY96R4Q11gV7spR .icon-shape p,#mermaid-svg-NQY96R4Q11gV7spR .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-NQY96R4Q11gV7spR .icon-shape rect,#mermaid-svg-NQY96R4Q11gV7spR .image-shape rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-NQY96R4Q11gV7spR .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-NQY96R4Q11gV7spR .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-NQY96R4Q11gV7spR :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-NQY96R4Q11gV7spR .client>*{fill:#0E2A33!important;stroke:#22D3EE!important;color:#E8EEF9!important;stroke-width:2px!important;}#mermaid-svg-NQY96R4Q11gV7spR .client span{fill:#0E2A33!important;stroke:#22D3EE!important;color:#E8EEF9!important;stroke-width:2px!important;}#mermaid-svg-NQY96R4Q11gV7spR .client tspan{fill:#E8EEF9!important;}#mermaid-svg-NQY96R4Q11gV7spR .agent>*{fill:#2A1F3D!important;stroke:#A78BFA!important;color:#E8EEF9!important;stroke-width:2px!important;}#mermaid-svg-NQY96R4Q11gV7spR .agent span{fill:#2A1F3D!important;stroke:#A78BFA!important;color:#E8EEF9!important;stroke-width:2px!important;}#mermaid-svg-NQY96R4Q11gV7spR .agent tspan{fill:#E8EEF9!important;}#mermaid-svg-NQY96R4Q11gV7spR .sub>*{fill:#111A2E!important;stroke:#4F8CFF!important;color:#E8EEF9!important;stroke-width:2px!important;}#mermaid-svg-NQY96R4Q11gV7spR .sub span{fill:#111A2E!important;stroke:#4F8CFF!important;color:#E8EEF9!important;stroke-width:2px!important;}#mermaid-svg-NQY96R4Q11gV7spR .sub tspan{fill:#E8EEF9!important;}#mermaid-svg-NQY96R4Q11gV7spR .human>*{fill:#2A1F0B!important;stroke:#F5A524!important;color:#E8EEF9!important;stroke-width:2px!important;}#mermaid-svg-NQY96R4Q11gV7spR .human span{fill:#2A1F0B!important;stroke:#F5A524!important;color:#E8EEF9!important;stroke-width:2px!important;}#mermaid-svg-NQY96R4Q11gV7spR .human tspan{fill:#E8EEF9!important;} 通过
不通过
高风险
用户任务
Supervisor
规划/路由
检索 Agent
写作 Agent
校验 Agent
人工审批
最终输出
图 1:一个典型工作流。Supervisor 规划,子代理执行,校验/人工把关。
3.1 一次工作流的请求生命周期
text
接收任务 → Supervisor 规划 → 子任务 1 → 校验 → 子任务 2 → 校验
→ 汇总 → 人工审批(可选)→ 输出
每个步骤都要:
- 输入/输出结构化;
- 记录状态;
- 可重试;
- 有超时。
工作流不是"把 Agent 串起来",而是"把状态和校验串起来"。
3.2 工作流的上下文传递
| 方式 | 优点 | 风险 |
|---|---|---|
| 共享上下文 | 简单 | 泄漏/膨胀 |
| 显式输出 key | 可控 | 需设计 |
| 只传必要字段 | 最稳 | 需要契约 |
建议:子代理只拿必要上下文,输出用 outputKey 显式传递。
3.3 工作流的输入/输出
输入 envelope:
text
goal, constraints, contextRefs, budget, tenant/user
输出 envelope:
text
status, result, evidence, cost, traceId
结构化输入/输出,才能做校验、重试与审计。
4. 子代理的契约
每个子代理应该:
- 只做一件事;
- 输入/输出结构化;
- 不共享隐式状态;
- 有超时/失败语义;
- 可单独测试。
java
interface Researcher {
@Agent("检索并整理资料,输出要点与来源")
ResearchResult research(@UserMessage String topic);
}
子代理接口越清晰,编排越稳。
4.1 子代理输出契约
java
public record ResearchResult(
List<String> keyPoints,
List<Source> sources,
double confidence) {}
要求:
- 字段少而稳定;
- 必填字段明确;
- 失败用错误码/状态,不抛裸异常;
- 输出可校验(schema);
- 版本化。
子代理输出越结构化,Supervisor 汇总越稳。
4.2 子代理的失败语义
| 结果 | 含义 | 上层处理 |
|---|---|---|
SUCCESS |
完整输出 | 继续 |
PARTIAL |
部分输出 | 补全/降级 |
RETRYABLE |
可重试 | 重试 |
FATAL |
不可恢复 | 终止/人工 |
NEEDS_APPROVAL |
需审批 | 暂停 |
子代理不要只返回"成功/异常",要给上层可决策的语义。
4.3 子代理的版本管理
- 输入/输出 schema 版本化;
- 兼容变更直接发布;
- 不兼容变更新版本;
- 编排层按版本路由;
- 灰度切换。
子代理升级不应悄悄改变上层契约。
5. Supervisor 模式
Supervisor 负责:
- 拆解任务;
- 选择子代理;
- 汇总结果;
- 处理冲突;
- 决定是否人工介入。
风险:
- Supervisor 自己也是模型,可能规划错;
- 路由错误会导致后续全错;
- 汇总可能丢信息。
对策:
- 给 Supervisor 明确的工具/子代理清单;
- 限制可选代理数量;
- 关键步骤加确定性校验;
- 记录规划轨迹,便于复盘。
5.1 Supervisor 的路由策略
| 策略 | 优点 | 缺点 |
|---|---|---|
| 规则路由 | 确定、快 | 不灵活 |
| Decision Model | 便宜、带置信度 | 需要训练/配置 |
| LLM 规划 | 灵活 | 贵、可能错 |
| 混合 | 平衡 | 复杂 |
建议:能用规则/Decision Model 就不用 LLM 规划;LLM 只处理真正开放的任务。
5.2 冲突处理
| 冲突 | 策略 |
|---|---|
| 子代理结论矛盾 | 保留双方+置信度,交人工/校验 |
| 数据版本不一致 | 按版本/时间取最新 |
| 权限冲突 | 取更严格权限 |
| 输出格式不一致 | 统一 schema/转换 |
Supervisor 不要"强行合并"冲突;要让冲突可见。
5.3 Supervisor 的提示词
text
你是任务主管。可用子代理:
- researcher:检索资料
- writer:写作
- reviewer:校验
规则:最多 3 步;不确定时请求人工;输出 JSON 计划。
提示词要写清"可用代理、边界、输出格式、终止条件"。
6. 状态与失败恢复
| 状态 | 存储 | 用途 |
|---|---|---|
| 任务计划 | 数据库 | 恢复/审计 |
| 子任务结果 | 数据库/对象存储 | 重试/汇总 |
| 工具调用 | 日志 | 幂等/审计 |
| 人工审批 | 工单系统 | 合规 |
失败恢复:
text
步骤失败 → 重试(幂等)→ 降级 → 人工介入
不要把状态只放在内存/模型上下文里。
6.1 工作流状态机
| 状态 | 含义 | 下一步 |
|---|---|---|
PENDING |
等待执行 | 运行 |
RUNNING |
子任务执行中 | 完成/失败 |
WAITING_APPROVAL |
等待人工 | 通过/拒绝 |
FAILED |
失败 | 重试/降级 |
DONE |
完成 | 输出 |
状态要持久化,不能只存在内存/上下文。否则进程重启就丢。
6.2 重试与补偿
- 只重试幂等步骤;
- 写操作要有补偿/回滚;
- 重试带退避与上限;
- 记录每次尝试;
- 超过上限转人工。
多步写操作要考虑 Saga/补偿,不要假设"重试一定成功"。
6.3 持久化设计
| 表/存储 | 内容 |
|---|---|
| workflow | 任务/状态/版本 |
| step | 子任务/结果/耗时 |
| approval | 审批/人/时间 |
| event | 状态变更日志 |
用乐观锁/版本号防并发;用 outbox 保证状态与消息一致。
7. Human-in-the-loop
需要人工介入的场景:
- 高风险写操作;
- 低置信度决策;
- 合规/审批;
- 冲突无法消解。
设计要点:
- 明确"暂停/恢复"协议;
- 人工输入结构化;
- 记录谁在何时改了什么;
- 超时自动降级。
HITL 不是"加个确认框",而是工作流的一部分。
7.1 HITL 的暂停/恢复协议
text
工作流暂停 → 生成审批任务(结构化)→ 人工处理 → 恢复/终止
要求:
- 审批任务包含上下文/风险/建议;
- 人工输入结构化(通过/拒绝/修改);
- 超时自动降级;
- 恢复时校验状态版本,防止并发冲突。
HITL 的关键是"可恢复",不是"弹窗"。
7.2 HITL 的权限
- 审批人要有对应权限;
- 不能自批;
- 高风险双人;
- 审批记录不可篡改;
- 超时自动拒绝/降级。
HITL 不是"找个同事点一下",而是受控流程。
8. 成本与延迟
| 模式 | 成本 | 延迟 | 适用 |
|---|---|---|---|
| 单 Agent | 低 | 低 | 简单任务 |
| Sequence | 中 | 中 | 多步骤 |
| Parallel | 高 | 低 | 多专家 |
| Loop | 高 | 高 | 质量迭代 |
| Supervisor | 高 | 高 | 动态任务 |
多 Agent 通常更贵、更慢。只有在"质量/可控性"收益足够时才用。
8.1 成本预算与终止
| 预算 | 控制 |
|---|---|
| 总 Token | 单任务上限 |
| 单步 Token | 子任务上限 |
| 轮次 | 最大循环次数 |
| 时间 | 端到端超时 |
| 工具调用 | 最大次数 |
text
超过任一预算 → 停止 → 返回部分结果/人工介入
没有预算的多 Agent,就是"自动烧钱机"。
8.2 并行与汇总的坑
| 坑 | 表现 | 修复 |
|---|---|---|
| 结果冲突 | 多个子代理结论矛盾 | 显式冲突处理 |
| 顺序依赖 | 并行结果互相依赖 | 改回顺序 |
| 汇总丢信息 | Supervisor 只取一个 | 结构化汇总 |
| 重复计算 | 子任务重叠 | 去重/分工 |
并行不是"同时跑就快",要先保证子任务独立。
8.3 成本模型
text
总成本 = Σ(每步子代理输入 Token + 输出 Token) × 单价
+ Supervisor 规划/汇总成本
控制点:
- 子代理只带必要上下文;
- Supervisor 不重复读全量;
- 并行步骤限制并发;
- 循环有上限。
多 Agent 的成本要按"步骤"拆,不要只看总数。
8.4 延迟优化
| 方法 | 效果 |
|---|---|
| 并行独立子任务 | 降低总时长 |
| 缓存中间结果 | 减少重复 |
| 小模型做路由 | 快 |
| 流式输出 | 感知快 |
| 减少轮次 | 最有效 |
多 Agent 的延迟通常来自串行步骤与模型调用,不是编排框架。
9. 反模式
- 为多 Agent 而多 Agent:任务本来几步代码就能完成;
- 共享全局上下文:等于单 Agent,还更贵;
- 没有校验:错误在步骤间传播;
- 没有超时/预算:循环烧钱;
- 没有人工出口:高风险操作无人把关。
9.1 一个多 Agent 失败案例
背景:团队做了一个"写作工作流":研究 → 写作 → 校对。
问题:
- 子代理输出是自由文本,校对无法稳定解析;
- 没有校验步骤,错误一路传到最后;
- 没有预算,校对循环了 8 次。
修复:
- 研究输出结构化(要点+来源);
- 写作输出 JSON(正文+引用);
- 校对加 schema 校验;
- 最多 3 轮,超限人工介入。
多 Agent 的稳定性来自契约与校验,不是"更多模型"。
9.2 一个 Loop 失控案例
现象:写作 Agent 的"评分→重写"循环跑了十几次,成本失控。
根因:
- 没有最大轮次;
- 评分标准模糊,永远"不够好";
- 没有预算。
修复:
- 最多 3 轮;
- 评分 rubric 明确;
- 超预算转人工。
Loop 必须有终止条件,否则就是烧钱。
10. 常见失败模式
| 现象 | 根因 | 修复 |
|---|---|---|
| 越跑越贵 | 循环/上下文膨胀 | 预算/终止 |
| 结果丢步骤 | 共享状态混乱 | 结构化状态 |
| Supervisor 乱路由 | 代理太多/描述不清 | 限制+清晰契约 |
| 无法恢复 | 状态只在内存 | 持久化 |
| 人工介入卡住 | 无超时 | 自动降级 |
10.1 工作流可观测性
| 指标 | 用途 |
|---|---|
| 每步耗时/Token | 找瓶颈 |
| 每步失败率 | 找脆弱点 |
| 循环次数 | 找失控 |
| 人工介入率 | 找低效 |
| 最终成功率 | 看效果 |
工作流的 Trace 要能展开到"每个子代理/每次工具调用"。
10.2 工作流测试
| 层 | 测什么 |
|---|---|
| 子代理单测 | 输入/输出契约 |
| 编排契约 | 顺序/并行/路由 |
| 故障注入 | 超时/失败/恢复 |
| 端到端 | 少量真实场景 |
用 Mock 子代理测编排,用真实模型测质量。
10.3 一个 Supervisor 路由错误案例
现象:用户问"怎么退款",Supervisor 直接路由到退款执行 Agent,触发了真实退款。
根因:
- 退款 Agent 同时包含"政策问答"和"执行退款";
- Supervisor 没有区分"咨询/执行";
- 写工具没有审批。
修复:
- 拆分"政策 Agent"和"退款执行 Agent";
- 执行类意图必须审批;
- 路由增加"只读/写"标签。
路由错误 + 权限缺失 = 生产事故。
10.4 工作流的回滚
- 工作流版本化;
- 新版本先灰度;
- 回滚时兼容已持久化的状态;
- 记录版本与迁移。
回滚不是"重发旧代码",要考虑状态兼容。
10.5 一个 HITL 超时案例
现象 :审批人休假,工作流卡在 WAITING_APPROVAL 三天。
根因:没有审批超时与兜底。
修复:
- 审批超时自动升级/拒绝;
- 通知催办;
- 超时后走降级路径;
- 记录 SLA。
HITL 也要有超时,否则工作流会被人工卡死。
11. FAQ
多 Agent 一定比单 Agent 好吗?
不一定。任务简单时,单 Agent + 工具更便宜、更稳。
子代理之间怎么共享数据?
通过结构化输出 + 显式状态,不要靠隐式上下文。
Supervisor 用大模型还是规则?
关键路由可以用规则/Decision Model;复杂规划再用大模型。
怎么控制成本?
每步预算、最大轮次、上下文裁剪、按需加载。
怎么测试工作流?
子代理单测 + 编排契约测试 + 端到端少量场景。
11.1 上多 Agent 前的四个问题
- 单 Agent 真的做不了吗?
- 子任务能独立验证吗?
- 失败能恢复吗?
- 成本/延迟可接受吗?
四个都"是",再上多 Agent。
12. 上线检查清单
- 任务真的需要多 Agent;
- 子代理职责单一;
- 输入/输出结构化;
- 状态持久化;
- 每步超时/预算;
- 失败恢复路径;
- 高风险人工介入;
- 规划轨迹可审计;
- 成本/延迟可观测。
12.1 最小可行工作流
从两步开始:
text
检索 Agent → 写作 Agent
加校验、预算、日志;跑通后再加 Supervisor/并行/人工。
不要第一天就设计 6 个 Agent 的复杂编排。
12.2 工作流上线的第一周
- 每天看步骤失败率与成本;
- 抽查人工介入样本;
- 调整预算/重试;
- 记录失败模式;
- 第二周再考虑加 Agent。
第一周的目标是"稳定",不是"更智能"。
12.3 工作流的 SLA
| 环节 | SLA | 超时行为 |
|---|---|---|
| 单步 | 按工具 | 重试/降级 |
| 审批 | 按业务 | 升级/拒绝 |
| 总任务 | 按场景 | 返回部分/人工 |
SLA 要写进流程与监控,不要靠人盯。没有 SLA 的工作流,迟早会卡住。监控与告警也要跟上,否则只是纸面承诺,请重视,这是生产底线,这关乎整体系统稳定性,绝不可忽视,切记。
13. 系列导航
- 上一篇:A16《MCP 实战:Streamable HTTP、工具治理与 Java 服务端》
- 下一篇:A18《Decision Model 与 Confidence Cascade:1/10 成本做路由》
- 全系列:《LangChain4j 生产级实战》20 篇路线图(专栏内查看)