48 条件分支:构建可解释的 Agent 路由
条件分支:构建可解释的 Agent 路由
条件分支决定 Agent 下一步去哪里。可靠路由必须基于有限状态和业务规则,而不是完全相信模型一句话。
[TOC]
1. 先把 Agent 想清楚
很多人一听到 Agent,就会想到“让大模型自己决定下一步”。这个理解只对了一半。
在真实项目里,Agent 更像是一个被工程规则约束住的任务执行器:
模型负责理解自然语言、提出候选动作
代码负责权限校验、状态流转、工具执行
业务接口负责最终事实和写操作
日志审计负责事后追踪
模型说下一步是 create_ticket,不代表现在就能创建。还要看字段是否完整、权限是否通过、用户是否确认。
所以这一阶段的博客不要写成“模型越来越聪明”。更准确的写法是:我们正在学习如何把模型的灵活性放进一个可控的工作流里。
2. 一个业务场景
用户说“帮我处理这个坏掉的订单”。路由可能先查订单,缺订单号就澄清;订单已过售后期就解释政策;状态允许才进入工单预览。
这个场景里面最重要的不是模型能不能说出一段好听的话,而是:
它选了哪个工具
为什么能调用这个工具
参数从哪里来
权限在哪里校验
失败后状态怎么变
用户确认前会不会产生真实写入
把这些问题问清楚,Agent 项目才不会变成一个不可解释的聊天黑盒。
这一节的关键是:路由必须可枚举。
判断顺序可以这样写:
1. 先定义允许的路由结果,例如 KNOWLEDGE、ORDER、TICKET、HUMAN、END
2. 模型可以判断意图,但只能返回这些枚举值
3. 低置信度、缺参数、权限不足和高风险动作要进入固定分支
4. 路由结果要记录原因,方便排查为什么调用了某个工具
5. 最后用容易混淆的话术测试路由是否稳定
它解决的是分支失控问题:让模型参与判断,但不允许它自由发明系统路径。
3. 核心概念
1. 路由枚举
路由函数只返回预定义节点名或终止状态。
这一点在项目里要落到具体规则:路由结果要有限。
2. 业务规则优先
权限、确认、字段完整性、最大步数由代码判断。
这一点在项目里要落到具体规则:高风险判断用代码。
3. 澄清分支
缺少关键字段时不要猜,要问用户补充。
这一点在项目里要落到具体规则:不确定先问。
4. 失败分支
超时、权限失败、工具异常要进入明确失败或转人工。
这一点在项目里要落到具体规则:失败也要有路。
4. 整体流程
graph TD;
A["读取 State"] --> B["检查终止条件"];
B["检查终止条件"] --> C["检查错误状态"];
C["检查错误状态"] --> D["检查缺字段"];
D["检查缺字段"] --> E["按意图选择节点"];
E["按意图选择节点"] --> F["执行节点"];
F["执行节点"] --> G["再次路由"];
这张图里,模型只是其中一个节点。工具、状态、权限、确认和审计同样重要。
如果一个 Agent 图里只有“用户 -> 模型 -> 答案”,那它还只是 Chat,不是能进入业务系统的 Agent。
5. 落地步骤
1. 定义路由优先级
例如最大步数、不可恢复错误、等待确认、缺字段、正常意图。
完成后应该能看到:路由规则表。
2. 记录路由原因
每次路由保存原因、输入摘要和置信度。
完成后应该能看到:routeDecision 日志。
3. 覆盖兜底状态
未知意图、低置信度、达到预算都要有处理方式。
完成后应该能看到:兜底分支。
4. 测试每条边
每条条件边至少一个测试样本。
完成后应该能看到:路由测试集。
6. 状态、接口或工具字段
| 项目 | 说明 |
|---|---|
| route | 目标节点 |
| condition | 进入条件 |
| reason | 路由原因 |
| priority | 优先级 |
| fallback | 失败兜底 |
字段设计要尽量结构化。不要让下游通过一段自然语言去猜“成功了没有”“下一步要干什么”。
7. 示例
路由优先级
1. stepCount 超限 -> failed2. 存在不可恢复错误 -> handoff3. waiting_confirmation -> pause
4. 缺少必填字段 -> clarify5. intent=ORDER_QUERY -> order_query
6. intent=CREATE_TICKET -> ticket_preview
7. 其他 -> knowledge_search
示例里的字段不一定照搬,但思想要保留:输入、状态、输出、错误和审计信息要分开。
8. 哪些事不能交给模型自由发挥
不能让模型输出任意节点名称后直接执行。模型可以输出意图,路由函数必须把它映射到允许节点。
这一节特别重要。Agent 项目最容易踩坑的地方,就是把“理解意图”和“执行业务动作”混成一件事。
模型可以建议动作,但最终执行必须经过代码和业务系统的规则。
9. 测试路径
建议至少准备下面几类测试:
正常路径:输入完整,工具正常返回
缺字段路径:订单号、联系方式、问题描述不完整
权限路径:查询别人的订单、访问无权知识库
失败路径:工具超时、模型输出非法、检索为空
恢复路径:等待确认时服务重启、重复确认、超时确认
Agent 的测试不能只看最终回答。你要检查状态、工具调用、审计日志和是否产生真实副作用。
10. 工程取舍
- 规则路由稳定,但对复杂语言不够灵活。
- 模型路由灵活,但需要置信度和兜底。
- 混合路由更适合生产。
取舍讲清楚以后,读者才能知道你为什么这样设计,而不是以为所有问题都要上 Agent。
11. 常见坑
- 失败后又回到同一节点无限循环。
- 缺字段时模型自己编字段。
- 没有拒绝确认后的终止路径。
- 路由日志没有记录原因。
这些坑本质上都和一个问题有关:没有把模型输出当成“不可信的候选结果”。
12. 验收清单
- ☐ 路由结果是有限枚举
- ☐ 每条分支有测试
- ☐ 未知状态有兜底
- ☐ 最大步数限制生效
- ☐ 路由原因可审计
如果这些检查项没过,先不要急着加更多工具。工具越多,边界越乱,排查越难。
13. 落地清单
- ☐ 写一套路由优先级
- ☐ 为 6 条边准备测试输入
- ☐ 设计低置信度澄清分支
- ☐ 记录一次路由决策日志
练习时可以先用 Mock,不要一开始就连真实订单或工单系统。等状态、权限和幂等设计清楚后,再接真实接口。
14. 小结
路由是 Agent 的交通规则。没有规则,模型越灵活,系统越容易跑偏。
Agent 的价值来自灵活性,但安全来自边界。能把这两件事同时讲清楚,才算真正理解 Agent 工程化。