用 LangGraph 搭建多 Agent 协作系统:从踩坑到跑通

起因

我已经用 n8n 搭了不少自动化流水线,但一直想试试 LangGraph 的多 Agent 协作——让多个专业 Agent 在 Supervisor 的统一调度下协同完成复杂任务。

手头的资源:

  • VPS 没有 GPU,5.8Gi 内存
  • 已经有 One API 作为 LLM 网关(配了 20+ 渠道)
  • 已经装了 LangChain 生态

目标:跑通一个「调研 → 撰写 → 审核」的三 Agent 内容生产流水线。

整体架构

text

用户指令 → Supervisor(调度器)
              ↓
    ┌─────────┼─────────┐
    ↓         ↓         ↓
Researcher  Writer   Reviewer
(调研)    (撰写)   (审核)

Supervisor 根据任务进度决定下一步调用哪个 Agent,Agent 之间通过 LangGraph 的 State 传递信息。

第一步:安装依赖

bash

cd /opt/rag-nvidia
source venv/bin/activate

pip install langgraph langgraph-supervisor langchain-openai langchain

四个包缺一不可

作用
langgraphAgent 运行时,提供状态管理和持久化
langgraph-supervisor预置的 Supervisor 模式实现
langchain-openai兼容 OpenAI 接口的模型封装
langchainAgent 创建的高级抽象

第二步:第一次尝试(失败)

最初的脚本用了 LangChain 1.x 的 create_agent

python

from langchain.agents import create_agent
from langgraph_supervisor import create_supervisor

researcher = create_agent(
    model=model,
    tools=[search_topic],
    name="researcher",
    system_prompt="你是调研专家。",
)

结果:Supervisor 输出了「给 Researcher 的指令」,但没有真正调用 researcher

text

[supervisor]
下一步调用:Researcher(调研员)
给 Researcher 的指令:请针对"AI 改变教育"进行深度调研...
(然后就没有下文了)

第三步:定位根因

反复调试后发现,问题不在 Agent 创建方式,而在模型的 tool calling 支持

langgraph-supervisor 依赖 function calling / tool use 来实现 Agent 之间的控制权转交(handoff)。Supervisor 通过调用 transfer_to_researcher 这样的工具来把控制权交给子 Agent。

如果模型不支持 tool calling,Supervisor 就无法真正执行 handoff,只能生成文字描述。

第四步:测试哪些模型支持 tool calling

写了一个脚本,向 NVIDIA NIM 的模型发送带 tools 参数的请求,看返回的 finish_reason

python

TOOLS = [{
    "type": "function",
    "function": {
        "name": "get_weather",
        "description": "Get current weather for a city",
        "parameters": {
            "type": "object",
            "properties": {"city": {"type": "string"}},
            "required": ["city"]
        }
    }
}]

body = {
    "model": model_id,
    "messages": [{"role": "user", "content": "What is the weather in Tokyo?"}],
    "tools": TOOLS,
    "tool_choice": "auto",
    "stream": False,
}

关键看 finish_reason

返回含义
finish_reason: "tool_calls" + tool_calls 字段有内容✅ 支持
finish_reason: "stop" + 普通文本❌ 不支持

测试结果

模型tool calling
gemma4:31bstop,直接文本回答
gpt-oss:120bstop,直接文本回答
nvidia/nemotron-3-super-120b-a12btool_calls
nvidia/nemotron-3-ultra-550b-a55btool_calls

关键发现:推理模型(gemma4、gpt-oss)不支持 tool calling,而 NVIDIA 的 Nemotron 系列支持。

第五步:用正确的模型跑通

把模型换成 nvidia/nemotron-3-super-120b-a12b

python

from langchain_openai import ChatOpenAI
from langchain.agents import create_agent
from langgraph_supervisor import create_supervisor
from langchain_core.tools import tool

model = ChatOpenAI(
    base_url="http://172.17.0.1:3000/v1",
    api_key="sk-你的OneAPI令牌",
    model="nvidia/nemotron-3-super-120b-a12b",
    temperature=0.7,
    timeout=300,
)


@tool
def search_topic(query: str) -> str:
    """搜索关于某个主题的信息。"""
    return f"关于「{query}」的调研结果:这是热门话题,主要观点包括 A、B、C 三方面。"


@tool
def write_draft(topic: str, research: str) -> str:
    """根据调研结果撰写文章草稿。"""
    return f"基于调研「{research}」,关于「{topic}」的草稿已完成。"


@tool
def review_content(draft: str) -> str:
    """审核文章草稿。"""
    return f"审核意见:草稿「{draft}」质量合格。"


researcher = create_agent(
    model=model,
    tools=[search_topic],
    name="researcher",
    system_prompt="你是调研专家。使用 search_topic 工具查找信息。",
)

writer = create_agent(
    model=model,
    tools=[write_draft],
    name="writer",
    system_prompt="你是内容撰写专家。根据调研结果产出草稿。",
)

reviewer = create_agent(
    model=model,
    tools=[review_content],
    name="reviewer",
    system_prompt="你是审核专家。检查草稿质量。",
)

workflow = create_supervisor(
    agents=[researcher, writer, reviewer],
    model=model,
    prompt="""你是内容生产团队的主管。
流程:先让 researcher 调研,再把结果交给 writer 撰写,最后让 reviewer 审核。""",
)

app = workflow.compile()

result = app.invoke({
    "messages": [{"role": "user", "content": "写一篇关于 AI 改变教育的内容"}]
})

结果:完整跑通。

text

[transfer_to_researcher]
Successfully transferred to researcher
    ↓
[researcher] 调研 → [transfer_back_to_supervisor]
    ↓
[transfer_to_writer]
Successfully transferred to writer
    ↓
[writer] 撰写 → [transfer_back_to_supervisor]
    ↓
[transfer_to_reviewer]
Successfully transferred to reviewer
    ↓
[reviewer] 审核 → [transfer_back_to_supervisor]
    ↓
[supervisor] 输出最终结果

关键验证点

验证项结果
Supervisor 决策✅ 依次调度三个 Agent
transfer_to_* 工具调用✅ 每次转交都成功
transfer_back_to_supervisor✅ 每个 Agent 完成后交回控制权
三个 Agent 都被执行✅ researcher → writer → reviewer

踩坑记录

1. 模型不支持 tool calling 是最常见的坑

多 Agent 协作必须依赖 tool calling。如果模型只返回文本、不返回 tool_calls,Supervisor 就无法转交控制权。

排查方式:用 curl 发送带 tools 参数的请求,看 finish_reason 是否是 tool_calls

2. 推理模型通常不支持 tool calling

gemma4:31bgpt-oss:120b 都是推理模型,它们会先生成思考过程再输出回答,但不支持 function calling。换非推理的 Nemotron 系列解决。

3. create_react_agent 已弃用

LangGraph 1.x 后,create_react_agent 被移到 langchain.agents.create_agent。如果用旧版会报 LangGraphDeprecatedSinceV10 警告。

4. 550B 模型太慢

nemotron-3-ultra-550b 虽然也支持 tool calling,但每次调用约 37 秒。多 Agent 协作涉及多次调用,总耗时可能 3-5 分钟。用 nemotron-3-super-120b 更快。

5. One API 能正常转发 tool calling

测试确认,通过 One API 调用 nemotron-3-super-120b 时,tools 参数被正确转发,tool_calls 响应也能正确返回。

当前状态

组件状态
LangChain + LangGraph✅ 已安装
langgraph-supervisor✅ 已安装
One API 转发 tool calling✅ 正常
nemotron-3-super-120b✅ 支持 tool calling
多 Agent 协作✅ 跑通

可优化的方向

1. 换真实工具

当前的 search_topicwrite_draftreview_content 都是返回固定文本的模拟工具。可以换成:

  • 真实搜索:接入 Tavily、SerpAPI
  • 真实发布:接入 WordPress REST API
  • 真实审核:接入 RAG,基于事实检查

2. 加更多 Agent

  • SEO Agent:优化标题和关键词
  • 配图 Agent:调用 Pollinations 生成特色图片
  • 发布 Agent:上传到 WordPress

3. 持久化与可视化

LangGraph 支持 checkpoint,可以把每次协作的中间状态存到 SQLite,方便回溯和调试。

4. 接入 n8n

把整个多 Agent 协作封装成一个 Flask 服务,n8n 通过 HTTP 调用它。

一句话总结

多 Agent 协作的核心前提是模型支持 tool calling。 选对模型(Nemotron 系列),配好 One API,用 LangGraph + langgraph-supervisor 就能在 VPS 上跑通完整的协作流水线。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注