《Agentic Design Patterns》第 2 章导读:路由(Routing)
本文是对开源书籍《Agentic Design Patterns》第 2 章的解读与导读,内容忠实呈现原文,并附个人思考。
原书在线阅读:https://adp.xindoo.xyz/ | 翻译项目代码仓库:https://github.com/xindoo/agentic-design-patterns
上一篇我们聊了第 1 章的提示词链------它解决的是"线性、有依赖"的确定性任务流。但现实世界远没有那么规整:智能体经常会遇到**需要"看情况决定下一步怎么做"**的场景。用户问的问题五花八门,有时是查订单、有时问产品、有时要技术支援、有时干脆没说清楚------这些根本没法用一条固定的流水线走到底。
这正是第 2 章**路由(Routing)**模式要解决的问题:让智能体能根据输入内容和当前状态,动态决定把流程引向哪个专门工具、函数或子流程。
一、什么是路由:从"固定路径"到"动态仲裁"
路由把条件逻辑 引入智能体的运行框架,让系统从"固定的执行路径"变成"动态评估标准、从一组可能动作中做选择"。它让系统变得更灵活、更有上下文感知能力。
书里用一个客服智能体的例子讲得很清楚:带路由能力的智能体拿到用户查询后,会先对查询分类、判断意图,然后据此分流:
- 分析用户的查询;
- 基于其意图 路由查询:
- 意图是"检查订单状态" → 路由到与订单数据库交互的子智能体或工具链;
- 意图是"产品信息" → 路由到搜索产品目录的子智能体或链条;
- 意图是"技术支持" → 路由到访问故障排除指南的链条,或升级到人工;
- 意图不清楚 → 路由到澄清子智能体或提示词链。
你看,这里没有"一刀切"的回复路径,而是像路由器一样,把不同的请求分发给不同的"出口"。
二、路由的四条实现思路
路由模式的核心组件是"做评估、指方向"的那套机制。书中给出了四种主流实现方式,各有取舍:
| 实现方式 | 原理 | 特点 |
|---|---|---|
| 基于 LLM 的路由 | 让语言模型分析输入,输出一个指示目的地的标识符(如"订单状态/产品信息/技术支持/其他") | 灵活、能理解复杂语义;有推理成本 |
| 基于嵌入的路由 | 把输入转成向量嵌入,与各路由的嵌入比较相似度,路由到最相似的那个 | 适合"语义路由",决策依据是含义而非关键词 |
| 基于规则的路由 | 用关键词、模式、结构化数据配合 if-else / switch 判断 | 快、确定性高;但对细微或新颖输入缺乏灵活性 |
| 基于机器学习模型的路由 | 训练一个判别式分类器,把路由逻辑编码进模型权重 | 是监督微调出来的专门组件;注意它与"基于 LLM 的路由"不同------它不在推理时跑提示词 |
这里有个容易混淆的点值得留意:基于 ML 模型的路由 和 基于 LLM 的路由 不是一回事。前者是微调出来的一个判别分类器,路由逻辑固化在权重里;后者是推理时用生成式模型跑提示词来输出决策。虽然可以从 LLM 生成合成数据来增强前者的训练集,但两者的"决策主体"完全不同。
另外,路由机制并不是只能放在最前面。书里强调:它可以在操作周期的多个节点 实现------可以在开始 给主任务分类、可以在处理链中间 决定后续动作、也可以在子程序期间从一组工具里挑选最合适的一个。
三、应用场景
- 人机交互(虚拟助手、AI 导师):先解析自然语言意图,决定是调信息检索工具、升级到人工、还是切换到课程下一个模块------突破线性对话,做上下文响应。
- 自动化数据/文档管道:把邮件、支持工单、API 载荷按内容/元数据/格式分类,分发到销售线索、数据转换、升级等不同工作流。
- 多工具/多智能体系统:充当"高级调度器"。比如一个由搜索、总结、分析等不同智能体组成的研究系统,用路由器按当前目标分派任务;AI 编码助手也用路由来识别编程语言和意图(调试/解释/翻译),再把代码片段交给对的工具。
一句话总结它的作用:路由把智能体从"预定义序列的静态执行器",升级成"能在变化条件下决策最有效方式"的动态系统。
四、代码实战一:用 LangChain(LangGraph 风格)实现路由
书中给出两种实现。第一种用 LangChain 的 RunnableBranch,搭建一个"协调器 + 三个模拟子智能体"的结构,按意图(booker / info / unclear)分发请求。
bash
pip install langchain langgraph google-cloud-aiplatform langchain-google-genai google-adk deprecated pydantic
python
## Copyright (c) 2025 Marco Fago
## 此代码根据 MIT 许可证授权。
from langchain_google_genai import ChatGoogleGenerativeAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough, RunnableBranch
llm = ChatGoogleGenerativeAI(model="gemini-2.5-flash", temperature=0)
## --- 定义模拟子智能体处理程序 ---
def booking_handler(request: str) -> str:
return f"预订处理程序处理了请求:'{request}'。结果:模拟预订操作。"
def info_handler(request: str) -> str:
return f"信息处理程序处理了请求:'{request}'。结果:模拟信息检索。"
def unclear_handler(request: str) -> str:
return f"协调器无法委托请求:'{request}'。请澄清。"
## --- 定义协调器路由链(判断委托给谁)---
coordinator_router_prompt = ChatPromptTemplate.from_messages([
("system", """分析用户的请求并确定哪个专家处理程序应处理它。
- 如果请求与预订航班或酒店相关,输出 'booker'。
- 对于所有其他一般信息问题,输出 'info'。
- 如果请求不清楚或不适合任一类别,输出 'unclear'。
只输出一个词:'booker'、'info' 或 'unclear'。"""),
("user", "{request}")
])
coordinator_router_chain = coordinator_router_prompt | llm | StrOutputParser()
## --- 定义委托逻辑 ---
branches = {
"booker": RunnablePassthrough.assign(output=lambda x: booking_handler(x['request']['request'])),
"info": RunnablePassthrough.assign(output=lambda x: info_handler(x['request']['request'])),
"unclear": RunnablePassthrough.assign(output=lambda x: unclear_handler(x['request']['request'])),
}
delegation_branch = RunnableBranch(
(lambda x: x['decision'].strip() == 'booker', branches["booker"]),
(lambda x: x['decision'].strip() == 'info', branches["info"]),
branches["unclear"] # 默认分支
)
coordinator_agent = {
"decision": coordinator_router_chain,
"request": RunnablePassthrough()
} | delegation_branch | (lambda x: x['output'])
## --- 示例用法 ---
def main():
print("--- 运行预订请求 ---")
print(coordinator_agent.invoke({"request": "给我预订去伦敦的航班。"}))
print("\n--- 运行信息请求 ---")
print(coordinator_agent.invoke({"request": "意大利的首都是什么?"}))
print("\n--- 运行不清楚的请求 ---")
print(coordinator_agent.invoke({"request": "告诉我关于量子物理学的事。"}))
main()
这套代码的逻辑 :coordinator_router_chain 先用提示词让 LLM 把请求分类成 booker / info / unclear 三者之一;RunnableBranch 拿到 LLM 的"决策"后,把原始请求交给对应的 handler。整个 coordinator_agent = 先路由出决策 → 再把请求分发给选中的处理程序 → 抽出最终输出。它模仿了多智能体框架里"中央协调器按意图把任务委托给专门智能体"的基本模式。
五、代码实战二:用 Google ADK 实现
第二种实现走的是 Google 智能体开发工具包(ADK) 的路子。ADK 的哲学和显式计算图不太一样:路由通常通过定义一组离散的 "工具" 来实现,选择哪个工具由框架内部逻辑用底层模型去匹配。
python
from google.adk.agents import Agent
from google.adk.runners import InMemoryRunner
from google.adk.tools import FunctionTool
def booking_handler(request: str) -> str:
return f"已模拟对 '{request}' 的预订操作。"
def info_handler(request: str) -> str:
return f"对 '{request}' 的信息请求。结果:模拟信息检索。"
booking_tool = FunctionTool(booking_handler)
info_tool = FunctionTool(info_handler)
booking_agent = Agent(
name="Booker", model="gemini-2.0-flash",
description="处理所有航班和酒店预订请求。", tools=[booking_tool]
)
info_agent = Agent(
name="Info", model="gemini-2.0-flash",
description="提供一般信息并回答用户问题。", tools=[info_tool]
)
coordinator = Agent(
name="Coordinator", model="gemini-2.0-flash",
instruction=( # 定义委托指令
"你是主协调器。你唯一的任务是分析传入的用户请求"
"并将它们委托给适当的专家智能体。不要尝试直接回答用户。\n"
"- 对于任何与预订相关的请求,委托给 'Booker' 智能体。\n"
"- 对于所有其他一般信息问题,委托给 'Info' 智能体。"
),
sub_agents=[booking_agent, info_agent] # 子智能体的存在默认启用 LLM 驱动的自动流
)
runner = InMemoryRunner(coordinator)
# 然后通过 runner.run(...) 处理用户的预订/信息请求并提取最终响应
关键区别在于:ADK 里定义 sub_agents 后,委托自动由"自动流"机制驱动,不需要像 LangChain 那样手写分支逻辑。这种"开箱即用"的委托对明确定义了离散操作集的系统更简单,而 LangGraph 的图结构则更适合路由逻辑本身就很复杂的场景。
六、速览
- 问题背景:智能体要频繁响应各种输入和情况,单一线性流程应付不来。没有"选择正确工具/子流程"的机制,系统就僵化、无自适应能力。
- 解决方案:通过把条件逻辑引入运行框架,让系统先分析查询意图,再动态把控制流导向最合适的专门工具/函数/子智能体;决策可由 LLM、预定义规则或嵌入相似性驱动。
- 实践建议 :当智能体必须根据用户输入或当前状态、在多个不同工作流/工具/子智能体之间做决策时使用路由模式。典型如客服机器人区分销售、技术支持与账户管理问题。
可视化总结

图 1:路由模式------使用 LLM 作为路由器,把输入分派给不同的专门处理流程。
关键要点
- 路由让智能体能根据条件动态决定工作流的下一步;
- 它突破线性执行,让系统能处理多样输入并自适应调整行为;
- 路由逻辑可用 LLM、规则系统或嵌入相似度实现;
- LangGraph、Google ADK 等框架用不同架构为路由提供了结构化实现方式。
结语与个人思考
如果说提示词链解决的是"怎么把一件事按顺序做好 ",那么路由解决的就是"面对一件不确定的事,该先往哪条路走 "。两者通常会在一个真实系统里配合使用:先路由定方向,再用链条把选定的子流程做扎实。整套书的主线其实就是这样一层层叠加的------单看每个模式都不复杂,难的是把它们合理地编排进一个系统。
值得留意的工程取舍:
- LLM 路由 vs 规则路由:规则路由快且确定性强,但碰到没学过的说法就抓瞎;LLM 路由灵活但每多一次推理就多一份延迟与成本。实践中常做成"规则兜底 + LLM 兜语义"的组合。
- 注意"路由外溢" :LLM 是概率模型,分类偶尔会飘。工程上要给"分类不确定"留后路(比如
unclear分支、重试、置信度阈值),这正是书里那个"如果意图不清楚→路由到澄清子智能体"的用意。
下一步建议阅读第 3 章 并行化(Parallelization)------当多个子任务互不依赖时,如何让它们同时跑以提升性能,和路由/链条形成完整的工作流三件套。
本文基于开源书籍《Agentic Design Patterns》(https://github.com/xindoo/agentic-design-patterns ,在线阅读 https://adp.xindoo.xyz/ )整理,供学习交流,版权归原作者所有。