AI Agent 团队协作:多 Agent 系统架构设计与 Java 实战

AI Agent 团队协作:多 Agent 系统架构设计与 Java 实战

系列文章

本文是 AI Agent 深度解析系列的第 10 篇,建议先阅读以下前置文章:


为什么一个 Agent 不够?

在前面的系列文章中,我们已经深入理解了单个 Agent 的核心能力:推理工具调用规划记忆。一个配备齐全的 Agent 已经能完成很多任务,但在真实的企业场景中,你会发现一个 Agent 很快就会遇到瓶颈:

上下文窗口的物理限制。即使是 128K token 的大模型,当你同时塞入系统提示词、历史对话、工具调用结果和检索到的文档时,留给”思考”的空间其实很有限。让一个 Agent 既做需求分析、又写代码、还做代码审查和测试,它的上下文窗口很快就会被撑爆。

角色混乱导致质量下降。一个人既要当产品经理、又要当架构师、还要当开发和测试,结果通常是每个角色都做得平庸。心理学上叫”角色冲突”——同一时间扮演多个角色会让认知负荷急剧上升。Agent 也是一样,当你让一个 Agent 同时负责代码生成和代码审查时,它很容易陷入”自己审自己”的盲区。

单点故障的系统风险。一个 Agent 挂了,整个流程就停了。而在多 Agent 系统中,某个 Agent 失败时可以被重试、被替代,甚至被其他 Agent 诊断和修复。

效率瓶颈。一个 Agent 只能串行执行任务,而多 Agent 可以并行工作——一个分析需求,一个查文档,一个准备测试用例,效率提升是数量级的。

这些问题指向一个自然的解决方案:让多个专业化的 Agent 组成团队,分工协作


多 Agent 系统的三大架构模式

1. 层级式架构(Hierarchical)

这是最接近现实企业组织的架构。有一个”主管 Agent”负责接收任务、分解子任务、分配给下属 Agent、收集结果并整合。

1
2
3
4
5
6
7
8
9
10
11
            ┌──────────────┐
│ 主管 Agent │
│ (Orchestrator)│
└──────┬───────┘
│ 分配任务
┌────────────┼────────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ 需求分析 │ │ 代码生成 │ │ 测试验证 │
│ Agent │ │ Agent │ │ Agent │
└──────────┘ └──────────┘ └──────────┘

优点:职责清晰,易于管理,主管 Agent 可以做质量把关。
缺点:主管 Agent 是单点瓶颈,它的上下文窗口要承载所有子 Agent 的结果。
适用场景:流程明确、步骤可预期的任务,比如代码生成流水线。

2. 对等式架构(Peer-to-Peer)

没有中央调度者,Agent 之间直接通信。每个 Agent 都可以发起对话、请求帮助、提供结果。这种架构更灵活,但也更难控制。

1
2
3
4
5
6
7
┌──────────┐         ┌──────────┐
│ Agent A │◄───────►│ Agent B │
└────┬─────┘ └─────┬────┘
│ │
│ ┌──────────┐ │
└───►│ Agent C │◄────┘
└──────────┘

优点:去中心化,没有单点瓶颈,灵活度高。
缺点:难以保证收敛(可能无限循环讨论),调试困难。
适用场景:开放式问题讨论,如头脑风暴、辩论式推理。

3. 混合式架构(Hybrid)

实际项目中最常用的架构。有一个轻量级的协调者负责全局调度,但子 Agent 之间也可以直接通信。协调者不参与具体工作,只负责”派活”和”收结果”。

1
2
3
4
5
6
7
8
9
10
11
12
           ┌─────────────────┐
│ 协调者 Agent │
│ (轻量级调度) │
└────────┬────────┘

┌─────────────┼─────────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ 研究员 │ │ 工程师 │ │ 审查员 │
│ Agent │──│ Agent │──│ Agent │
└──────────┘ └──────────┘ └──────────┘
(可以直接通信,不必经过协调者)

这种架构兼顾了可控性和灵活性,是我们后面实战的重点。


通信机制:Agent 之间怎么”说话”?

消息传递(Message Passing)

最直接的方式——Agent A 往 Agent B 的消息队列里扔一条消息,Agent B 收到后处理并回复。

在 LangChain4j 中,这可以通过 ChatMemory 的变体来实现。每个 Agent 有独立的对话记忆,Agent 之间的消息通过一个”消息总线”中转:

1
2
3
4
public interface AgentMessageBus {
void send(String fromAgent, String toAgent, String message);
List<AgentMessage> receive(String agentName);
}

共享状态(Shared State)

所有 Agent 共享一个”黑板”(Blackboard),每个 Agent 都可以读写。这类似于线程共享内存的模式——高效但需要注意并发控制。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class SharedBlackboard {
private final Map<String, Object> state = new ConcurrentHashMap<>();
private final List<BlackboardListener> listeners = new CopyOnWriteArrayList<>();

public void write(String key, Object value, String writer) {
state.put(key, value);
// 通知所有监听者
listeners.forEach(l -> l.onUpdate(key, value, writer));
}

public Object read(String key) {
return state.get(key);
}
}

事件驱动(Event-Driven)

Agent 发布事件,感兴趣的 Agent 订阅并响应。这种模式天然适合 Spring 的事件机制:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Component
public class AgentEventPublisher {
@Autowired
private ApplicationEventPublisher publisher;

public void publishTaskComplete(String agentName, TaskResult result) {
publisher.publishEvent(new AgentTaskCompleteEvent(agentName, result));
}
}

@Component
public class ReviewerAgent {
@EventListener
public void onTaskComplete(AgentTaskCompleteEvent event) {
if ("codeGenerator".equals(event.getAgentName())) {
// 自动触发代码审查
reviewCode(event.getResult());
}
}
}

三种模式的对比

维度 消息传递 共享状态 事件驱动
耦合度 中(需要知道对方) 高(共享内存) 低(发布-订阅)
调试难度 高(竞态条件) 低(事件可追踪)
适用场景 点对点协作 状态密集型任务 松耦合流水线
扩展性 一般
Spring 友好度 非常好

实战建议:大多数场景下,事件驱动是最优选择。它和 Spring 的 ApplicationEventPublisher 天然契合,而且松耦合的特性让系统更容易扩展和维护。


任务分解:从”造房子”到”搬砖”

多 Agent 系统的第一个挑战不是”怎么让 Agent 协作”,而是”怎么把大任务拆成小任务”。

任务分解的三种策略

1. 基于流程的分解

适合有明确步骤的任务。比如”从需求到代码”可以分解为:需求分析 → 架构设计 → 代码实现 → 测试 → 审查。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class PipelineOrchestrator {
private final List<AgentStep> steps;

public Result execute(Task task) {
Object context = task;
for (AgentStep step : steps) {
context = step.execute(context);
if (step.failed()) {
return Result.failure(step.getError());
}
}
return Result.success(context);
}
}

2. 基于能力的分解

根据每个 Agent 的”特长”分配任务。就像你不会让前端工程师去调数据库一样。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class CapabilityBasedRouter {
private final Map<String, Agent> agentRegistry;

public AgentRoute route(SubTask task) {
// 分析任务需要的能力
Set<String> requiredCapabilities = analyzeCapabilities(task);
// 找到匹配能力的 Agent
Agent bestAgent = agentRegistry.values().stream()
.filter(a -> a.getCapabilities().containsAll(requiredCapabilities))
.min(Comparator.comparingInt(Agent::getCurrentLoad))
.orElseThrow(() -> new NoSuitableAgentException(task));
return new AgentRoute(bestAgent, task);
}
}

3. 基于数据的分解

把大任务按数据维度拆分。比如”分析 1000 份简历”可以拆成 10 组,每组 100 份,由 10 个 Agent 并行处理。


冲突解决:当 Agent 意见不一致时

多个 Agent 协作一定会遇到冲突。比如代码生成 Agent 写了一段代码,但审查 Agent 认为有性能问题。怎么解决?

策略一:权威裁决

由一个”高级 Agent”做最终决策。比如协调者 Agent 综合双方意见后做决定。

1
2
3
4
5
6
7
8
9
10
public class ConflictResolver {
public Resolution resolve(AgentOpinion opinion1, AgentOpinion opinion2) {
// 把两个意见都交给仲裁者
String prompt = String.format(
"Agent A 认为:%s\nAgent B 认为:%s\n请综合分析并给出最终方案。",
opinion1.getContent(), opinion2.getContent()
);
return arbitratorAgent.chat(prompt);
}
}

策略二:投票机制

适用于对等架构。多个 Agent 投票,少数服从多数。适合”分类”类任务(比如情感分析、内容审核),不太适合创造性任务。

策略三:迭代协商

Agent 之间多轮对话,逐步收敛到共识。最接近人类团队的协作方式,但代价是 token 消耗高、可能不收敛。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class NegotiationProtocol {
private static final int MAX_ROUNDS = 3;

public Agreement negotiate(Agent agent1, Agent agent2, Topic topic) {
String currentProposal = agent1.propose(topic);
for (int round = 0; round < MAX_ROUNDS; round++) {
String response = agent2.evaluate(currentProposal);
if (isAgreement(response)) {
return new Agreement(response, round);
}
currentProposal = agent1.refine(currentProposal, response);
}
// 超过最大轮次,交给仲裁者
return conflictResolver.arbitrate(agent1, agent2, topic);
}
}

实战建议:在企业场景中,”权威裁决 + 迭代协商”的混合策略最实用。简单分歧用裁决快速解决,复杂分歧用协商深入讨论,但必须设置最大轮次防止无限循环。


实战:用 LangChain4j + Spring Boot 构建多 Agent 系统

接下来我们实现一个完整的多 Agent 系统:一个”技术文档生成器”,由三个 Agent 协作完成。

整体架构

1
2
3
4
5
6
7
8
9
10
用户需求 ──► 协调者 Agent ──► 研究员 Agent(搜索资料)
│ │
│ ▼
└──────► 写手 Agent(撰写文章)


审查员 Agent(质量检查)


输出最终文档

Step 1:定义 Agent 基础接口

1
2
3
4
5
public interface Agent {
String getName();
Set<String> getCapabilities();
AgentResponse chat(String message, AgentContext context);
}

Step 2:实现研究员 Agent

研究员 Agent 的职责是根据主题搜索和整理资料。它配备了搜索工具(参考 Tool Use 文章)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
@Component
public class ResearcherAgent implements Agent {

private final ChatLanguageModel model;
private final ToolExecutor searchTool;

public ResearcherAgent(
@Value("${agent.model}") ChatLanguageModel model,
ToolExecutor searchTool) {
this.model = model;
this.searchTool = searchTool;
}

@Override
public String getName() { return "researcher"; }

@Override
public Set<String> getCapabilities() {
return Set.of("search", "summarize", "fact-check");
}

@Override
public AgentResponse chat(String message, AgentContext context) {
String systemPrompt = """
你是一个技术研究员。你的职责是:
1. 根据给定的主题搜索最新的技术资料
2. 整理关键信息,提取核心要点
3. 验证信息的准确性和时效性

输出格式:
- 核心概念(3-5 个要点)
- 技术细节(包括代码示例或架构图描述)
- 参考来源
- 注意事项和常见误区

当前主题:%s
""".formatted(context.getTopic());

// 使用工具搜索资料
List<ChatMessage> messages = List.of(
SystemMessage.from(systemPrompt),
UserMessage.from(message)
);

// 配置工具并调用
model.setTools(List.of(ToolSpecification.from(searchTool)));
Response<AiMessage> response = model.generate(messages);

return new AgentResponse(
getName(),
response.content().text(),
extractSources(response)
);
}
}

Step 3:实现写手 Agent

写手 Agent 接收研究员的资料,撰写结构化的技术文章。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
@Component
public class WriterAgent implements Agent {

private final ChatLanguageModel model;

@Override
public String getName() { return "writer"; }

@Override
public Set<String> getCapabilities() {
return Set.of("write", "structure", "illustrate");
}

@Override
public AgentResponse chat(String message, AgentContext context) {
String systemPrompt = """
你是一个资深技术写手。你的职责是:
1. 基于研究员提供的资料,撰写深入浅出的技术文章
2. 使用循序渐进的结构:先讲"是什么",再讲"为什么",最后讲"怎么用"
3. 包含实际的代码示例(优先 Java/Spring Boot)
4. 用类比和生活化的例子解释复杂概念
5. 文章长度 3000-5000 字

写作风格要求:
- 像给朋友讲课一样自然
- 先给结论,再展开原理
- 避免学术腔
- 每个代码示例都要有解释

研究资料:
%s
""".formatted(context.getResearchResults());

List<ChatMessage> messages = List.of(
SystemMessage.from(systemPrompt),
UserMessage.from(message)
);

Response<AiMessage> response = model.generate(messages);
return new AgentResponse(getName(), response.content().text(), List.of());
}
}

Step 4:实现审查员 Agent

审查员 Agent 检查文章质量,提出修改意见。它和写手 Agent 形成”制衡”关系。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
@Component
public class ReviewerAgent implements Agent {

private final ChatLanguageModel model;

@Override
public String getName() { return "reviewer"; }

@Override
public Set<String> getCapabilities() {
return Set.of("review", "quality-check", "fact-verify");
}

@Override
public AgentResponse chat(String message, AgentContext context) {
String systemPrompt = """
你是一个严格的技术审查员。你的职责是检查文章的:
1. 技术准确性:代码示例是否正确?概念解释是否准确?
2. 深度:是否只停留在表面?有没有讲清楚"为什么"?
3. 完整性:是否遗漏了关键知识点?
4. 可读性:结构是否清晰?例子是否恰当?

输出格式(JSON):
{
"approved": true/false,
"score": 1-10,
"issues": ["问题1", "问题2"],
"suggestions": ["建议1", "建议2"]
}
""";

List<ChatMessage> messages = List.of(
SystemMessage.from(systemPrompt),
UserMessage.from("请审查以下文章:\n" + context.getDraft())
);

Response<AiMessage> response = model.generate(messages);
return new AgentResponse(getName(), response.content().text(), List.of());
}
}

Step 5:协调者 Agent —— 整合一切

协调者是整个系统的”大脑”,它决定任务执行流程,调用其他 Agent,并处理冲突。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
@Service
public class OrchestratorAgent {

private final ResearcherAgent researcher;
private final WriterAgent writer;
private final ReviewerAgent reviewer;
private final ChatLanguageModel model;

// 最大重试次数
private static final int MAX_RETRIES = 2;

public String generateDocument(String topic) {
AgentContext context = new AgentContext(topic);

// 阶段 1:研究
AgentResponse researchResult = researcher.chat(
"请深入研究以下主题,收集全面的资料:" + topic,
context
);
context.setResearchResults(researchResult.getContent());

// 阶段 2:撰写(可能需要多轮修改)
AgentResponse writeResult = writer.chat(
"基于研究资料,撰写一篇完整的技术文章",
context
);

String currentDraft = writeResult.getContent();
for (int attempt = 0; attempt < MAX_RETRIES; attempt++) {
// 阶段 3:审查
context.setDraft(currentDraft);
AgentResponse reviewResult = reviewer.chat(
"请审查这篇文章的质量",
context
);

ReviewReport report = parseReviewReport(reviewResult.getContent());
if (report.isApproved() && report.getScore() >= 7) {
return currentDraft; // 审查通过
}

// 阶段 4:根据审查意见修改
currentDraft = writer.chat(
"审查员提出了以下意见,请据此修改文章:\n"
+ String.join("\n", report.getIssues()) + "\n"
+ "修改建议:\n"
+ String.join("\n", report.getSuggestions()),
context
).getContent();
}

return currentDraft; // 超过重试次数,返回最新版本
}
}

Step 6:用 Spring 事件驱动解耦

为了让系统更灵活,我们用 Spring 的事件机制来驱动 Agent 之间的协作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// 事件定义
public record AgentTaskEvent(String agentName, String task, AgentContext context) {}
public record AgentResultEvent(String agentName, AgentResponse result) {}

// 协调者通过事件驱动
@Service
public class EventDrivenOrchestrator {

@Autowired private ApplicationEventPublisher publisher;
@Autowired private ApplicationContext appContext;

public void startWorkflow(String topic) {
AgentContext context = new AgentContext(topic);
publisher.publishEvent(new AgentTaskEvent("researcher", topic, context));
}

@EventListener
public void onResearchComplete(AgentResultEvent event) {
if ("researcher".equals(event.agentName())) {
// 研究完成,触发写作
AgentContext ctx = event.result().getContext();
ctx.setResearchResults(event.result().getContent());
publisher.publishEvent(new AgentTaskEvent("writer", "write article", ctx));
}
}

@EventListener
public void onWriteComplete(AgentResultEvent event) {
if ("writer".equals(event.agentName())) {
// 写作完成,触发审查
AgentContext ctx = event.result().getContext();
ctx.setDraft(event.result().getContent());
publisher.publishEvent(new AgentTaskEvent("reviewer", "review article", ctx));
}
}
}

源码级解读:LangChain4j 中的 Agent 交互机制

LangChain4j 本身没有内置”多 Agent”的抽象,但它的 ChatLanguageModel + ToolSpecification + ChatMemory 三件套提供了构建多 Agent 系统的所有原材料。

关键在于理解 AiMessage 的工具调用链:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// LangChain4j 的单次调用流程
Response<AiMessage> response = model.generate(messages, toolSpecifications);

// 如果 AiMessage 包含 toolExecutionRequests,说明 Agent 想调用工具
if (response.content().hasToolExecutionRequests()) {
for (ToolExecutionRequest request : response.content().toolExecutionRequests()) {
// 执行工具,获取结果
String result = toolExecutor.execute(request);
// 把结果作为 ToolExecutionResultMessage 追加到消息列表
messages.add(ToolExecutionResultMessage.from(request, result));
}
// 再次调用模型,让它基于工具结果继续推理
response = model.generate(messages, toolSpecifications);
}

在多 Agent 场景中,我们可以把”调用另一个 Agent”本身作为一种工具:

1
2
3
4
5
6
7
8
9
10
11
@Tool("调用研究员 Agent 搜索资料")
public String callResearcher(@P("搜索主题") String topic) {
return researcherAgent.chat("搜索: " + topic, new AgentContext(topic))
.getContent();
}

@Tool("调用审查员 Agent 检查代码质量")
public String callReviewer(@P("待审查的代码") String code) {
return reviewerAgent.chat("审查: " + code, new AgentContext(""))
.getContent();
}

这样,协调者 Agent 就可以通过 ReAct 模式(参考 ReAct 文章)自主决定何时调用哪个子 Agent,形成一个动态的协作链。

与 Spring AI 的对比

Spring AI 在 1.0 版本中对多 Agent 的支持更偏向于”函数调用链”模式,通过 @Bean 注册 FunctionCallback,让模型通过函数调用串联多个步骤:

1
2
3
4
5
6
7
8
9
10
11
@Bean
@Description("搜索技术资料")
public Function<SearchRequest, SearchResult> searchTool() {
return request -> searchService.search(request.query());
}

@Bean
@Description("审查文章质量")
public Function<Article, ReviewReport> reviewTool() {
return article -> reviewService.review(article);
}

Spring AI 的优势在于和 Spring 生态天然集成——依赖注入、事件驱动、配置管理都是开箱即用。劣势在于多 Agent 协作的抽象层次较低,很多东西需要你自己实现。

LangChain4j vs Spring AI 多 Agent 对比

维度 LangChain4j Spring AI
Agent 抽象 无内置,需要自行封装 无内置,通过 Function 组合
工具注册 @Tool 注解,编译时扫描 FunctionCallback Bean
记忆管理 ChatMemory 接口丰富 ChatMemory 较简单
流式支持 StreamingChatLanguageModel Flux 响应式
生态集成 独立库 深度集成 Spring Boot
多模型支持 好(统一接口) 好(统一接口)

生产环境的坑与最佳实践

1. Token 成本控制

多 Agent 系统最大的成本陷阱是上下文膨胀。每个 Agent 每次调用都要带上系统提示词 + 历史消息 + 工具结果,三个 Agent 各调用两轮,token 消耗可能是单 Agent 的 6-10 倍。

解决方案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 用摘要压缩历史上下文
public class SummarizingMemory implements ChatMemory {
private final ChatLanguageModel model;
private final List<ChatMessage> messages = new ArrayList<>();
private static final int MAX_MESSAGES = 10;

@Override
public void add(ChatMessage message) {
messages.add(message);
if (messages.size() > MAX_MESSAGES) {
// 把早期消息压缩成摘要
String summary = summarize(messages.subList(0, MAX_MESSAGES / 2));
messages.subList(0, MAX_MESSAGES / 2).clear();
messages.add(0, SystemMessage.from("之前的对话摘要:" + summary));
}
}
}

2. 超时与熔断

Agent 调用可能因为网络、模型过载等原因超时。在多 Agent 链路中,一个超时会导致整个流程卡住。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Service
public class ResilientAgentCaller {

@CircuitBreaker(name = "agent", fallbackMethod = "fallback")
@TimeLimiter(name = "agent")
public CompletableFuture<AgentResponse> callAgent(Agent agent, String msg, AgentContext ctx) {
return CompletableFuture.supplyAsync(() -> agent.chat(msg, ctx));
}

public CompletableFuture<AgentResponse> fallback(Agent agent, String msg, AgentContext ctx, Throwable t) {
// 降级:返回缓存结果或简化提示
return CompletableFuture.completedFuture(
new AgentResponse(agent.getName(), "服务暂时不可用,请稍后重试。", List.of())
);
}
}

配合 Resilience4j 的熔断器配置:

1
2
3
4
5
6
7
8
9
10
11
resilience4j:
circuitbreaker:
instances:
agent:
slidingWindowSize: 10
failureRateThreshold: 50
waitDurationInOpenState: 30s
timelimiter:
instances:
agent:
timeoutDuration: 60s

3. 可观测性

多 Agent 系统的调试比单 Agent 难得多。你需要知道每个 Agent 收到了什么、输出了什么、花了多长时间。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
@Aspect
@Component
public class AgentTracingAspect {

@Around("execution(* com.example.agent.Agent.chat(..))")
public Object traceAgent(ProceedingJoinPoint pjp) throws Throwable {
Agent agent = (Agent) pjp.getTarget();
String input = (String) pjp.getArgs()[0];

Span span = tracer.nextSpan().name("agent:" + agent.getName()).start();
try (Tracer.SpanInScope ws = tracer.withSpan(span)) {
log.info("[{}] 输入: {}", agent.getName(), abbreviate(input, 200));
long start = System.currentTimeMillis();

Object result = pjp.proceed();

long elapsed = System.currentTimeMillis() - start;
log.info("[{}] 输出: {} (耗时: {}ms)", agent.getName(),
abbreviate(result.toString(), 200), elapsed);

span.tag("agent.name", agent.getName());
span.tag("agent.elapsed_ms", String.valueOf(elapsed));
return result;
} catch (Exception e) {
span.error(e);
throw e;
} finally {
span.end();
}
}
}

4. 并发安全

当多个 Agent 并行执行时,共享的 AgentContext 可能出现竞态条件。使用不可变对象或并发安全的数据结构:

1
2
3
4
5
6
7
8
9
10
11
12
public class AgentContext {
private final String topic;
private final ConcurrentHashMap<String, String> data = new ConcurrentHashMap<>();

public void put(String key, String value) {
data.put(key, value); // 线程安全
}

public String get(String key) {
return data.get(key);
}
}

横向对比:主流多 Agent 框架

框架 语言 核心理念 优势 劣势
CrewAI Python 角色扮演 + 任务委派 上手快,概念清晰 深度定制困难
AutoGen Python 对话式协作 灵活,支持人机混合 学习曲线陡
LangGraph Python 图状态机 可控性最强,可视化 概念多,入门门槛高
LangChain4j Java 工具 + 记忆 Java 生态无缝集成 多 Agent 抽象需自建
Spring AI Java 函数回调 Spring 原生支持 多 Agent 支持较薄

对于 Java 开发者来说,LangChain4j + Spring Boot 的组合是当前最务实的选择。虽然没有开箱即用的”多 Agent 框架”,但 @Tool 注解 + Spring Event + ChatMemory 的组合足以构建生产级的多 Agent 系统。


多 Agent 的边界与未来

什么时候不该用多 Agent?

  • 任务足够简单:如果一个 Agent 能在 2-3 轮对话内完成,加多个 Agent 只会增加复杂度和成本。
  • 实时性要求极高:多 Agent 的通信开销会显著增加延迟。
  • 预算有限:token 消耗是硬成本,多 Agent 动辄 5-10 倍的消耗需要有预算支撑。
  • 缺乏可观测性基础设施:没有日志、追踪、监控,多 Agent 系统出了问题你根本不知道是哪个 Agent 的锅。

未来方向

自组织 Agent 团队:目前的多 Agent 系统大多需要人工定义角色和流程。未来的方向是 Agent 自己决定”我需要什么样的队友”、”我该怎么分工”——就像一个项目经理自动组建团队。

Agent 协议标准化:MCP(参考 MCP 文章)解决了 Agent 与工具之间的标准化通信,但 Agent 与 Agent 之间的通信还没有统一协议。Google 的 A2A(Agent-to-Agent)协议正在尝试填补这个空白。

混合人机协作:不是所有决策都应该交给 Agent。在关键节点引入人类审批,形成”Agent 做初步工作 → 人类审核 → Agent 继续执行”的半自动模式,是目前最安全的落地方式。


总结

多 Agent 系统不是银弹,但在合适的场景下,它能显著提升 AI 系统的能力边界。关键要点:

  1. 选择合适的架构:层级式适合流程明确的任务,对等式适合开放探索,混合式最通用。
  2. 通信机制要简单:事件驱动是 Spring 生态下的最佳选择,避免过度设计。
  3. 任务分解是核心:好的分解决定了系统的上限,差的分解会让多 Agent 反而不如单 Agent。
  4. 控制成本:上下文压缩、摘要机制、智能缓存缺一不可。
  5. 可观测性是生命线:没有追踪和日志,多 Agent 系统就是黑盒。

从单 Agent 到多 Agent,本质上是从”一个人干活”到”一个团队协作”的转变。这个过程中遇到的很多问题——角色定义、任务分配、冲突解决——在人类组织管理中已经有成熟的解决方案。多 Agent 系统的设计,某种意义上就是在用代码重新实现组织管理学的核心思想。


本文是 AI Agent 深度解析系列的第 10 篇。在之前的系列中,我们已经探讨了 ReAct 推理模式Tool Use 工具调用记忆系统LangChain4j MemoryRAG 检索增强规划策略MCP 协议结构化输出Prompt Engineering。多 Agent 协作是这些能力的自然延伸——当单个 Agent 的能力被充分挖掘后,让多个 Agent 组成团队就是下一个进化方向。