一、单 Agent vs Multi-Agent:什么时候需要多智能体?
1.1 单 Agent 的瓶颈
单个 Agent 面临以下问题:
- 上下文膨胀:复杂任务的中间状态全部堆在一个对话里,token 消耗爆炸
- 专业性不足:一个 Agent 身兼数职,System Prompt 臃肿,质量下降
- 无法并行:所有步骤串行执行,耗时长
- 错误传播:某步出错,整个任务失败,无法局部重试
1.2 Multi-Agent 适用场景
| 场景 | 适合 Multi-Agent 的原因 |
|---|---|
| 软件开发流程(需求→代码→测试→审查) | 各角色专业不同,可并行 |
| 复杂报告生成(搜集→分析→撰写→校对) | 步骤解耦,质量更高 |
| 数据处理流水线(提取→转换→验证→入库) | 天然流水线结构 |
| 客服升级流程(初筛→专业判断→人工兜底) | 条件路由,降本增效 |
判断标准:如果任务可以拆解为 3 个以上专业子任务,且子任务之间有明确的输入输出边界,就适合 Multi-Agent。
二、LangGraph 核心抽象详解
LangGraph 是 LangChain 官方推出的 Agent 编排框架,用**图(Graph)**的方式定义 Agent 工作流:
bash
核心概念:
State(状态) → 贯穿整个图的共享数据结构
Node(节点) → 每个 Agent 或处理函数
Edge(边) → 节点间的流转关系
Graph(图) → 节点 + 边组成的完整工作流
2.1 安装依赖
bash
pip install langgraph langchain-openai langchain-core python-dotenv
2.2 State 设计------最重要的第一步
State 是所有 Agent 共享的"工作台",设计好 State 结构是 Multi-Agent 成功的关键:
python
# state.py
from typing import TypedDict, Annotated, List, Optional
from langgraph.graph.message import add_messages
class DevWorkflowState(TypedDict):
"""软件开发工作流的共享状态"""
# 原始需求
requirement: str
# 各阶段输出
analysis_result: Optional[str] # 需求分析结果
code_result: Optional[str] # 编码结果
test_result: Optional[str] # 测试结果
review_result: Optional[str] # 代码审查结果
# 流程控制
current_step: str # 当前步骤
errors: List[str] # 错误收集
approved: bool # 是否通过审查
# 消息历史(使用 add_messages 自动追加)
messages: Annotated[list, add_messages]
三、实战:四角色 Agent 流水线
3.1 配置大模型客户端
python
# llm_config.py
import os
from langchain_openai import ChatOpenAI
from dotenv import load_dotenv
load_dotenv()
# 使用 DeepSeek V4 Flash(性价比最高)
def get_llm(temperature: float = 0.3):
return ChatOpenAI(
model="deepseek-v4-flash",
api_key=os.getenv("DEEPSEEK_API_KEY"),
base_url="https://api.deepseek.com",
temperature=temperature,
)
# 复杂推理用 Pro 版
def get_pro_llm(temperature: float = 0.1):
return ChatOpenAI(
model="deepseek-v4-pro",
api_key=os.getenv("DEEPSEEK_API_KEY"),
base_url="https://api.deepseek.com",
temperature=temperature,
)
3.2 定义四个专业 Agent 节点
python
# agents.py
from langchain_core.messages import HumanMessage, AIMessage, SystemMessage
from state import DevWorkflowState
from llm_config import get_llm, get_pro_llm
# ── Agent 1:需求分析师 ──────────────────────────────────────────
def analyst_agent(state: DevWorkflowState) -> DevWorkflowState:
"""分析需求,输出技术方案和任务拆解"""
llm = get_llm()
system = SystemMessage(content="""你是一个资深需求分析师。
分析用户需求,输出:
1. 功能点列表(按优先级排序)
2. 技术方案选型
3. 数据结构设计
4. 接口定义(输入/输出)
格式要求:结构清晰,用 Markdown 呈现""")
response = llm.invoke([
system,
HumanMessage(content=f"请分析以下需求:\n\n{state['requirement']}")
])
print(f"✅ [需求分析师] 分析完成")
return {
**state,
"analysis_result": response.content,
"current_step": "analyzed",
"messages": [AIMessage(content=response.content, name="analyst")]
}
# ── Agent 2:编码工程师 ──────────────────────────────────────────
def coder_agent(state: DevWorkflowState) -> DevWorkflowState:
"""根据需求分析结果编写代码"""
llm = get_pro_llm() # 编码用 Pro 版,质量更高
system = SystemMessage(content="""你是一个资深 Python 工程师。
根据需求分析结果,编写完整、可运行的代码:
- 代码结构清晰,有适当注释
- 包含异常处理
- 遵循 PEP8 规范
- 只输出代码和必要说明,不要重复需求分析内容""")
response = llm.invoke([
system,
HumanMessage(content=f"""
需求分析结果:
{state['analysis_result']}
原始需求:
{state['requirement']}
请编写实现代码:""")
])
print(f"✅ [编码工程师] 编码完成")
return {
**state,
"code_result": response.content,
"current_step": "coded",
"messages": [AIMessage(content=response.content, name="coder")]
}
# ── Agent 3:测试工程师 ──────────────────────────────────────────
def tester_agent(state: DevWorkflowState) -> DevWorkflowState:
"""为代码编写测试用例"""
llm = get_llm()
system = SystemMessage(content="""你是一个 QA 测试工程师,专注 Python 单元测试。
为给定代码编写完整测试:
- 使用 pytest 框架
- 覆盖正常流程、边界条件、异常情况
- 每个测试函数有清晰的命名和注释
- 覆盖率目标 80% 以上""")
response = llm.invoke([
system,
HumanMessage(content=f"""
请为以下代码编写测试用例:
{state['code_result']}
需求背景:{state['requirement']}""")
])
print(f"✅ [测试工程师] 测试用例生成完成")
return {
**state,
"test_result": response.content,
"current_step": "tested",
"messages": [AIMessage(content=response.content, name="tester")]
}
# ── Agent 4:代码审查员 ──────────────────────────────────────────
def reviewer_agent(state: DevWorkflowState) -> DevWorkflowState:
"""审查代码质量,给出通过/拒绝决定"""
llm = get_pro_llm()
system = SystemMessage(content="""你是一个严格的代码审查员。
审查代码质量,重点关注:
1. 代码正确性(逻辑是否有 bug)
2. 安全性(有无注入、越界等风险)
3. 性能(有无明显性能问题)
4. 可维护性(代码是否清晰)
5. 测试充分性(测试是否覆盖关键场景)
最后必须给出明确结论:
【审查结果】APPROVED 或 REJECTED
【原因】xxx
【修改建议】xxx(如果 REJECTED)""")
response = llm.invoke([
system,
HumanMessage(content=f"""
请审查以下代码和测试:
== 实现代码 ==
{state['code_result']}
== 测试代码 ==
{state['test_result']}
需求:{state['requirement']}""")
])
content = response.content
approved = "APPROVED" in content.upper()
print(f"✅ [代码审查员] 审查完成 → {'通过 ✅' if approved else '拒绝 ❌'}")
return {
**state,
"review_result": content,
"approved": approved,
"current_step": "reviewed",
"messages": [AIMessage(content=content, name="reviewer")]
}
3.3 构建图结构
python
# workflow.py
from langgraph.graph import StateGraph, END
from state import DevWorkflowState
from agents import analyst_agent, coder_agent, tester_agent, reviewer_agent
def should_continue(state: DevWorkflowState) -> str:
"""条件路由:审查通过则结束,否则重新编码"""
if state.get("approved"):
return "end"
# 检查错误次数,避免无限循环
errors = state.get("errors", [])
if len(errors) >= 2:
print("⚠️ 已重试 2 次,强制结束")
return "end"
return "recode"
def add_error(state: DevWorkflowState) -> DevWorkflowState:
"""记录审查失败,准备重试"""
errors = state.get("errors", [])
errors.append(f"审查失败,原因:{state.get('review_result', '')[:100]}")
return {**state, "errors": errors}
# ── 构建图 ──────────────────────────────────────────────────────
def build_dev_workflow() -> StateGraph:
graph = StateGraph(DevWorkflowState)
# 添加节点
graph.add_node("analyst", analyst_agent)
graph.add_node("coder", coder_agent)
graph.add_node("tester", tester_agent)
graph.add_node("reviewer", reviewer_agent)
graph.add_node("add_error", add_error)
# 设置入口
graph.set_entry_point("analyst")
# 添加普通边(顺序流转)
graph.add_edge("analyst", "coder")
graph.add_edge("coder", "tester")
graph.add_edge("tester", "reviewer")
# 条件边:审查结果决定下一步
graph.add_conditional_edges(
"reviewer",
should_continue,
{
"end": END,
"recode": "add_error" # 记录错误后重新编码
}
)
graph.add_edge("add_error", "coder") # 重新编码
return graph.compile()
3.4 运行工作流
python
# main.py
from workflow import build_dev_workflow
def run_dev_workflow(requirement: str):
app = build_dev_workflow()
initial_state = {
"requirement": requirement,
"analysis_result": None,
"code_result": None,
"test_result": None,
"review_result": None,
"current_step": "start",
"errors": [],
"approved": False,
"messages": [],
}
print(f"\n{'='*60}")
print(f"🚀 启动开发工作流")
print(f"需求:{requirement}")
print(f"{'='*60}\n")
final_state = app.invoke(initial_state)
print(f"\n{'='*60}")
print(f"📋 工作流执行完成")
print(f"最终状态:{'✅ 通过' if final_state['approved'] else '⚠️ 未通过(已达重试上限)'}")
print(f"重试次数:{len(final_state.get('errors', []))}")
print(f"{'='*60}")
return final_state
if __name__ == "__main__":
result = run_dev_workflow(
"实现一个 Python 装饰器,用于统计函数执行时间,"
"支持设置超时时间,超时自动抛出 TimeoutError,"
"并将统计结果写入日志文件。"
)
print("\n== 最终代码 ==")
print(result["code_result"])
四、并行执行:让测试和文档同时生成
python
# parallel_workflow.py
from langgraph.graph import StateGraph, END
from typing import TypedDict, Annotated, List
from langgraph.graph.message import add_messages
class ParallelState(TypedDict):
requirement: str
code_result: str
test_result: str
doc_result: str # 新增:文档生成
messages: Annotated[list, add_messages]
def doc_writer_agent(state: ParallelState) -> ParallelState:
"""并行生成 API 文档(与测试同时进行)"""
from llm_config import get_llm
from langchain_core.messages import SystemMessage, HumanMessage
llm = get_llm()
response = llm.invoke([
SystemMessage(content="你是技术文档工程师,为代码生成 README 和 API 文档。"),
HumanMessage(content=f"为以下代码生成文档:\n\n{state['code_result']}")
])
return {**state, "doc_result": response.content}
def build_parallel_workflow():
graph = StateGraph(ParallelState)
from agents import analyst_agent, coder_agent, tester_agent, reviewer_agent
graph.add_node("analyst", analyst_agent)
graph.add_node("coder", coder_agent)
graph.add_node("tester", tester_agent)
graph.add_node("doc_writer", doc_writer_agent)
graph.add_node("reviewer", reviewer_agent)
graph.set_entry_point("analyst")
graph.add_edge("analyst", "coder")
# 编码完成后,测试和文档并行执行
graph.add_edge("coder", "tester")
graph.add_edge("coder", "doc_writer")
# 并行结果汇聚到审查节点
graph.add_edge("tester", "reviewer")
graph.add_edge("doc_writer", "reviewer")
graph.add_edge("reviewer", END)
return graph.compile()
五、Human-in-the-Loop:人工介入节点
生产环境中,某些关键决策不能完全交给 AI。LangGraph 支持在任意节点暂停,等待人工确认:
python
from langgraph.graph import StateGraph, END
from langgraph.checkpoint.memory import MemorySaver
def build_workflow_with_human():
"""带人工介入的工作流"""
graph = StateGraph(DevWorkflowState)
graph.add_node("analyst", analyst_agent)
graph.add_node("coder", coder_agent)
graph.add_node("tester", tester_agent)
graph.add_node("reviewer", reviewer_agent)
graph.set_entry_point("analyst")
graph.add_edge("analyst", "coder")
graph.add_edge("coder", "tester")
graph.add_edge("tester", "reviewer")
graph.add_edge("reviewer", END)
# 使用内存检查点(生产环境用 SqliteSaver 或 PostgresSaver)
memory = MemorySaver()
return graph.compile(
checkpointer=memory,
interrupt_before=["coder"] # 在编码前暂停,等待人工确认需求分析
)
def run_with_human_approval(requirement: str):
app = build_workflow_with_human()
config = {"configurable": {"thread_id": "dev-session-001"}}
# 初始状态
state = {
"requirement": requirement,
"analysis_result": None, "code_result": None,
"test_result": None, "review_result": None,
"current_step": "start", "errors": [], "approved": False, "messages": []
}
# 运行到 coder 节点前暂停
for event in app.stream(state, config):
print(f"节点执行:{list(event.keys())}")
# 此时工作流暂停,等待人工决策
print("\n⏸️ 工作流已暂停,请审核需求分析结果...")
current = app.get_state(config)
print("需求分析结果:", current.values.get("analysis_result", "")[:200])
human_input = input("\n是否继续执行编码?(y/n): ")
if human_input.lower() != 'y':
print("❌ 用户取消执行")
return None
# 人工确认后继续执行
print("▶️ 继续执行...")
for event in app.stream(None, config):
print(f"节点执行:{list(event.keys())}")
return app.get_state(config).values
六、监控与调试:LangSmith 追踪执行链路
python
# 在项目根目录 .env 文件添加
# LANGCHAIN_TRACING_V2=true
# LANGCHAIN_API_KEY=your-langsmith-api-key
# LANGCHAIN_PROJECT=my-multi-agent-project
import os
os.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_API_KEY"] = "your-key"
# 之后所有 LangGraph 执行都会自动上传到 LangSmith
# 在 https://smith.langchain.com 查看:
# - 每个 Agent 的输入/输出
# - Token 消耗明细
# - 执行时间
# - 错误堆栈
本地调试替代方案:
python
# 打印每步执行细节
for step in app.stream(initial_state):
for node_name, node_output in step.items():
print(f"\n{'─'*40}")
print(f"节点:{node_name}")
print(f"当前步骤:{node_output.get('current_step', 'N/A')}")
if "errors" in node_output and node_output["errors"]:
print(f"错误:{node_output['errors']}")
七、完整项目结构与运行
bash
multi-agent-dev/
├── .env
├── state.py # 状态定义
├── llm_config.py # LLM 配置
├── agents.py # 四个 Agent 定义
├── workflow.py # 图构建
├── main.py # 入口
└── requirements.txt
bash
# requirements.txt
langgraph>=0.2.0
langchain-openai>=0.2.0
langchain-core>=0.3.0
python-dotenv
# 运行
python main.py
总结
Multi-Agent 的核心价值在于分工专业化 + 并行提速 + 局部容错。LangGraph 的图结构让复杂工作流可视化且可调试。
实践要点:
- State 设计先行:State 结构决定了信息如何在 Agent 间流转,改动成本高
- 节点职责单一:每个 Agent 只做一件专业的事,System Prompt 简洁
- 条件边控制流 :
conditional_edges是实现重试、分支、人工介入的关键 - 先用 Flash 模型,确认流程正确后再切换 Pro 版