LangGraph 多智能体协作系统

27 阅读15分钟

让三个不同角色的 Agent(产品经理、架构师、程序员)在 LangGraph 中"开会讨论",自主完成需求分析与代码生成任务。


1. Multi-Agent 架构概述

1.1 为什么需要 Multi-Agent?

单 Agent 在处理复杂任务时存在明显局限:

问题说明
工具过多Agent 拥有太多工具时,决策质量下降
上下文复杂单个 Agent 难以跟踪复杂的多步骤任务
领域专业化不同任务需要不同领域的专业知识
可控性差单 Agent 执行过程黑盒,难以精确控制

Multi-Agent 系统通过分而治之的策略解决这些问题:

┌─────────────────────────────────────────────────────────────┐
│                   Multi-Agent 优势                           │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   模块化                                                     │
│   ├── 独立开发、测试、维护                                   │
│   └── 职责单一,边界清晰                                     │
│                                                             │
│   专业化                                                     │
│   ├── 每个Agent专注特定领域                                  │
│   └── 专业分工,效果更好                                     │
│                                                             │
│   可控性                                                     │
│   ├── 明确控制Agent间通信                                    │
│   └── 流程可视化,易于调试                                   │
│                                                             │
└─────────────────────────────────────────────────────────────┘

1.2 Multi-Agent 架构模式

LangGraph 支持多种多智能体架构:

┌─────────────────────────────────────────────────────────────┐
│                Multi-Agent 三种核心架构                      │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  1. Network(网络式)                                        │
│     ┌───┐     ┌───┐                                         │
│     │ A │◄───▶│ B │    任何Agent都可与其他Agent通信          │
│     └───┘     └───┘    Agent自己决定下一步调用谁             │
│       ▲         ▲                                           │
│       │         │                                           │
│       └────┬────┘                                           │
│            │                                                │
│          ┌─▼─┐                                              │
│          │ C │                                              │
│          └───┘                                              │
│                                                             │
│  2. Supervisor(监督者式)                                   │
│            ┌─────┐                                          │
│            │  S  │  Supervisor 决定调用哪个 Agent            │
│            └──┬──┘  所有 Agent 只与 Supervisor 通信          │
│         ┌─────┼─────┐                                       │
│         ▼     ▼     ▼                                       │
│       ┌───┐ ┌───┐ ┌───┐                                    │
│       │ A │ │ B │ │ C │                                    │
│       └───┘ └───┘ └───┘                                    │
│                                                             │
│  3. Hierarchical(层级式)                                   │
│            ┌─────┐                                          │
│            │ CEO │   多层监督者结构                          │
│            └──┬──┘   上层监督者管理下层监督者                │
│         ┌─────┴─────┐                                       │
│         ▼           ▼                                       │
│       ┌───┐       ┌───┐                                    │
│       │ S1│       │ S2│                                    │
│       └─┬─┘       └─┬─┘                                    │
│      ┌──┴──┐     ┌──┴──┐                                   │
│      ▼     ▼     ▼     ▼                                   │
│     ┌─┐   ┌─┐   ┌─┐   ┌─┐                                 │
│     │A│   │B│   │C│   │D│                                 │
│     └─┘   └─┘   └─┘   └─┘                                 │
│                                                             │
└─────────────────────────────────────────────────────────────┘

2. LangGraph 核心概念

2.1 三大核心要素

# LangGraph 最小可用图的三个要素

from typing import TypedDict
from langgraph.graph import StateGraph, END, START

# 1. State:状态数据结构
class GraphState(TypedDict):
    messages: list      # 消息历史
    current_agent: str  # 当前活跃的 Agent
    task_status: str    # 任务状态

# 2. Nodes:处理节点(Python 函数)
def agent_node(state: GraphState) -> dict:
    """Agent 处理逻辑"""
    # 处理 state,返回更新
    return {"messages": ["处理完成"]}

# 3. Edges:连接边(控制流转)
builder = StateGraph(GraphState)
builder.add_node("agent", agent_node)
builder.add_edge(START, "agent")
builder.add_edge("agent", END)

graph = builder.compile()

2.2 条件边与循环

LangGraph 的核心优势:支持条件分支和循环

from typing import Literal

def router(state: GraphState) -> Literal["continue", "end"]:
    """条件路由函数"""
    if len(state["messages"]) > 10:
        return "end"
    return "continue"

# 添加条件边
builder.add_conditional_edges(
    "agent",
    router,
    {
        "continue": "agent",  # 循环回到自己
        "end": END            # 结束
    }
)

3. 实战案例:三角色协作系统

3.1 场景描述

模拟一个软件开发团队的协作流程:

用户需求 ──▶ 产品经理分析 ──▶ 架构师设计 ──▶ 程序员编码 ──▶ 代码输出
                │                │                │
                └────────────────┴────────────────┘
                              协作讨论

角色分工

角色职责输出
产品经理需求分析、用户故事、功能列表需求文档
架构师技术方案、模块设计、接口定义设计文档
程序员代码实现、单元测试可执行代码

3.2 系统架构设计

┌─────────────────────────────────────────────────────────────┐
│                   三角色协作系统架构                          │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│                      ┌─────────┐                            │
│                      │  START  │                            │
│                      └────┬────┘                            │
│                           │                                 │
│                           ▼                                 │
│                   ┌───────────────┐                         │
│                   │  产品经理Agent │                         │
│                   │  需求分析      │                         │
│                   └───────┬───────┘                         │
│                           │                                 │
│                    需求通过?                                │
│                      │                                      │
│            ┌─────────┴─────────┐                            │
│            │                   │                            │
│            ▼                   ▼                            │
│          通过               需要讨论                         │
│            │                   │                            │
│            ▼                   │                            │
│   ┌───────────────┐            │                            │
│   │  架构师Agent   │◄───────────┘                            │
│   │  技术设计      │                                        │
│   └───────┬───────┘                                        │
│            │                                                │
│     设计通过?                                               │
│            │                                                │
│     ┌──────┴──────┐                                         │
│     │             │                                         │
│     ▼             ▼                                         │
│   通过        需要讨论                                       │
│     │             │                                         │
│     ▼             │                                         │
│ ┌─────────────┐   │                                         │
│ │ 程序员Agent │◄──┘                                         │
│ │ 代码实现    │                                             │
│ └──────┬──────┘                                             │
│        │                                                    │
│  代码完成?                                                  │
│        │                                                    │
│   ┌────┴────┐                                               │
│   │         │                                               │
│   ▼         ▼                                               │
│  完成    需要修改                                            │
│   │         │                                               │
│   ▼         │                                               │
│ ┌────┐      │                                               │
│ │END │◄─────┘                                               │
│ └────┘                                                      │
│                                                             │
└─────────────────────────────────────────────────────────────┘

3.3 完整代码实现

3.3.1 项目结构

multi_agent_project/
├── main.py                 # 主程序入口
├── state.py                # 状态定义
├── agents/
│   ├── __init__.py
│   ├── product_manager.py  # 产品经理 Agent
│   ├── architect.py        # 架构师 Agent
│   └── programmer.py       # 程序员 Agent
├── graph.py                # 工作流图定义
├── prompts/
│   ├── pm_prompt.py        # 产品经理提示词
│   ├── arch_prompt.py      # 架构师提示词
│   └── dev_prompt.py       # 程序员提示词
└── requirements.txt

3.3.2 状态定义

# state.py
from typing import TypedDict, Annotated, List, Optional
import operator

class AgentMessage(TypedDict):
    """Agent 消息结构"""
    agent: str           # 发送者
    content: str         # 消息内容
    message_type: str    # 消息类型:analysis/design/code/review

class DevelopmentState(TypedDict):
    """开发工作流状态"""

    # 输入
    user_requirement: str                    # 用户原始需求

    # 产品经理输出
    requirement_doc: str                     # 需求文档
    user_stories: List[str]                  # 用户故事列表
    feature_list: List[str]                  # 功能列表

    # 架构师输出
    tech_stack: str                          # 技术栈选择
    module_design: str                       # 模块设计
    api_design: str                          # API 设计

    # 程序员输出
    code_files: dict                         # 代码文件 {filename: content}
    test_cases: List[str]                    # 测试用例

    # 协作状态
    messages: Annotated[List[AgentMessage], operator.add]  # 消息历史
    current_stage: str                       # 当前阶段
    iteration_count: int                     # 迭代次数
    approved: bool                           # 是否通过

    # 决策
    next_agent: Optional[str]                # 下一个要调用的 Agent
    feedback: Optional[str]                  # 反馈意见

3.3.3 提示词模板

# prompts/pm_prompt.py

PRODUCT_MANAGER_SYSTEM = """你是一位资深的产品经理,拥有10年的产品规划经验。

你的职责是:
1. 理解并分析用户需求
2. 编写清晰的需求文档
3. 拆分用户故事
4. 列出功能清单

你的输出风格:
- 结构化、条理清晰
- 使用 Markdown 格式
- 关注用户价值而非技术实现

当你需要与架构师讨论时,在消息中明确标注:
[DISCUSS] 需要讨论的问题...
"""

PRODUCT_MANAGER_TEMPLATE = """
## 用户需求
{user_requirement}

## 已有讨论记录
{messages}

## 任务
请分析上述需求,输出:
1. 需求概述(一段话总结)
2. 用户故事列表(作为XX,我希望XX,以便XX)
3. 功能清单(按优先级排序)
4. 非功能性需求(性能、安全等)

如果你认为需求足够清晰,输出 [APPROVED] 标记。
如果需要进一步讨论,输出 [DISCUSS] 标记并说明问题。
"""
# prompts/arch_prompt.py

ARCHITECT_SYSTEM = """你是一位资深的技术架构师,拥有15年的系统设计经验。

你的职责是:
1. 根据需求选择合适的技术栈
2. 设计系统模块结构
3. 定义接口规范
4. 考虑性能、扩展性、安全性

你的输出风格:
- 技术方案具体可行
- 包含架构图描述(用 ASCII 或文字描述)
- 接口设计符合 RESTful 规范
"""

ARCHITECT_TEMPLATE = """
## 需求文档
{requirement_doc}

## 功能清单
{feature_list}

## 已有讨论记录
{messages}

## 任务
请根据需求设计技术方案,输出:
1. 技术栈选择(语言、框架、数据库、中间件)
2. 系统架构设计(模块划分、关系图)
3. 核心接口定义(API 路径、方法、参数、返回值)
4. 数据库表设计(核心表结构)

如果你认为设计足够完善,输出 [APPROVED] 标记。
如果需要与产品经理讨论,输出 [DISCUSS] 标记并说明问题。
"""
# prompts/dev_prompt.py

PROGRAMMER_SYSTEM = """你是一位全栈程序员,精通多种编程语言和框架。

你的职责是:
1. 根据设计文档实现代码
2. 编写单元测试
3. 确保代码质量

你的编码风格:
- 代码规范、注释清晰
- 遵循 SOLID 原则
- 包含错误处理
- 编写可测试的代码
"""

PROGRAMMER_TEMPLATE = """
## 技术栈
{tech_stack}

## 模块设计
{module_design}

## API 设计
{api_design}

## 已有讨论记录
{messages}

## 任务
请根据设计实现代码,输出:
1. 项目结构(目录树)
2. 核心代码文件(每个文件用 ```language 标注)
3. 单元测试代码
4. 运行说明

如果你认为代码实现完成,输出 [COMPLETED] 标记。
如果需要修改设计,输出 [NEED_REVISION] 标记并说明问题。
"""

3.3.4 Agent 实现

# agents/product_manager.py
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from typing import Dict
import json
import re

class ProductManagerAgent:
    """产品经理 Agent"""

    def __init__(self, model: str = "gpt-4"):
        self.llm = ChatOpenAI(model=model, temperature=0.3)
        self.name = "产品经理"

    def process(self, state: Dict) -> Dict:
        """处理需求分析"""
        from prompts.pm_prompt import PRODUCT_MANAGER_SYSTEM, PRODUCT_MANAGER_TEMPLATE

        # 构建消息历史
        messages_str = self._format_messages(state.get("messages", []))

        # 构建提示
        prompt = ChatPromptTemplate.from_messages([
            ("system", PRODUCT_MANAGER_SYSTEM),
            ("human", PRODUCT_MANAGER_TEMPLATE)
        ])

        chain = prompt | self.llm

        # 执行
        result = chain.invoke({
            "user_requirement": state["user_requirement"],
            "messages": messages_str
        })

        content = result.content

        # 解析输出
        output = self._parse_output(content)

        # 判断是否批准
        approved = "[APPROVED]" in content
        need_discuss = "[DISCUSS]" in content

        return {
            "requirement_doc": output.get("requirement_doc", ""),
            "user_stories": output.get("user_stories", []),
            "feature_list": output.get("feature_list", []),
            "messages": [{
                "agent": self.name,
                "content": content,
                "message_type": "analysis"
            }],
            "current_stage": "requirement_analysis",
            "approved": approved,
            "next_agent": "architect" if approved else "product_manager",
            "feedback": output.get("discussion_points") if need_discuss else None
        }

    def _format_messages(self, messages: list) -> str:
        """格式化消息历史"""
        formatted = []
        for msg in messages:
            formatted.append(f"[{msg['agent']}]: {msg['content']}")
        return "\n\n".join(formatted)

    def _parse_output(self, content: str) -> dict:
        """解析输出内容"""
        output = {}

        # 提取需求概述
        overview_match = re.search(r'需求概述[::]\s*(.+?)(?=\n\d|##)', content, re.DOTALL)
        if overview_match:
            output["requirement_doc"] = overview_match.group(1).strip()

        # 提取用户故事
        stories = re.findall(r'作为.+?,希望.+?,以便.+?', content)
        output["user_stories"] = stories

        # 提取功能列表
        features = re.findall(r'^\d+\.\s*(.+)$', content, re.MULTILINE)
        output["feature_list"] = [f.strip() for f in features if f.strip()]

        return output
# agents/architect.py
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from typing import Dict
import re

class ArchitectAgent:
    """架构师 Agent"""

    def __init__(self, model: str = "gpt-4"):
        self.llm = ChatOpenAI(model=model, temperature=0.2)
        self.name = "架构师"

    def process(self, state: Dict) -> Dict:
        """处理架构设计"""
        from prompts.arch_prompt import ARCHITECT_SYSTEM, ARCHITECT_TEMPLATE

        # 构建消息历史
        messages_str = self._format_messages(state.get("messages", []))

        # 构建提示
        prompt = ChatPromptTemplate.from_messages([
            ("system", ARCHITECT_SYSTEM),
            ("human", ARCHITECT_TEMPLATE)
        ])

        chain = prompt | self.llm

        # 执行
        result = chain.invoke({
            "requirement_doc": state.get("requirement_doc", ""),
            "feature_list": "\n".join(state.get("feature_list", [])),
            "messages": messages_str
        })

        content = result.content

        # 解析输出
        output = self._parse_output(content)

        # 判断状态
        approved = "[APPROVED]" in content
        need_discuss = "[DISCUSS]" in content

        return {
            "tech_stack": output.get("tech_stack", ""),
            "module_design": output.get("module_design", ""),
            "api_design": output.get("api_design", ""),
            "messages": [{
                "agent": self.name,
                "content": content,
                "message_type": "design"
            }],
            "current_stage": "architecture_design",
            "approved": approved,
            "next_agent": "programmer" if approved else "product_manager",
            "feedback": output.get("discussion_points") if need_discuss else None
        }

    def _format_messages(self, messages: list) -> str:
        formatted = []
        for msg in messages:
            formatted.append(f"[{msg['agent']}]: {msg['content']}")
        return "\n\n".join(formatted)

    def _parse_output(self, content: str) -> dict:
        output = {}

        # 提取技术栈
        tech_match = re.search(r'技术栈[::]\s*(.+?)(?=\n\d|##|\n\n)', content, re.DOTALL)
        if tech_match:
            output["tech_stack"] = tech_match.group(1).strip()

        # 提取模块设计
        module_match = re.search(r'(?:系统架构|模块设计)[::]\s*(.+?)(?=接口|API|##)', content, re.DOTALL)
        if module_match:
            output["module_design"] = module_match.group(1).strip()

        # 提取 API 设计
        api_match = re.search(r'(?:接口定义|API设计)[::]\s*(.+?)(?=数据库|##|$)', content, re.DOTALL)
        if api_match:
            output["api_design"] = api_match.group(1).strip()

        return output
# agents/programmer.py
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from typing import Dict
import re

class ProgrammerAgent:
    """程序员 Agent"""

    def __init__(self, model: str = "gpt-4"):
        self.llm = ChatOpenAI(model=model, temperature=0.1)
        self.name = "程序员"

    def process(self, state: Dict) -> Dict:
        """处理代码实现"""
        from prompts.dev_prompt import PROGRAMMER_SYSTEM, PROGRAMMER_TEMPLATE

        # 构建消息历史
        messages_str = self._format_messages(state.get("messages", []))

        # 构建提示
        prompt = ChatPromptTemplate.from_messages([
            ("system", PROGRAMMER_SYSTEM),
            ("human", PROGRAMMER_TEMPLATE)
        ])

        chain = prompt | self.llm

        # 执行
        result = chain.invoke({
            "tech_stack": state.get("tech_stack", ""),
            "module_design": state.get("module_design", ""),
            "api_design": state.get("api_design", ""),
            "messages": messages_str
        })

        content = result.content

        # 解析输出
        output = self._parse_output(content)

        # 判断状态
        completed = "[COMPLETED]" in content
        need_revision = "[NEED_REVISION]" in content

        return {
            "code_files": output.get("code_files", {}),
            "test_cases": output.get("test_cases", []),
            "messages": [{
                "agent": self.name,
                "content": content,
                "message_type": "code"
            }],
            "current_stage": "code_implementation",
            "approved": completed,
            "next_agent": END if completed else "architect",
            "feedback": output.get("revision_points") if need_revision else None
        }

    def _format_messages(self, messages: list) -> str:
        formatted = []
        for msg in messages:
            formatted.append(f"[{msg['agent']}]: {msg['content']}")
        return "\n\n".join(formatted)

    def _parse_output(self, content: str) -> dict:
        output = {}

        # 提取代码文件
        code_blocks = re.findall(r'```(\w+)?\n?([^`]+)```', content, re.DOTALL)

        # 尝试提取文件名
        file_patterns = re.findall(r'(?:文件名|File)[::]\s*`?([^`\n]+)`?', content)

        code_files = {}
        for i, (lang, code) in enumerate(code_blocks):
            if i < len(file_patterns):
                filename = file_patterns[i].strip()
            else:
                filename = f"file_{i+1}.py" if lang == 'python' else f"file_{i+1}.{lang or 'txt'}"
            code_files[filename] = code.strip()

        output["code_files"] = code_files

        # 提取测试用例
        test_match = re.search(r'测试[用例]?[::]\s*(.+?)(?=运行说明|##|$)', content, re.DOTALL)
        if test_match:
            output["test_cases"] = [test_match.group(1).strip()]

        return output

3.3.5 工作流图定义

# graph.py
from langgraph.graph import StateGraph, END, START
from langgraph.checkpoint.memory import MemorySaver
from state import DevelopmentState
from agents.product_manager import ProductManagerAgent
from agents.architect import ArchitectAgent
from agents.programmer import ProgrammerAgent
from typing import Literal

class DevelopmentWorkflow:
    """开发工作流"""

    def __init__(self, model: str = "gpt-4"):
        # 初始化 Agent
        self.pm_agent = ProductManagerAgent(model)
        self.arch_agent = ArchitectAgent(model)
        self.dev_agent = ProgrammerAgent(model)

        # 构建图
        self.graph = self._build_graph()

    def _build_graph(self) -> StateGraph:
        """构建工作流图"""

        # 创建构建器
        builder = StateGraph(DevelopmentState)

        # 添加节点
        builder.add_node("product_manager", self._pm_node)
        builder.add_node("architect", self._arch_node)
        builder.add_node("programmer", self._dev_node)

        # 添加边
        builder.add_edge(START, "product_manager")

        # 条件边:产品经理 -> 架构师 或 继续分析
        builder.add_conditional_edges(
            "product_manager",
            self._pm_router,
            {
                "architect": "architect",
                "continue": "product_manager"  # 需要更多分析
            }
        )

        # 条件边:架构师 -> 程序员 或 回到产品经理讨论
        builder.add_conditional_edges(
            "architect",
            self._arch_router,
            {
                "programmer": "programmer",
                "product_manager": "product_manager",  # 需要讨论需求
                "continue": "architect"  # 需要修改设计
            }
        )

        # 条件边:程序员 -> 结束 或 回到架构师
        builder.add_conditional_edges(
            "programmer",
            self._dev_router,
            {
                "end": END,
                "architect": "architect"  # 需要修改设计
            }
        )

        return builder.compile(checkpointer=MemorySaver())

    def _pm_node(self, state: DevelopmentState) -> dict:
        """产品经理节点"""
        print("\n" + "="*60)
        print("📋 产品经理正在分析需求...")
        print("="*60)

        result = self.pm_agent.process(state)

        print(f"\n需求文档:\n{result.get('requirement_doc', 'N/A')}")
        print(f"\n用户故事:\n" + "\n".join(f"- {s}" for s in result.get('user_stories', [])))
        print(f"\n功能列表:\n" + "\n".join(f"- {f}" for f in result.get('feature_list', [])))

        if result.get('approved'):
            print("\n✅ 需求分析完成,交给架构师...")
        elif result.get('feedback'):
            print(f"\n🔄 需要讨论: {result['feedback']}")

        return result

    def _arch_node(self, state: DevelopmentState) -> dict:
        """架构师节点"""
        print("\n" + "="*60)
        print("🏗️ 架构师正在进行技术设计...")
        print("="*60)

        result = self.arch_agent.process(state)

        print(f"\n技术栈:\n{result.get('tech_stack', 'N/A')}")
        print(f"\n模块设计:\n{result.get('module_design', 'N/A')[:500]}...")
        print(f"\nAPI 设计:\n{result.get('api_design', 'N/A')[:500]}...")

        if result.get('approved'):
            print("\n✅ 架构设计完成,交给程序员...")
        elif result.get('feedback'):
            print(f"\n🔄 需要讨论: {result['feedback']}")

        return result

    def _dev_node(self, state: DevelopmentState) -> dict:
        """程序员节点"""
        print("\n" + "="*60)
        print("💻 程序员正在编写代码...")
        print("="*60)

        result = self.dev_agent.process(state)

        code_files = result.get('code_files', {})
        print(f"\n生成了 {len(code_files)} 个代码文件:")
        for filename in code_files.keys():
            print(f"  - {filename}")

        if result.get('approved'):
            print("\n✅ 代码实现完成!")
        elif result.get('feedback'):
            print(f"\n🔄 需要修改: {result['feedback']}")

        return result

    def _pm_router(self, state: DevelopmentState) -> Literal["architect", "continue"]:
        """产品经理路由"""
        if state.get("approved") and state.get("current_stage") == "requirement_analysis":
            return "architect"
        return "continue"

    def _arch_router(self, state: DevelopmentState) -> Literal["programmer", "product_manager", "continue"]:
        """架构师路由"""
        if state.get("approved") and state.get("current_stage") == "architecture_design":
            return "programmer"
        if state.get("feedback"):
            return "product_manager"
        return "continue"

    def _dev_router(self, state: DevelopmentState) -> Literal["end", "architect"]:
        """程序员路由"""
        if state.get("approved"):
            return "end"
        return "architect"

    def run(self, requirement: str, thread_id: str = "default"):
        """执行工作流"""
        initial_state = {
            "user_requirement": requirement,
            "messages": [],
            "iteration_count": 0,
            "approved": False
        }

        config = {"configurable": {"thread_id": thread_id}}

        return self.graph.invoke(initial_state, config=config)

3.3.6 主程序入口

# main.py
import os
from dotenv import load_dotenv
from graph import DevelopmentWorkflow

# 加载环境变量
load_dotenv()

def main():
    """主程序入口"""

    print("""
╔═══════════════════════════════════════════════════════════╗
║                                                           ║
║     🤖 Multi-Agent 软件开发协作系统                        ║
║     产品经理 + 架构师 + 程序员                             ║
║                                                           ║
╚═══════════════════════════════════════════════════════════╝
    """)

    # 获取用户需求
    print("请输入您的需求(输入 exit 退出):")

    while True:
        requirement = input("\n需求 > ").strip()

        if requirement.lower() == "exit":
            print("再见!")
            break

        if not requirement:
            print("请输入有效的需求描述")
            continue

        # 创建工作流
        workflow = DevelopmentWorkflow(model="gpt-4")

        # 执行
        print("\n🚀 开始协作开发流程...")
        result = workflow.run(requirement)

        # 输出最终结果
        print("\n" + "="*60)
        print("📊 最终输出")
        print("="*60)

        print("\n📁 生成的代码文件:")
        for filename, content in result.get("code_files", {}).items():
            print(f"\n--- {filename} ---")
            print(content[:500] + "..." if len(content) > 500 else content)

        print("\n" + "="*60)
        print("✨ 协作完成!")
        print("="*60)

if __name__ == "__main__":
    main()

3.3.7 依赖文件

# requirements.txt
langgraph>=0.2.0
langchain>=0.3.0
langchain-openai>=0.2.0
python-dotenv>=1.0.0

4. 运行示例

4.1 示例输入

需求 > 我需要开发一个待办事项(Todo)应用,支持添加、删除、编辑、标记完成等功能,数据需要持久化存储,支持多用户。

4.2 执行过程

╔═══════════════════════════════════════════════════════════╗
║     🤖 Multi-Agent 软件开发协作系统                        ║
║     产品经理 + 架构师 + 程序员                             ║
╚═══════════════════════════════════════════════════════════╝

🚀 开始协作开发流程...

============================================================
📋 产品经理正在分析需求...
============================================================

需求文档:
开发一个多用户待办事项管理应用,核心功能包括任务的增删改查、状态管理、数据持久化和用户隔离。

用户故事:
- 作为用户,我希望能够创建新的待办事项,以便记录需要完成的任务
- 作为用户,我希望能够编辑待办事项,以便修改任务内容或截止日期
- 作为用户,我希望能够删除待办事项,以便清理不需要的任务
- 作为用户,我希望能够标记任务完成状态,以便追踪进度
- 作为用户,我希望我的数据独立存储,以便保护隐私

功能列表:
1. 用户注册/登录功能
2. 创建待办事项(标题、描述、优先级、截止日期)
3. 编辑待办事项
4. 删除待办事项
5. 标记完成/未完成
6. 任务列表展示(支持筛选排序)
7. 数据持久化存储

✅ 需求分析完成,交给架构师...

============================================================
🏗️ 架构师正在进行技术设计...
============================================================

技术栈:
- 后端: Python + FastAPI
- 数据库: PostgreSQL + SQLAlchemy ORM
- 认证: JWT Token
- 前端: Vue.js 3 + Element Plus

模块设计:
├── backend/
│   ├── main.py           # FastAPI 入口
│   ├── models/           # 数据模型
│   ├── routes/           # API 路由
│   ├── services/         # 业务逻辑
│   └── utils/            # 工具函数
├── frontend/
│   ├── src/
│   │   ├── views/        # 页面组件
│   │   ├── components/   # 公共组件
│   │   └── api/          # API 调用

API 设计:
POST   /api/auth/register   # 用户注册
POST   /api/auth/login      # 用户登录
GET    /api/todos           # 获取待办列表
POST   /api/todos           # 创建待办
PUT    /api/todos/{id}      # 更新待办
DELETE /api/todos/{id}      # 删除待办

✅ 架构设计完成,交给程序员...

============================================================
💻 程序员正在编写代码...
============================================================

生成了 5 个代码文件:
  - models.py
  - main.py
  - routes.py
  - services.py
  - test_todos.py

============================================================
📊 最终输出
============================================================

📁 生成的代码文件:

--- models.py ---
from sqlalchemy import Column, Integer, String, Boolean, DateTime, ForeignKey
from sqlalchemy.orm import relationship
from database import Base
from datetime import datetime

class User(Base):
    __tablename__ = "users"
    id = Column(Integer, primary_key=True, index=True)
    username = Column(String, unique=True, index=True)
    email = Column(String, unique=True, index=True)
    hashed_password = Column(String)
    todos = relationship("Todo", back_populates="owner")

class Todo(Base):
    __tablename__ = "todos"
    id = Column(Integer, primary_key=True, index=True)
    title = Column(String, index=True)
    description = Column(String, nullable=True)
    completed = Column(Boolean, default=False)
    priority = Column(String, default="medium")
    due_date = Column(DateTime, nullable=True)
    created_at = Column(DateTime, default=datetime.utcnow)
    owner_id = Column(Integer, ForeignKey("users.id"))
    owner = relationship("User", back_populates="todos")
...

============================================================
✨ 协作完成!
============================================================

5. 高级特性

5.1 人工干预(Human-in-the-Loop)

# 在关键节点添加人工审核
from langgraph.prebuilt import ToolNode

def human_review_node(state: DevelopmentState) -> dict:
    """人工审核节点"""
    print("\n📋 请审核以下内容:")
    print(state.get("requirement_doc", ""))

    approval = input("\n是否批准?(y/n): ")

    return {
        "approved": approval.lower() == "y",
        "feedback": None if approval.lower() == "y" else "请修改需求"
    }

# 添加到图中
builder.add_node("human_review", human_review_node)
builder.add_edge("product_manager", "human_review")

5.2 状态持久化

from langgraph.checkpoint.sqlite import SqliteSaver

# 使用 SQLite 持久化
with SqliteSaver("checkpoints.db") as checkpointer:
    graph = builder.compile(checkpointer=checkpointer)

    # 恢复执行
    result = graph.invoke(
        initial_state,
        config={"configurable": {"thread_id": "session_123"}}
    )

5.3 流式输出

async def run_stream(requirement: str):
    """流式执行"""
    async for event in graph.astream_events(
        {"user_requirement": requirement},
        version="v1"
    ):
        if event["event"] == "on_chain_start":
            print(f"\n🔄 开始: {event['name']}")
        elif event["event"] == "on_chain_end":
            print(f"✅ 完成: {event['name']}")

6. 架构对比

6.1 与其他框架对比

特性LangGraphCrewAIAutoGen
状态管理内置、可视化简单对话式
循环支持✅ 原生支持⚠️ 有限✅ 支持
条件分支✅ 原生支持⚠️ 有限⚠️ 通过对话
人工干预✅ 原生支持⚠️ 有限✅ 支持
持久化✅ 内置❌ 需自建⚠️ 需配置
调试能力✅ LangSmith⚠️ 有限⚠️ 有限
学习曲线

6.2 适用场景

LangGraph 适用场景:
├── 需要精确控制工作流
├── 需要状态持久化
├── 需要支持循环和分支
├── 需要人工干预点
└── 需要生产级部署

CrewAI 适用场景:
├── 快速原型开发
├── 角色扮演式协作
└── 简单的多 Agent 任务

AutoGen 适用场景:
├── 对话式交互
├── 代码生成场景
└── 研究/实验项目

7. 最佳实践

7.1 状态设计原则

# ✅ 好的状态设计
class GoodState(TypedDict):
    # 输入输出清晰分离
    user_input: str
    final_output: str

    # 中间状态最小化
    current_step: str

    # 使用 Annotated 处理累加
    messages: Annotated[list, operator.add]

# ❌ 不好的状态设计
class BadState(TypedDict):
    everything: dict  # 太笼统
    temp_data: list   # 不明确用途
    # 缺少类型注解

7.2 节点职责单一

# ✅ 好的节点设计
def analyze_node(state: State) -> dict:
    """只做分析,返回分析结果"""
    result = analyze(state["input"])
    return {"analysis": result}

def generate_node(state: State) -> dict:
    """只做生成,使用分析结果"""
    result = generate(state["analysis"])
    return {"output": result}

# ❌ 不好的节点设计
def do_everything_node(state: State) -> dict:
    """什么都做,难以维护"""
    analysis = analyze(state["input"])
    output = generate(analysis)
    return {"output": output}  # 丢失中间状态

7.3 错误处理

from langgraph.pregel import GraphRecursionError

def safe_invoke(workflow, requirement: str):
    """安全的执行入口"""
    try:
        result = workflow.run(requirement)
        return result
    except GraphRecursionError:
        print("⚠️ 达到最大迭代次数")
        return {"error": "max_iterations_reached"}
    except Exception as e:
        print(f"⚠️ 执行出错: {e}")
        return {"error": str(e)}

8. GitHub 项目推荐

项目描述链接
LangGraph核心框架github.com/langchain-a…
LangGraph SwarmSwarm 架构扩展github.com/langchain-a…
LangGraph4jJava 版本github.com/langgraph4j…
LangGraph Templates官方模板github.com/langchain-a…

总结

本文通过一个完整的实战案例,演示了如何使用 LangGraph 构建多智能体协作系统:

  1. 架构设计:选择 Supervisor 模式,由工作流控制 Agent 调用顺序
  2. 状态管理:使用 TypedDict 定义清晰的状态结构
  3. 节点实现:每个 Agent 作为独立节点,职责单一
  4. 条件路由:根据状态动态决定下一步
  5. 循环支持:支持迭代修改,直到满足条件

关键收益

  • 需求分析 → 架构设计 → 代码实现,全流程自动化
  • Agent 间可以"讨论"和"反馈"
  • 状态可追溯,便于调试
  • 支持人工干预点


欢迎关注的我的公众号《码上未来》,一起交流AI前沿技术!

添加我微信 return_not_null 进群聊AI