1674 字
约 5 分钟
0
给 Agent 装个"总机":策略调度器让多种 Agent 各司其职

给 Agent 装个"总机":策略调度器让多种 Agent 各司其职

AutoAgent 会自己打磨,FlowAgent 会先规划再干,FixedAgent 按固定流程走……项目里 Agent 多了,怎么让它们各干各的活,还不改主代码?

一、一个现实问题:Agent 不止一种

做了两个 Agent 之后,你会发现一个很自然的诉求:

  • AutoAgent:适合"结果要反复打磨"的任务(分析→执行→质检→回炉)
  • FlowAgent:适合"流程明确"的任务(盘工具→规划→拆步→执行)
  • 后来还可能有 FixedAgent(固定流水线)、XXAgent……

这时候最粗暴的写法是:

if ("auto".equals(type)) {
    autoAgent.execute(...);
} else if ("flow".equals(type)) {
    flowAgent.execute(...);
} else if ("fixed".equals(type)) {
    fixedAgent.execute(...);
} else {
    throw new RuntimeException("不认识的类型");
}

能跑,但每次加一种 Agent 都要改这段代码。改多了就变成一坨没人敢动的 if-else。

那怎么设计,才能做到"加新 Agent 不改主代码"?

二、答案:一个"不聪明"的总机

思路其实特别朴素——加一个调度器(Router),它不做任何智能决策,只做一件事:查表转发。

用户请求(带了 agentId)
   │
   ▼
总机(调度器)
   ├─ 查数据库:这个 agentId 的"工种标签"是什么?
   ├─ 用标签去 Map 里找同名对象
   └─ 找到谁,就把活派给谁

为什么说它"不聪明"?因为它整个逻辑就三步,不思考、不调模型、不做业务判断——它只是个"查表转发的接线员"。

三、总机怎么知道派给谁:两层对暗号

总机"知道"的关键,是数据库写一个名字,代码挂一个同名牌子,两边对得上:

第一层:数据库里每个 Agent 档案上写着归属

ai_agent 表加一列 strategy由配置的人决定每个 Agent 属于哪个工种:

智能体4(查日志)→ strategy = "autoAgentExecuteStrategy"
智能体1(发文章)→ strategy = "flowAgentExecuteStrategy"
智能体6(固定活)→ strategy = "fixedAgentExecuteStrategy"

这个字段是配置,不是代码——所以"哪个 Agent 走哪条路",改数据库就行,不用动代码。

第二层:代码里每个策略门口挂着同名牌子

每个策略类通过注解注册自己的名字:

@Service("autoAgentExecuteStrategy")  → AutoAgentExecuteStrategy
@Service("flowAgentExecuteStrategy") → FlowAgentExecuteStrategy
@Service("fixedAgentExecuteStrategy")→ FixedAgentExecuteStrategy

Spring 启动时,把所有实现 IExecuteStrategy 接口的类收集成一个 Map,key 就是注解名:

executeStrategyMap = {
    "autoAgentExecuteStrategy"  → AutoAgentExecuteStrategy对象,
    "flowAgentExecuteStrategy"  → FlowAgentExecuteStrategy对象,
    "fixedAgentExecuteStrategy" → FixedAgentExecuteStrategy对象,
}

总机干活:拿档案上的名字,对 Map 里的牌子

// ① 查档案
String strategy = repository.queryAiAgentByAgentId(agentId).getStrategy();
// "autoAgentExecuteStrategy"

// ② 对暗号:用名字去 Map 取对象
IExecuteStrategy executeStrategy = executeStrategyMap.get(strategy);

// ③ 找不到就报错,找到就派活
if (executeStrategy == null) throw new BizException("不存在的策略:" + strategy);
executeStrategy.execute(request, emitter);

总机从头到尾只做字符串查表。 它不懂业务,不懂 Auto 和 Flow 的区别,它只是对名字。

四、为什么这个设计好:加新策略不改主代码

这是这套设计最值钱的地方——开闭原则

  • 加一种新 Agent(比如 FixedAgent)→ 写一个新类,@Service("fixedAgentExecuteStrategy") 注解一下
  • Spring 自动把它收进 Map
  • 总机一行不用改,因为它是从数据库读名字、从 Map 取对象

对比一下:

if-else 版:加新策略 → 改主代码 → 重新发版 → 可能改崩别人
调度器版:加新策略 → 写个新类 → 数据库配一行 → 完事

调度器版的好处还不止加策略:同一个 Agent 想换策略,改数据库字段就行(比如智能体1 从 flow 改成 auto,一行 update);多个 Agent 复用同一策略,也是配置说了算。

五、一个重要澄清:总机不是"主 Agent"

很多人一听"调度器"会以为:是不是有个"主 Agent"在操控其他 Agent?

不是。 这是两种完全不同的架构哲学:

路由分发(本文) Orchestrator 编排
入口 无智能,纯查表转发 有智能,会思考派谁
决策依据 数据库配置(strategy 字段) 主 Agent 现场判断
关系 各策略平级,总机不操控 主 Agent 派活给子 Agent
适合 策略事先可分、类型明确 任务需要动态编排

本项目的调度器属于路由分发:它不聪明,聪明的是"配置"——把"智能体4走 Auto"这件事提前写死在数据库里,总机只是执行这个决定。

六、也别忽略边界

作为学习沉淀,照例泼冷水:

  • 策略名要精确匹配:数据库写的名字和注解名差一个字符就找不到,会抛"不存在的策略"。生产上可以加"启动时校验所有 agent 的 strategy 都能在 Map 找到"。
  • Map 是静态注册的:策略列表在启动时就固定了,运行时不能热插拔(热插拔需要动态类加载或插件机制)。
  • 调度器不做兜底:策略执行失败了,总机只负责把异常抛出去,不做降级或换策略重试(这些要策略内部或外面再包一层)。
  • 真正的决策在配置:调度器把"智能"外包给了数据库,那"配错了"就是事故——配置要有校验和管理界面。

七、总结

三句话收尾:

  1. Agent 多了之后,需要一个"总机"统一入口——它不做智能决策,只做查表转发。
  2. 两暗号机制:数据库的 strategy 字段(配置决定归属)+ 注解名注册的 Map(代码提供对象),字符串对上就派活,加新策略不用改总机。
  3. 调度器不是主 Agent——它是路由分发,不是 Orchestrator 编排;聪明在配置,不在调度器。

至此,Agent 设计三部曲完成:

  1. 《让 AI 学会"自己干活、自己检查、自己改"》——一个 Agent 怎么自我闭环(多角色)
  2. 《让 AI 学会"先写计划再干活"》——Agent 的两种执行哲学(动态循环 vs 规划执行)
  3. 《给 Agent 装个"总机"》——多种 Agent 怎么组织调度(路由分发)

从"一个 Agent 内部怎么设计"到"多个 Agent 外部怎么组织",这条 Agent 架构的学习路径就算闭环了。

给 Agent 装个"总机":策略调度器让多种 Agent 各司其职
http://www.clxhxhhr.top/posts/619/
作者
clxstart
发布于
2026-09-15
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。