从0搭AI Agent(六):什么时候该把任务拆给多个 Agent

第 1 篇(为什么不是调一次 API)里我列过本系列大纲,说好要讲「多智能体编排」。前面 5 篇把单 Agent 的循环、LangGraph 编排、SSE 流式、生产级运行时讲完了,这一篇补上最后一块:什么时候不该用「一个大 Agent 包打天下」。

以下代码均来自玄镜(OracleMind)真实源码:oraclemind-ai/src/agent/home_agent.py、harness/boundary/langgraph_nodes.py。示例省略导入与模型初始化;create_react_agent 的参数名(system_prompt / prompt / state_modifier)以你当前 LangChain / LangGraph 依赖版本为准。

一、单 Agent 的「撑死」临界点

玄镜的 home_agent 是首页通用入口:负责闲聊 / 通用问答,必要时调排盘工具。最初它就是用 LangGraph 的 ReAct 把几个工具挂上去:

ini 复制代码
# 早期示意:实际工具数后来涨到十几个
tools = [bazi_paipan, ziwei_paipan, name_generate, name_detail]
agent = create_react_agent(
    model=model,
    tools=tools,
    system_prompt=HOME_AGENT_SYSTEM_PROMPT,
)

看起来很优雅------一个 Agent 通过 ReAct 自己决定调哪个工具。但当工具数涨到十几个、每个工具还带着「无生辰禁止排盘」之类的强约束时,问题来了:

  • 系统提示越写越长,模型漏掉硬约束的概率上升;
  • 工具返回的大段排盘 JSON 挤占上下文,后面的解读质量肉眼可见地下降;
  • 跨领域术语互相污染 prompt:塔罗的「逆位」和八字的「逆克」根本不是一回事,塞同一个提示词里模型会串味。

于是玄镜拆成了一个入口 Agent + 多个专用 Agent:

  • home_agent:首页通用入口,负责闲聊 / 通用问答;命理排盘调用工具或转交
  • ming_agent:八字、紫微等命理排盘与解读专用 Agent
  • report_agent / scale_report_agent:报告、量表生成
  • assessment_agent:评估类

每个专用 Agent 的工具集和提示词都收窄到自己的领域,互不干扰;入口 Agent 只做路由和通用问答。

二、拆完怎么保证「不可靠的模型」不把流程搞崩

多 Agent 最怕某一个环节抽风,导致整条链路在用户面前崩掉 。玄镜把「生成 → 校验 → 重试/降级」做成了可复用的 harness(langgraph_nodes.py)。

拆成多个专用 Agent 后,每个子 Agent(如 ming_agent)的生成节点后都接同一套 boundary harness;入口 Agent(home_agent)只接收已校验的结构化结果,不直接透传子 Agent 的原始输出。

真实源码里这套节点由 make_boundary_nodes(validator, max_retries=2) 工厂生成;下面为了看清路由逻辑,直接展示等价的 route_boundary 和状态字段:

csharp 复制代码
# 结构示意:state 至少包含
#   validation:  {ok: bool, reason: str}   # 校验器 validator 的硬校验结果
#   feedback:    str                        # 回灌给 generate 的错误信息
#   retry_count: int                        # 已重试次数
#   degraded:    bool                       # 是否已进入降级(由 degraded_output 节点写入)
MAX_RETRIES = 2

def route_boundary(state):
    v = state.get("validation", {})
    if v.get("ok"):
        return "valid"
    if state.get("retry_count", 0) >= MAX_RETRIES:   # 重试耗尽
        return "degraded"
    return "retry"

graph.add_conditional_edges("boundary_check", route_boundary, {
    "valid":    END,
    "retry":    "generate",          # 带 feedback 重新生成
    "degraded": "degraded_output",   # 模板兜底 / 只返回已校验字段
})

闭环职责:

  • boundary_check 节点:调用校验器 validator 做格式 / 越界硬校验 ,写 validation;校验失败时 把 validator 的 reason 写入 feedback,并递增 retry_count;
  • 路由:校验通过 → valid 结束;未过但还能重试 → retry(把 feedback 塞回 prompt 重来);重试耗尽 → degraded;
  • degraded_output 节点:模板兜底 / 只返回已校验字段 / 转人工,尽量避免把未校验内容直接透出。

注意这套回路叫「生成 → 校验 → 重试/降级」,降级是其中的一环,不是额外步骤。

三、判断清单:该拆还是该合

判断信号 建议
工具 ≤5、同领域、提示词稳定(经验阈值,非硬规则) 单 ReAct Agent 够用(如 home_agent)
术语 / 约束互相污染、工具返回挤爆上下文、失败模式不同 按领域拆专用 Agent
关键输出需格式 / 越界硬校验 套 boundary harness
多 Agent 要传结构化上下文 用 StateGraph 的 state 显式传,别靠 prompt 隐式猜

四、拆也有代价,别无脑拆

拆 Agent 不是免费的:会多出路由、状态传递、延迟、调试成本,以及跨 Agent 的 token 开销。如果只是「工具多但同领域」,先试这三招,往往就够了:

  1. 工具分组:把同类工具收敛,提示词里明确「什么场景用哪组」;
  2. 压缩工具返回 :排盘 JSON 上万字符,先压成千字符级的摘要再注入(玄镜的 _compact_paipan_summary 就是干这个的);
  3. 提示词分层:通用规则放系统提示,领域规则放工具描述。

只有当出现术语污染 / 约束冲突 / 上下文挤占 / 失败模式不同 ,且上述手段压不住时,再拆专用 Agent。一个很实用的铁律:子 Agent 不要把原始排盘 JSON 全量回灌主 Agent,只回传结构化摘要和已校验字段------这正好呼应前面「大段 JSON 挤占上下文」的痛点。

写在最后

这是「从0搭 AI Agent」系列的收官篇。玄镜是我独立从 0 到 1 交付的生产级 AI 产品(LangGraph 多智能体 + RAG + SSE 流式,FastAPI + Next.js)。我目前在看前端 + AI 应用 / 全栈 AI 方向的机会,欢迎交流。

接下来开一个新系列聊 RAG------玄镜没用裸向量检索,而是加了一层「特征加权」,原因和做法下篇展开。

下一篇(新系列「RAG 实战」第 1 篇):RAG 别只会向量检索:玄镜为什么加了「特征加权」

相关推荐
壹米饭1 小时前
手搓 MCP 到最简 Agent,我都做了什么?
agent·ai编程·mcp
大草原的小灰灰1 小时前
LLM应用的标准开发框架LangChain(八)- 中间件
python·中间件·langchain
无懈可击1 小时前
Vue 可视化AI表单设计器 FcDesigner v3.6 版本发布,支持导出 SQL功能!
vue.js·开源·ai编程
ZzT1 小时前
vibe coding 做小游戏·玩法重做篇:只留自走棋、去掉羁绊,用电脑自动对局调难度
ai编程·游戏开发
灵感__idea1 小时前
Claude Code 实战:AI这么强了,为什么还在发明新概念?
aigc·ai编程·claude
Carson带你学Android1 小时前
AI时代,你的 App 会被 Agent 这三种方式调用
android·ai编程
装不满的克莱因瓶2 小时前
【SpringAI Alibaba】ReactAgent记忆管理MessageTrimmingHook与MessageDeletionHook
java·人工智能·ai·ai编程·springai·springaialibaba
the局外人2 小时前
LangChain ToolRuntime 入门:context、state 与 store 的实际用法
后端·langchain·agent
西安小哥2 小时前
给 LLM 网关加一层熔断:主模型挂了 42 秒以后我做的事
ai编程