多智能体协作库langgraph-swarm-py

https://github.com/langchain-ai/langgraph-swarm-py多智能体协作库 


一、这玩意是干啥的?

想象你有一个客服团队:Alice 是数学专家,Bob 是个说话像海盗的逗比。用户来了,先跟 Bob 聊天,然后问"5+7 等于几?",Bob 不会算,就说"这事儿得找 Alice",然后把用户转给 Alice。Alice 算完答案,对话结束。

这个库就是帮你实现"智能体之间自动转接"的。

GitHub:langchain-ai/langgraph-swarm-py


二、三个核心概念

1. Swarm(蜂群)— 一群智能体的管理者

就像蜂群里的蜂王,它知道:

  • 现在谁在干活(active_agent)
  • 该把活儿派给谁(路由逻辑)
  • 怎么让智能体们互相交接(handoff 机制)
为什么需要它? 如果没有这个管理者,你每次跟 AI 对话,它都不知道上次是谁在回答你,每次都从头开始,像个金鱼记忆。

2. Handoff(交接)— 智能体之间的"传话筒"

每个智能体手里有个"转接电话"的工具。比如 Bob 会说:"我有个 transfer_to_alice 按钮,按一下就把用户转给 Alice。"

交接的时候做了三件事:

  1. 发一条消息:"已成功转接给 Alice"(让用户知道发生了什么)
  2. 告诉系统:"下一个找 Alice 干活"(更新 active_agent)
  3. 把之前的聊天记录打包带过去(这样 Alice 知道前面聊了啥)
为什么需要它? 就像医院分诊,你不能让一个心脏科医生去拔牙。每个智能体有自己擅长的活,遇到不擅长的就转给对的人。

3. Active Agent(活跃智能体)— 记住"上次是谁"

系统里有个小本本,记着"现在该谁干活"。新消息来了,先看小本本,找到那个人,让他继续处理。

为什么需要它? 保证对话的连续性。你问"5+7 等于几",系统知道上次是 Alice 在干活,就直接找 Alice,不会又去问 Bob"你要不要算一下?"

三、代码怎么组织的?

langgraph_swarm/
├── swarm.py       ← 蜂群管理者(怎么组队、怎么调度)
├── handoff.py     ← 交接工具(怎么转接、转给谁)
└── __init__.py    ← 对外暴露的接口

三个模块各司其职:

模块

核心功能

关键函数

swarm.py

多智能体编排引擎

create_swarm()add_active_agent_router()

handoff.py

智能体间交接机制

create_handoff_tool()get_handoff_destinations()

__init__.py

公共 API 导出

暴露 4 个符号


四、一个完整的例子

# 1. 创建两个智能体
alice = 创建智能体(模型, 工具=[加法器, 转接给Bob], 角色="我是数学专家")
bob = 创建智能体(模型, 工具=[转接给Alice], 角色="我是海盗")

# 2. 组建成蜂群
swarm = create_swarm([alice, bob], 默认启动="Alice")

# 3. 用户第一句话:"我想跟 Bob 说话"
# → 系统启动 Alice,Alice 看到用户想找 Bob,按转接按钮
# → 系统切到 Bob,Bob 开始用海盗口吻聊天

# 4. 用户第二句话:"5+7 等于几?"
# → 系统记得上次是 Bob,直接找 Bob
# → Bob 不会算,按转接按钮找 Alice
# → Alice 算出 12,返回答案


五、为什么这个设计好?

特性

说明

🎯 不用手动写调度代码

你只需要告诉每个智能体"你能转给谁",库自动处理所有路由

🧠 有记忆

通过 checkpointer 保存对话,关了重开还能继续聊

🔌 可扩展

想加第三个智能体?一行代码:create_swarm([alice, bob, charlie])

⚙️ 可定制

不满意默认的转接方式?自己写个 handoff 工具,想传什么数据都行


六、频繁交接问题:会不会转错?

Q1:很多智能体互相转换,要维护复杂的 handoff 工具吗?

不需要。库自动搞定。 create_swarm 在添加每个智能体时,会调用 get_handoff_destinations() 自动扫描这个智能体身上有哪些 handoff 工具,自动识别路由目标。

关键机制在 get_handoff_destinations

  1. 钻进智能体内部的图结构
  2. 找到 tools 节点里的所有工具
  3. 检查每个工具的 metadata 里有没有 __handoff_destination 标记
  4. 把标记里的目标名字全部收集起来

Q2:会不会交接给错误的智能体?

有可能,但责任在 LLM,不在库。 交接的决策者是 LLM,库只负责执行。

库做的防护:

  • 工具描述create_handoff_tooldescription 参数告诉 LLM 这个工具是干啥的
  • system_prompt 引导:可以给每个智能体写清楚角色定位
  • 没有强制路由:库不会替 LLM 做决定

怎么降低风险? 给每个 handoff 工具写清晰的 description,描述越具体,LLM 越不容易选错。


七、为什么要路由到"上次干活的 Agent"?

核心代码就一句话:

def route_to_active_agent(state: dict) -> str:
    return state.get("active_agent", default_active_agent)

每次新消息进来,先看 state 里记的 active_agent 是谁,就找谁。

这个设计的巧妙之处

特点

说明

🔗 保证对话连续性

没有记忆的话,每次都要重新判断"该找谁",对话会断

避免反复路由的性能浪费

有记忆 = 直接跳过去,省一次 LLM 调用

👤 符合人类对话直觉

你跟一个人聊天,不会每句话都重新自我介绍

🔄 和 handoff 工具形成闭环

handoff 更新 active_agent,路由读取 active_agent,写和读分离

🛡️ 支持默认值降级

第一次对话时 active_agent 是空的,走 default_active_agent

一句话总结: 这个设计把"谁在处理当前对话"这个状态从"每次都重新计算"变成了"记住就行"。就像你在餐厅点了菜,服务员不需要每上一道菜都问"这桌是谁的?",因为订单上写着桌号。active_agent 就是那个桌号。

八、从交接看执行全过程(基于测试用例)

场景还原

Turn 1: 用户说"我想跟 Bob 说话"

步骤

动作

系统启动,active_agent 为空 → 走默认值 "Alice"

路由到 Alice,Alice 调用 transfer_to_bob 工具

handoff 执行:goto → Bob 节点;update → 把 active_agent 改成 "Bob"

Bob 收到消息 + 完整历史,开始用海盗口吻回复

结束

active_agent = "Bob"

Turn 2: 用户说"5+7 等于几?"

步骤

动作

路由函数读 state.get("active_agent") → "Bob"

直接路由到 Bob,Bob 调用 transfer_to_alice

handoff 执行:active_agent 被改成 "Alice"

Alice 调用 add(5, 7),返回 12

结束

active_agent = "Alice"

三个关键问题的答案

问题

答案

Alice 交接给 Bob 后,当前活跃的是谁?

Bob。 handoff 在第 91 行立刻把 active_agent 改成了 "Bob"

下次对话进来,路由到谁?

Bob。 路由函数读的是 state.get("active_agent"),上次结束时的值是 "Bob"

Bob 知道前面聊了啥吗?

全知道。 所有历史消息都打包传给了 Bob

关键洞察

active_agent 不是"谁在处理",而是"处理完之后的最后一个人是谁"。 就像接力赛,最后一棒是谁,active_agent 就记谁。下次发令枪响,直接找最后一棒的人。

消息是全量传递的,不是只传"当前智能体的消息"。所有智能体共享一个 messages 列表,所以 Bob 能看到 Alice 说过什么,Alice 也能看到 Bob 说过什么。


九、每个智能体都充当"路由器"角色

关键机制:handoff 工具就是一个普通的 tool

create_handoff_tool 创建的本质上就是一个普通的 LangChain Tool,跟 add(a, b) 这种计算工具没区别。它被塞进智能体的 tools 列表里,LLM 看到它,自己决定要不要调用。

完整流程拆解

场景: 用户说"帮我算 5+7"

步骤

动作

路由到 Bob(active_agent = "Bob")

Bob 的 LLM 看到工具列表中有 transfer_to_alice

LLM 决定调用 transfer_to_alice

系统跳到 Alice 节点

Alice 的 LLM 看到工具列表中有 add(a, b)

LLM 调用 add(5, 7) → 返回 12

LLM 生成回复:"结果是 12"

三个关键点

  1. 路由判断 = LLM 的工具选择 — 不是库写了 if 规则,而是 LLM 自己推理
  2. 每个智能体只需要知道"我能转给谁" — 不需要知道对方的能力
  3. 没有中心调度器 — 系统是去中心化的,每个智能体自己决定要不要转、转给谁
每个智能体都需要充当判断路由的作用——这个"判断"不是代码逻辑,是 LLM 的工具调用决策。库只负责:发按钮 → 按按钮后跳转 → 记住最后谁在干活。

十、消息归属问题:不是模糊记录

每条 AI 消息都有 name 字段,明确标记是谁说的。messages 列表不是"所有消息混在一起",而是每条都有角色归属:

messages = [
    {"role": "user", "content": "我想跟 Bob 说话"},       # 用户说的
    AIMessage(name="Alice", tool_calls=[transfer_to_bob]), # Alice 说的
    ToolMessage(content="已转接给 Bob"),                    # 系统说的(handoff 工具生成)
    AIMessage(name="Bob", content="Ahoy, matey! ..."),     # Bob 说的
    {"role": "user", "content": "5+7 等于几?"},           # 用户说的
    AIMessage(name="Bob", tool_calls=[transfer_to_alice]), # Bob 转接的
    ToolMessage(content="add(5,7)=12"),                    # 系统说的(add 工具结果)
    AIMessage(name="Alice", content="结果是12"),           # Alice 回答的
]


附:代码模块详解

swarm.py — 多智能体编排引擎

组件

说明

SwarmState

继承自 MessagesState,核心字段是 active_agent(记录当前活跃的智能体)

create_swarm()

工厂函数,接收多个智能体列表,自动构建 StateGraph。验证非空、自动转换类型、添加节点、推断路由

add_active_agent_router()

底层路由函数,在 START 处添加条件边,根据 active_agent 状态字段决定路由

handoff.py — 智能体间交接机制

组件

说明

create_handoff_tool()

创建标准交接工具,工具名自动生成,内部生成 ToolMessage + 返回 Command(goto=...)

get_handoff_destinations()

从已编译的智能体图中提取所有 handoff 目标

公共 API(__init__.py

暴露 4 个公共符号:SwarmStateadd_active_agent_routercreate_handoff_toolcreate_swarm

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值