LangChain4j + Spring Boot 多智能体协调架构原理深度解析

前言

LangChain4j 是 Java 生态中比较成熟的 LLM 应用开发框架,提供了丰富的多智能体协调能力。本文以一个《部落冲突》玩家分析系统为载体,深入剖析 LangChain4j 中 @SupervisorAgentAgenticServices、工具绑定机制、内存管理、消息编排等核心组件的工作原理与实现细节。具体效果展示部落冲突玩家,可以前往微信 coc计算器小程序体验下。以下是具体的实现。

💡 前情回顾 如果你想先了解框架Spring AI的落地应用,欢迎阅读我之前的文章:

一、核心组件全景图

text

scss 复制代码
┌─────────────────────────────────────────────────────────────────┐
│                        LangChain4j Multi-Agent                  │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │              SupervisorAgent (协调层)                     │   │
│  │  @SupervisorAgent(subAgents = {...})                      │   │
│  │  - 意图识别与任务分发                                      │   │
│  │  - 并行/串行子Agent调用                                    │   │
│  │  - 结果聚合与JSON输出                                      │   │
│  └─────────────────────────────────────────────────────────┘   │
│                              │                                   │
│          ┌───────────────────┼───────────────────┐              │
│          ▼                   ▼                   ▼              │
│  ┌──────────────┐   ┌──────────────┐   ┌──────────────┐      │
│  │ DataSummary   │   │ Upgrade      │   │ Battle       │      │
│  │ Agent         │   │ Planner      │   │ Tactics      │      │
│  │               │   │ Agent        │   │ Agent        │      │
│  └──────────────┘   └──────────────┘   └──────────────┘      │
│          │                   │                   │              │
│          └───────────────────┴───────────────────┘              │
│                              │                                   │
│                              ▼                                   │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │                   Tool Execution Layer                   │   │
│  │  @Tool 注解方法 → PlayerDataTool → DAO → Database       │   │
│  └─────────────────────────────────────────────────────────┘   │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

二、@SupervisorAgent 注解详解

2.1 注解定义与元数据

@SupervisorAgent 是 LangChain4j 提供的核心协调注解,用于声明一个接口为监督者智能体:

java

less 复制代码
@SupervisorAgent(
    subAgents = {
        BattleTacticsAgent.class,
        DataSummaryAgent.class,
        DefenseTacticsAgent.class,
        UpgradePlannerAgent.class
    }
)
@SystemMessage("""
    # Role:部落冲突(CoC)高级参谋长

    ## 核心职责
    1. 分析用户的请求意图,找出需要执行哪些分析模块。
    2. 并行调用对应的子 Agent 来获取数据。
    3. 收集所有子 Agent 的结果,严格按照 JSON 格式输出最终报告。
    """)
String answer(@V("openId") String openId, @UserMessage String request);

注解参数解析

参数 类型 作用
subAgents Class<?>[] 声明该Supervisor管辖的子Agent类型数组
supervisorResponseStrategy SupervisorResponseStrategy 结果聚合策略,默认实现为JSON拼接
supervisorResponseStrategy SupervisorResponseStrategy 结果聚合策略,为可选的 enum 值,默认 LAST
maxAgentsInvocations int 单次执行中最大子Agent调用次数,默认 10

注意 :LangChain4j 1.12 版本中,@SupervisorAgent 的推荐用法是用 @SubAgent 注解嵌套声明子Agent及其 outputKey。上面的数组写法当前可用,但后续可能会变为 Deprecated,建议关注官方文档的更新。

2.2 Supervisor 的工作原理

当调用 supervisor.answer(openId, request) 时,LangChain4j 内部经历以下流程:

text

markdown 复制代码
1. 用户消息进入
        │
        ▼
2. Supervisor 接收 UserMessage,解析 @V 注解绑定变量
        │
        ▼
3. Supervisor 的 LLM 分析意图,决定调用哪些子Agent
        │
        ├──→ 子Agent1.answer()  ──→ 并行执行
        ├──→ 子Agent2.answer()  ──→ 并行执行
        ├──→ 子Agent3.answer()  ──→ 并行执行
        │
        ▼
4. 收集所有子Agent返回结果
        │
        ▼
5. 根据 SupervisorResponseStrategy 聚合结果
        │
        ▼
6. 输出最终JSON响应

2.3 SupervisorResponseStrategy 聚合策略

LangChain4j 提供了三种内置聚合策略:

java

arduino 复制代码
public enum SupervisorResponseStrategy {
    LAST,        // 默认:仅返回最后调用的子Agent的最终响应
    SUMMARY,     // 返回Supervisor与其子Agent交互的摘要
    SCORED       // 使用内部LLM对最后响应和摘要分别打分,返回得分高者
}

在业务代码中,可以这样配置:

java

scss 复制代码
@Bean
public SuperAgent cocSupervisor(ChatModel chatModel,
                                 DataSummaryAgent dataSummaryAgent,
                                 UpgradePlannerAgent upgradePlannerAgent,
                                 BattleTacticsAgent battleTacticsAgent,
                                 DefenseTacticsAgent defenseTacticsAgent) {

    return AgenticServices.supervisorBuilder(SuperAgent.class)
            .chatModel(chatModel)
            .subAgents(dataSummaryAgent, upgradePlannerAgent,
                       battleTacticsAgent, defenseTacticsAgent)
            // 可选:指定聚合策略(默认为 LAST)
            .supervisorResponseStrategy(SupervisorResponseStrategy.SUMMARY)
            .build();
}

三、AgenticServices 工厂解析

3.1 整体架构

AgenticServices 是 LangChain4j 提供的能力工厂类,通过 Builder 模式创建各类 AI 服务:

java

csharp 复制代码
public class AgenticServices {

    // 通用AI服务构建器
    public static <T> AiServicesBuilder<T> builder(Class<T> interfaceClass) {
        return new AiServicesBuilder<>(interfaceClass);
    }

    // 工具型Agent构建器(用于带@Tool注解的Agent)
    public static <T> AgentBuilder<T, ?> agentBuilder(Class<T> agentServiceClass) {
        return new AgentBuilder<>(agentServiceClass);
    }

    // Supervisor构建器
    public static <T> SupervisorAgentService<T> supervisorBuilder(Class<T> agentServiceClass) {
        return new SupervisorAgentService<>(agentServiceClass);
    }
}

3.2 AgentBuilder 内部机制

java

typescript 复制代码
public class AgentBuilder<T, SELF extends AgentBuilder<T, SELF>> {

    private final Class<T> agentServiceClass;
    private ChatModel chatModel;
    private SystemMessageProvider systemMessageProvider;
    private List<Object> tools = new ArrayList<>();
    private ChatMemory chatMemory;
    private ChatMemoryProvider chatMemoryProvider;
    private ContentRetriever contentRetriever;

    // 关键方法:注册可调用工具
    public SELF tools(Object... tools) {
        this.tools.addAll(Arrays.asList(tools));
        return self();
    }

    // 关键方法:注册系统消息提供器
    public SELF systemMessageProvider(
            SystemMessageProvider provider) {
        this.systemMessageProvider = provider;
        return self();
    }

    // 最终build()方法
    public T build() {
        // 1. 通过动态代理创建接口实现
        // 2. 绑定chatModel、tools、memory等组件
        // 3. 注册到Spring容器(如在@Configuration中使用@Bean)
        return (T) Proxy.newProxyInstance(
            agentServiceClass.getClassLoader(),
            new Class[]{agentServiceClass},
            new AgentInvocationHandler(this)
        );
    }
}

说明 :LangChain4j 内部的具体类名和包路径可能随版本变化(如 AgenticServicesBuilder 可能更名为 AgentBuilder),但 Builder 模式的核心逻辑保持一致。上面代码是基于 1.12.2-beta22 版本行为的抽象描述。

3.3 动态代理机制

LangChain4j 使用 Java 动态代理实现接口,当调用 agent.answer() 时:

java

typescript 复制代码
public class AgentInvocationHandler implements InvocationHandler {

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        // 1. 提取@SystemMessage和@UserMessage注解
        SystemMessage sysMsg = method.getAnnotation(SystemMessage.class);
        UserMessage userMsg = method.getAnnotation(UserMessage.class);

        // 2. 从@V注解提取变量绑定
        Map<String, Object> variables = extractVariables(method, args);

        // 3. 获取系统消息(可能通过provider动态获取)
        String systemMessage = systemMessageProvider.provide(memoryId);

        // 4. 构建最终Prompt
        String prompt = buildPrompt(systemMessage, userMsgTemplate, variables);

        // 5. 调用ChatModel
        AiMessage response = chatModel.sendUserMessage(prompt);

        // 6. 检查是否需要执行工具
        if (response.hasToolCalls()) {
            return executeToolCalls(response.toolCalls(), tools);
        }

        // 7. 直接返回文本结果
        return response.text();
    }
}

四、工具绑定机制(@Tool)

4.1 注解定义

java

less 复制代码
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Tool {
    String name() default "";
    String description() default "";
}

4.2 工具注册与调用流程

java

typescript 复制代码
// 1. 定义工具类
public class PlayerDataTool {

    @Tool(name = "queryPlayerBuildInfo", 
          description = "根据openid查询玩家所有建筑升级数据")
    public String queryPlayerBuildInfo(String openid) {
        // 实现查询逻辑
        return buildInfoDao.selectByOpenid(openid);
    }

    @Tool(name = "queryBuildLevel",
          description = "根据openid和建筑名称查询玩家该建筑当前等级")
    public String queryBuildLevel(String openid, String buildName) {
        // 实现查询逻辑
        return buildLevelDao.selectLevel(openid, buildName);
    }
}
// 注:@Tool注解的name和description属性均可省略。
// 省略name时默认使用方法名;省略description时使用name作为tool description。

// 2. 注册到Agent
@Bean
public DataSummaryAgent dataSummaryAgent(ChatModel chatModel) {
    return AgenticServices.agentBuilder(DataSummaryAgent.class)
            .chatModel(chatModel)
            .tools(playerDataTool)  // ← 工具绑定
            .build();
}

4.3 工具调用的内部实现

当 LLM 返回 AiMessage 包含工具调用时:

java

scss 复制代码
// AgentInvocationHandler.invoke() 中的工具执行逻辑
if (response.hasToolCalls()) {
    List<ToolExecution> executions = new ArrayList<>();
    for (ToolCall toolCall : response.toolCalls()) {
        // 1. 根据toolCall.name()查找对应的@Tool方法
        Method toolMethod = findToolMethod(toolCall.name());

        // 2. 反序列化参数
        Object[] params = deserializeArguments(toolCall.arguments(), toolMethod);

        // 3. 反射调用
        Object result = toolMethod.invoke(toolObject, params);

        // 4. 包装结果
        executions.add(new ToolExecution(toolCall.id(), result));
    }

    // 5. 将工具结果反馈给LLM生成最终回复
    return chatModel.sendToolResults(executions);
}

4.4 工具选择的LLM引导

LangChain4j 会自动将 @Tool 方法的签名和描述注入到 System Prompt 中:

text

arduino 复制代码
你是一个AI助手。你可以使用以下工具:

- queryPlayerBuildInfo(openid: String): String
  根据openid查询玩家所有建筑升级数据

- queryBuildLevel(openid: String, buildName: String): String
  根据openid和建筑名称查询玩家该建筑当前等级

当你需要查询玩家数据时,请调用合适的工具。

五、系统消息与内存管理

5.1 SystemMessage 注解

java

less 复制代码
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface SystemMessage {
    String value() default "";
}

在接口定义时使用:

java

python 复制代码
public interface BattleTacticsAgent {

    @SystemMessage("""
        # Role:部落冲突进攻战术专家

        # 任务
        分析当前版本主流进攻流派,给出配兵建议和打法思路。

        # 输出格式
        ### ⚔️ 流派名称
        * **兵种与数量**:...
        """)
    String recommendTactics(String openid);
}

5.2 动态 SystemMessageProvider

最强大的特性是可以动态提供 System Message:

java

kotlin 复制代码
@Bean
public DataSummaryAgent dataSummaryAgent(ChatModel chatModel) {
    return AgenticServices.agentBuilder(DataSummaryAgent.class)
            .chatModel(chatModel)
            .systemMessageProvider(memoryId -> {
                // memoryId 可以用于区分不同会话
                // 此处从Redis动态加载Prompt
                return stringRedisTemplate.opsForValue()
                    .get("ai:prompt:module1:" + memoryId);
            })
            .tools(playerDataTool)
            .build();
}

应用场景

  1. 多租户Prompt隔离:不同用户加载不同Prompt模板
  2. AB测试:对不同用户群使用不同策略
  3. Prompt热更新:无需重启即可更新Prompt内容
  4. 会话历史注入:根据memoryId加载历史上下文

5.3 Memory 组件

LangChain4j 的 Memory 用于维护多轮对话状态:

java

csharp 复制代码
public interface ChatMemory {
    // 获取对话历史
    List<ChatMessage> messages();

    // 添加消息到历史
    void add(ChatMessage message);

    // 清除历史
    void clear();
}

默认实现:MessageWindowChatMemory

java

java 复制代码
public class MessageWindowChatMemory implements ChatMemory {

    private final int maxMessages;

    public MessageWindowChatMemory(int maxMessages) {
        this.maxMessages = maxMessages;
    }

    @Override
    public List<ChatMessage> messages() {
        List<ChatMessage> all = store.getMessages();
        // 只返回最近N条消息(滑动窗口)
        return all.subList(Math.max(0, all.size() - maxMessages), all.size());
    }
}

在Agent中使用Memory:

java

less 复制代码
// 带Memory的Agent配置
@Bean
public DataSummaryAgent dataSummaryAgent(ChatModel chatModel,
                                          ChatMemory chatMemory) {
    return AgenticServices.agentBuilder(DataSummaryAgent.class)
            .chatModel(chatModel)
            .chatMemory(chatMemory)  // ← Memory绑定
            .tools(playerDataTool)
            .build();
}

// Agent 接口中通过 @MemoryId 标记会话标识参数
public interface DataSummaryAgent {
    String answer(@MemoryId String memoryId, @V("openId") String openId);
}

// 调用时传入 memoryId
String result = agent.answer("user123", openId);

5.4 消息编排流程

text

less 复制代码
用户消息 → @UserMessage模板格式化
              │
              ▼
@SystemMessage + 历史Memory
              │
              ▼
         合并为完整Prompt
              │
              ▼
         ChatModel.send()
              │
              ▼
      ┌───────┴───────┐
      │               │
  无工具调用        有工具调用
      │               │
      ▼               ▼
   返回文本       工具执行循环
                      │
                      ▼
               结果反馈LLM
                      │
                      ▼
                  最终回复

六、Supervisor 的并行协调机制

6.1 子Agent并行调用

当 Supervisor 分析出需要多个子Agent并行执行时:

java

arduino 复制代码
// Supervisor内部的并行执行逻辑(伪代码)
public String answer(String openId, String request) {
    // 1. 分析意图,确定需要调用的子Agent
    List<SubAgent> targetAgents = analyzeIntent(request);

    // 2. 并行执行所有子Agent
    List<Future<String>> futures = new ArrayList<>();
    for (SubAgent agent : targetAgents) {
        futures.add(executor.submit(() ->
            agent.answer(buildSubPrompt(openId, agent))
        ));
    }

    // 3. 等待所有结果
    List<String> results = new ArrayList<>();
    for (Future<String> future : futures) {
        results.add(future.get(timeout, TimeUnit.SECONDS));
    }

    // 4. 聚合结果
    return mergeStrategy.merge(request, results);
}

6.2 变量传递机制

@V 注解实现 Supervisor 到子Agent的变量传递:

java

less 复制代码
@SupervisorAgent(subAgents = {...})
@SystemMessage("""
    当前请求的玩家 openId 是:{{openId}}。
    当你在调用任何子 Agent 时,必须将 "{{openId}}" 作为参数传给他们。
    """)
String answer(@V("openId") String openId, @UserMessage String request);

内部实现中,Supervisor 会将 @V("openId") 绑定的参数自动注入到子Agent调用中:

java

typescript 复制代码
// Supervisor构建子Agent调用时的参数绑定
public String callSubAgent(SubAgent agent, String openId) {
    // 查找子Agent接口中接受openId的方法
    Method method = findMethodWithOpenIdParam(agent.getClass());

    // 将Supervisor接收的openId传递给子Agent
    return agent.answer(openId, buildSubTaskPrompt(openId, agent));
}

6.3 串行依赖处理

某些场景下子Agent之间存在依赖关系,可以通过 Supervisor 的系统消息描述:

java

python 复制代码
@SystemMessage("""
    ## 执行规则
    1. 首先调用 DataSummaryAgent 获取玩家基础数据
    2. 基于基础数据,调用 UpgradePlannerAgent 生成规划
    3. 最后调用 BattleTacticsAgent 推荐进攻流派

    ## 依赖关系说明
    UpgradePlannerAgent 必须等待 DataSummaryAgent 完成!
    """)

虽然默认是并行执行,但通过系统消息的约束引导,LLM会选择串行执行流程。

七、自定义Agent(非Supervisor)

7.1 纯工具型Agent

java

less 复制代码
// 继承Agent接口,标记为Agent类型
public interface IntelligenceProcessorAgent {

    @SystemMessage("""
        # Role: 战术情报提炼专家
        分析网页原始数据,提取结构化战术信息。
        """)
    @UserMessage("请分析以下数据:\n\n{{raw_data}}")
    String extractAttackTactics(@V("raw_data") String rawData);
}

// 通过AiServices构建(非agentBuilder)
@Bean
public IntelligenceProcessorAgent intelligenceProcessorAgent(ChatModel chatModel) {
    return AiServices.builder(IntelligenceProcessorAgent.class)
            .chatModel(chatModel)
            .build();
}

Agent vs AiServices 的区别

特性 AgenticServices.agentBuilder() AiServices.builder()
@Tool支持 原生支持 需要额外配置
工具选择机制 LLM自主决策 需要在prompt中引导
适用场景 复杂工具调用 简单Q&A或单次处理

7.2 多方法Agent

一个Agent接口可以定义多个方法:

java

less 复制代码
public interface CocAnalysisAgent {

    @SystemMessage("你的角色是进攻战术专家")
    String analyzeAttack(@UserMessage String request);

    @SystemMessage("你的角色是防守阵型专家")
    String analyzeDefense(@UserMessage String request);

    @SystemMessage("你的角色是升级规划专家")
    String analyzeUpgrade(@UserMessage String request);
}

八、Spring Boot集成

8.1 配置类结构

java

kotlin 复制代码
@Configuration
public class AiConfig {

    // 1. 注入ChatModel(由Spring Boot自动配置或自定义)
    @Autowired
    private ChatModel chatModel;

    // 2. 注入工具Bean
    @Resource
    private PlayerDataTool playerDataTool;

    @Resource
    private TavilyTools tavilyTools;

    // 3. 按需注入Memory
    @Autowired
    private ChatMemory chatMemory;

    // 4. 创建各子Agent
    @Bean
    public DataSummaryAgent dataSummaryAgent(ChatModel chatModel) {
        return AgenticServices.agentBuilder(DataSummaryAgent.class)
                .chatModel(chatModel)
                .systemMessageProvider(memoryId ->
                    stringRedisTemplate.opsForValue().get("ai:prompt:module1"))
                .tools(playerDataTool)
                .build();
    }

    // 5. 创建Supervisor(注入所有子Agent)
    @Bean
    public SuperAgent cocSupervisor(ChatModel chatModel,
                                     DataSummaryAgent dataSummaryAgent,
                                     UpgradePlannerAgent upgradePlannerAgent,
                                     BattleTacticsAgent battleTacticsAgent,
                                     DefenseTacticsAgent defenseTacticsAgent) {

        return AgenticServices.supervisorBuilder(SuperAgent.class)
                .chatModel(chatModel)
                .subAgents(dataSummaryAgent, upgradePlannerAgent,
                           battleTacticsAgent, defenseTacticsAgent)
                .build();
    }
}

8.2 ChatModel配置

LangChain4j支持多种ChatModel实现:

yaml

yaml 复制代码
langchain4j:
  open-ai:
    chat-model:
      base-url: https://api.minimaxi.com/v1
      api-key: ${COC_API_KEY}
      model-name: MiniMax-M2.7
      temperature: 0.2
      timeout: PT3M
      log-requests: true
      log-responses: true

java

less 复制代码
@Configuration
public class ChatModelConfig {

    @Bean
    public ChatModel chatModel(
            @Value("${langchain4j.open-ai.chat-model.base-url}") String baseUrl,
            @Value("${langchain4j.open-ai.chat-model.api-key}") String apiKey
            // ... 其他配置
    ) {
        return OpenAiChatModel.builder()
                .baseUrl(baseUrl)
                .apiKey(apiKey)
                .modelName("MiniMax-M2.7")
                .temperature(0.2)
                .timeout(Duration.ofMinutes(3))
                .build();
    }
}

小提示:原文 yaml 配置中 api-key: ${CO外资C_API_KEY} 疑似打字错误,建议使用 ${COC_API_KEY}${COC_API_KEY:default_value}

九、流程图:完整请求处理链路

text

scss 复制代码
┌──────────────────────────────────────────────────────────────────────┐
│                          外部请求入口                                  │
│                    superAgent.answer(openId, request)                  │
└──────────────────────────────────────────────────────────────────────┘
                                    │
                                    ▼
┌──────────────────────────────────────────────────────────────────────┐
│                    SupervisorAgent (协调层)                            │
│  ┌────────────────────────────────────────────────────────────────┐  │
│  │ 1. @V("openId") 绑定变量 → openId                                │  │
│  │ 2. @SystemMessage 加载系统提示词                                  │  │
│  │ 3. @UserMessage 格式化用户消息                                    │  │
│  │ 4. LLM分析意图,决定调用哪些子Agent                                │  │
│  └────────────────────────────────────────────────────────────────┘  │
└──────────────────────────────────────────────────────────────────────┘
                                    │
            ┌───────────────────────┼───────────────────────┐
            ▼                       ▼                       ▼
    ┌───────────────┐       ┌───────────────┐       ┌───────────────┐
    │DataSummary    │       │UpgradePlanner │       │BattleTactics  │
    │Agent          │       │Agent          │       │Agent          │
    │               │       │               │       │               │
    │ @SystemMessage│       │ @SystemMessage│       │ @SystemMessage│
    │ (独立角色定义) │       │ (独立角色定义) │       │ (独立角色定义) │
    │               │       │               │       │               │
    │ tools:        │       │ tools:        │       │ tools:        │
    │ PlayerDataTool│       │ PlayerDataTool│       │ PlayerDataTool│
    └───────────────┘       └───────────────┘       └───────────────┘
            │                       │                       │
            │   ┌───────────────────┘                       │
            │   │ LLM决定工具调用                            │
            │   ▼                                           │
            │ ┌─────────────────────────────────────────────┐│
            │ │          @Tool 执行层                        ││
            │ │  queryPlayerBuildInfo(openid)               ││
            │ │  queryBuildLevel(openid, buildName)          ││
            │ │  → DAO → Database                           ││
            │ └─────────────────────────────────────────────┘│
            │   │ 工具结果反馈LLM                            │
            │   ▼                                           │
            │ LLM生成结构化回复                              │
            └───────────────────────────────────────────────┘
                                    │
                                    ▼
┌──────────────────────────────────────────────────────────────────────┐
│                    Supervisor 聚合层                                   │
│  ┌────────────────────────────────────────────────────────────────┐  │
│  │ SupervisorResponseStrategy                                      │  │
│  │ - 收集各子Agent的JSON/文本结果                                    │  │
│  │ - 按预定义结构组装                                               │  │
│  │ - 处理null值和缺失字段                                           │  │
│  └────────────────────────────────────────────────────────────────┘  │
└──────────────────────────────────────────────────────────────────────┘
                                    │
                                    ▼
                           最终JSON输出

十、总结与展望:LangChain4j vs LangGraph vs Spring AI

LangChain4j 的多智能体能力总结

通过上述各组件的有机组合,LangChain4j 提供了一条从简单单 Agent 到复杂多 Agent 协调的完整演进路径:

能力层级 核心组件 适用场景
简单问答 AiServices + @SystemMessage 单轮问答、文本生成
工具调用 AgenticServices.agentBuilder() + @Tool 需要查询数据库、调用 API 等工具的场景
多 Agent 协调 @SupervisorAgent + AgenticServices.supervisorBuilder() 意图分发、并行子任务执行、结果聚合
动态提示词 SystemMessageProvider 多租户、AB 测试、Prompt 热更新
多轮对话 ChatMemory + @MemoryId 需要上下文记忆的连续对话

在 Java 生态中,LangChain4j 是目前集成度最高、对 Spring Boot 支持最完善的选择之一,它让 Java 开发者可以用纯接口定义 + 注解驱动 的方式快速构建 AI 应用,无需深究底层协议。但与之并肩的还有官方出品的 Spring AI ,以及多智能体领域事实标准 LangGraph,三者在技术定位和能力边界上有显著差异。

三者核心定位对比:为什么多智能体流程编排选 LangGraph?

维度 LangChain4j Spring AI LangGraph
开发语言 Java / Spring Boot ⭐ Java / Spring Boot ⭐ Python / TypeScript
上手门槛 低(注解驱动,社区成熟) 低(Spring 原生风格,自动配置) 中(需理解图和状态概念)
多 Agent 能力 中等(Supervisor 模式,隐式路由) 弱(无内置的多 Agent 编排,需手动组合) 强(显式有向图、条件边、循环、Map-Reduce)
流程编排灵活性 一般(依赖 LLM 自主决策) 一般(需自行封装) 极强(图级控制、状态持久化、断点续跑)
工具/函数调用 丰富(@Tool 注解,自动生成 Schema) 丰富(@Tool 注解,与函数式 Bean 结合紧密) 灵活(自定义 Node 函数,可集成任意库)
状态管理与可观测性 较弱(调用链隐式,依赖 LLM 日志) 较弱(无内置图状态,需借助 Micrometer) 极强(State 对象流转、图可视化、回放与回溯)
高级 Multi-Agent 模式 有限(Supervisor 为主) 需手动编码实现 丰富(分层、辩论、Reflexion、ReAct 循环)
Spring 整合深度 较好(Starter、自动配置) 极佳(官方出品,极致原生体验) 无(需自行封装 HTTP/gRPC 服务)
多模型支持 广泛(OpenAI、MiniMax、Ollama 等) 广泛(与 Spring 生态无缝对接) 广泛(LangChain 生态模型全部可用)
生产就绪程度 简单场景可快速落地 企业级 Java 环境首选,生态协同强 复杂场景长期迭代首选,学术与工业验证充分

如何做出技术选型?

① 什么时候选 Spring AI?

  • 当你的团队以 Spring Boot 为核心技术栈,追求极致的一体化开发体验时,Spring AI 是最自然的选择。
  • 它提供了与 Spring 生态的无缝整合(如 @Tool 直接对标 Service Bean、与 WebClientRetryObservability 深度结合),尤其适合在已有 Spring 微服务体系上扩展 AI 能力。
  • 但它的多智能体能力目前较弱,如果你需要复杂的 Agent 协作,不建议用 Spring AI 从零造轮子,而应将其作为调用下游 Agent 服务的"门面"。

② 什么时候选 LangChain4j?

  • 当你的业务场景需要显式的多 Agent 协调(如 Supervisor 模式),但又不想脱离 Java 技术栈时,LangChain4j 是最佳折中。
  • 它比 Spring AI 提供了更成熟的 Agent 抽象(@SupervisorAgentAgenticServices),又比 LangGraph 更容易落地到 Spring Boot 中。
  • 适合:智能客服、报告生成、数据汇总与分析等流程相对线性的多 Agent 场景

③ 什么时候必须选 LangGraph?

  • 当你面对高度复杂的多 Agent 协同:如多步规划、条件分支、持续循环(ReAct)、人工审批介入、多代理辩论等。
  • 当你需要图级别的可观测性:步骤追踪、状态可视化、断点续跑、回放。
  • 当你需要前沿的 Multi-Agent 模式:如 Reflexion、Self-Refine、Multi-Agent Collaboration 等,这些论文实现的第一语言通常是 Python。
  • 推荐架构 :用 Spring AI / LangChain4j 作为 Java 侧的 AI 服务入口,将核心 Agent 流程编排交给 LangGraph(Python 微服务) ,通过 HTTP 或 gRPC 通信。这种"混合架构"兼顾了 Java 生态的稳定性和 Python 生态的灵活性,是目前企业级应用的最佳实践。

最后的话

LangChain4j 与 Spring AI 让 Java 开发者迈入了 AI 应用开发的大门,而 LangGraph 则打开了多智能体协同的复杂世界。在真实业务中,技术选型从来不是"非此即彼",而是根据场景灵活组合。当前阶段,如果你想构建真正复杂的、可进化的多智能体系统,LangGraph 依然是流程编排的底座,而 Java 侧的工具(LangChain4j/Spring AI)负责将其包装为业务可用的服务。随着 Spring AI 的 Roadmap 中已开始出现 StateGraph 等概念,未来 Java 生态的 Multi-Agent 能力也值得期待。

完整的pom文件如下:

xml

xml 复制代码
<properties>
    <docker.repostory>registry.cn-hangzhou.aliyuncs.com/coccounter/coc</docker.repostory>
    <java.version>17</java.version>
    <spring-cloud.version>2025.0.1</spring-cloud.version>
</properties>
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.31</version>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-spring-boot3-starter</artifactId>
        <version>3.5.5</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>

    <!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
    <dependency>
        <groupId>com.google.guava</groupId>
        <artifactId>guava</artifactId>
        <version>32.1.2-jre</version>
    </dependency>

    <dependency>
        <groupId>org.jsoup</groupId>
        <artifactId>jsoup</artifactId>
        <version>1.21.2</version>
    </dependency>
    <dependency>
        <groupId>cn.hutool</groupId>
        <artifactId>hutool-all</artifactId>
        <version>5.8.21</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>2.0.39</version>
    </dependency>

    <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-openfeign -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>

    <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
    <dependency>
        <groupId>com.google.code.gson</groupId>
        <artifactId>gson</artifactId>
        <version>2.10.1</version>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>

    <!-- 阿里云 OSS 依赖 -->
    <dependency>
        <groupId>com.aliyun.oss</groupId>
        <artifactId>aliyun-sdk-oss</artifactId>
        <version>3.15.1</version>
    </dependency>

    <!-- Knife4j Swagger UI 依赖 -->
    <dependency>
        <groupId>com.github.xiaoymin</groupId>
        <artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
        <version>4.4.0</version>
    </dependency>

    <dependency>
        <groupId>dev.langchain4j</groupId>
        <artifactId>langchain4j-open-ai-spring-boot-starter</artifactId>
        <version>1.12.2-beta22</version>
    </dependency>

    <dependency>
        <groupId>dev.langchain4j</groupId>
        <artifactId>langchain4j-spring-boot-starter</artifactId>
        <version>1.12.2-beta22</version>
    </dependency>

    <dependency>
        <groupId>dev.langchain4j</groupId>
        <artifactId>langchain4j-agentic</artifactId>
        <version>1.12.2-beta22</version>
    </dependency>

</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <executions>
                <execution>
                    <goals>
                        <goal>build-info</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>com.spotify</groupId>
            <artifactId>docker-maven-plugin</artifactId>
            <version>1.1.0</version>
        </plugin>
    </plugins>
</build>

参考

相关推荐
Trouvaille ~1 小时前
零基础入门 LangChain 与 LangGraph(八):真正让 Agent“活起来”——持久化、记忆、人机交互与时间旅行
langchain·人机交互·agent·python3.11·持久化机制·langgraph·ai应用开发
AI人工智能+电脑小能手2 小时前
【大白话说Java面试题】【Java基础篇】第20题:HashMap在计算index的时候,为什么要对数组长度做减1操作
java·开发语言·数据结构·后端·面试·哈希算法·hash-index
还是转转2 小时前
深入认识 Agent —— 实现你自己的 Agent
ai·agent
abigale032 小时前
LangChain:自定义模型・RAG 检索・Agent 原理笔记
langchain·llm·prompt·agent·rag·lcel
阿丰资源2 小时前
基于Spring Boot的新闻推荐系统(源码+数据库+文档)
数据库·spring boot·后端
Gopher_HBo3 小时前
Disruptor消费源码分析
后端
ToTensor3 小时前
Agent 记忆管理框架基准测试排名
人工智能·agent
千寻girling3 小时前
滑动窗口刷了快一个月(26天)了 , 还没有刷完. | 含(操作系统学什么的Java 后端)
java·开发语言·javascript·c++·人工智能·后端·python
jiayong233 小时前
国内外视频/图像大模型与智能体工具平台竞品对比
ai·音视频·agent