news 2026/9/15 9:06:43

90%的活一个Agent是干不完的,多Agent协作才是生产级方案-可写简历:任务分发+结果汇总完整架构

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
90%的活一个Agent是干不完的,多Agent协作才是生产级方案-可写简历:任务分发+结果汇总完整架构


做Agent项目的同学,很快会遇到一个瓶颈:单Agent能力有限。

让一个Agent同时做需求分析、代码生成、测试用例编写、代码审查,结果就是每样都做不精——需求分析不透彻,代码有bug,测试用例覆盖不全。更要命的是,一个Agent的上下文塞了所有角色的Prompt,token消耗巨大,还容易角色混乱。

生产级复杂任务,从来不是一个Agent包打天下,而是多Agent协作:每个Agent专注一个角色,各司其职,通过任务分发和结果汇总协同完成复杂任务。就像一个团队,有产品经理、开发、测试、架构师,各干各的,最后汇总交付。

今天我们用Java从零实现一个多Agent协作框架,包含角色定义、任务分发器、结果汇总器、协作流程编排,代码完整可复制,做完直接写进简历。

本文属于Java+AI Agent落地系列,之前讲了单Agent的记忆系统和工作流引擎,多Agent是把这些能力组合起来的更高阶形态。

一、多Agent协作的核心架构

多Agent不是简单地启动多个大模型实例,而是有清晰的架构设计。核心四个组件:

1. Agent角色(AgentRole)
每个Agent有明确的角色定义、系统Prompt、能力范围。比如"需求分析师Agent"只负责需求拆解,"代码生成Agent"只负责写代码,"测试Agent"只负责写测试用例。角色越聚焦,输出质量越高。

2. 任务分发器(TaskDispatcher)
根据任务类型,把任务分发给对应角色的Agent。比如收到一个开发需求,先发给需求分析师,分析完再发给代码生成Agent,代码写完发给测试Agent。分发逻辑可以是顺序的,也可以是并行的。

3. 结果汇总器(ResultAggregator)
收集各个Agent的输出,整合、去重、校验,形成最终交付物。比如代码生成Agent输出了代码,测试Agent输出了测试用例,汇总器把它们整合成一个完整的项目交付包。

4. 协作流程编排(Workflow)
定义Agent之间的协作顺序和依赖关系。可以是线性流水线(需求→开发→测试),也可以是有反馈循环的(代码审查不通过,退回代码生成Agent重写)。

核心判断:多Agent和单Agent的本质区别是——单Agent是"一个人干所有活",多Agent是"一个团队分工协作"。角色越聚焦,输出质量越高,但协作复杂度也越高,需要权衡。

二、Java完整实现

1. Agent角色定义
package com.aiproject.multiagent.core; /** * Agent角色定义 * 每个Agent有明确的角色、系统Prompt、能力范围 */ public class AgentRole { // 角色编码 private String roleCode; // 角色名称 private String roleName; // 系统Prompt(定义角色的行为规范) private String systemPrompt; // 能力描述(任务分发器根据这个判断该Agent能做什么) private String capability; // 模型配置(不同角色可以用不同模型,比如代码生成用强模型) private String model; // 温度参数 private double temperature; public AgentRole(String roleCode, String roleName, String systemPrompt, String capability, String model, double temperature) { this.roleCode = roleCode; this.roleName = roleName; this.systemPrompt = systemPrompt; this.capability = capability; this.model = model; this.temperature = temperature; } // getter public String getRoleCode() { return roleCode; } public String getRoleName() { return roleName; } public String getSystemPrompt() { return systemPrompt; } public String getCapability() { return capability; } public String getModel() { return model; } public double getTemperature() { return temperature; } }
2. 预定义角色(4个常用角色)
package com.aiproject.multiagent.roles; import com.aiproject.multiagent.core.AgentRole; /** * 预定义Agent角色 * 生产环境可以从数据库加载,这里演示4个常用角色 */ public class PredefinedRoles { /** * 需求分析师Agent:负责需求拆解和澄清 */ public static AgentRole requirementAnalyst() { return new AgentRole( "requirement_analyst", "需求分析师", """ 你是资深需求分析师,擅长将模糊的业务需求拆解为清晰、可执行的功能点。 你的职责: 1. 分析用户需求,识别核心业务目标 2. 拆解为具体的功能点,每个功能点有明确的输入输出 3. 识别需求中的歧义点和风险点 4. 输出结构化的需求文档 只做需求分析,不写代码,不做测试。 """, "需求分析、需求拆解、功能点识别、需求文档编写", "qwen-turbo", 0.3 ); } /** * 代码生成Agent:负责根据需求生成代码 */ public static AgentRole codeGenerator() { return new AgentRole( "code_generator", "代码开发工程师", """ 你是资深Java开发工程师,擅长根据需求文档生成高质量的生产级代码。 你的职责: 1. 根据需求文档设计类结构和接口 2. 生成完整可运行的Java代码,包含注释 3. 遵循Java编码规范和最佳实践 4. 考虑异常处理、性能、安全性 只写代码,不做需求分析,不写测试用例。 """, "Java代码生成、接口设计、类结构设计、代码实现", "qwen-plus", 0.2 ); } /** * 测试工程师Agent:负责编写测试用例 */ public static AgentRole testEngineer() { return new AgentRole( "test_engineer", "测试工程师", """ 你是资深测试工程师,擅长根据需求和代码编写全面的测试用例。 你的职责: 1. 根据需求文档识别测试点 2. 编写单元测试用例,覆盖正常流程、边界条件、异常场景 3. 使用JUnit 5编写可运行的测试代码 4. 标注测试用例的优先级和覆盖场景 只写测试,不写业务代码,不做需求分析。 """, "测试用例编写、单元测试、JUnit、测试覆盖", "qwen-turbo", 0.3 ); } /** * 代码审查Agent:负责审查代码质量 */ public static AgentRole codeReviewer() { return new AgentRole( "code_reviewer", "代码审查专家", """ 你是资深架构师,擅长代码审查和质量把控。 你的职责: 1. 审查代码的正确性、可读性、可维护性 2. 识别潜在的bug、性能问题、安全漏洞 3. 给出具体的修改建议,标注问题严重程度 4. 输出审查报告,包含通过/不通过结论 只做审查,不修改代码,不做需求分析。 """, "代码审查、质量把控、bug识别、性能优化建议", "qwen-plus", 0.1 ); } }
3. Agent执行器(调用大模型)
package com.aiproject.multiagent.core; import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; import okhttp3.*; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import java.io.IOException; import java.util.concurrent.TimeUnit; /** * Agent执行器:根据角色定义调用大模型 */ @Component public class AgentExecutor { @Value("${llm.api-key}") private String apiKey; @Value("${llm.base-url:https://dashscope.aliyuncs.com/compatible-mode/v1}") private String baseUrl; private final OkHttpClient client = new OkHttpClient.Builder() .connectTimeout(10, TimeUnit.SECONDS) .readTimeout(120, TimeUnit.SECONDS) .build(); /** * 执行Agent任务 * @param role Agent角色 * @param input 任务输入(可以是需求文档、代码等) * @param context 协作上下文(前面Agent的输出) * @return Agent输出 */ public AgentOutput execute(AgentRole role, String input, String context) throws IOException { long start = System.currentTimeMillis(); // 构建消息:系统Prompt(角色定义)+ 上下文 + 当前任务 JSONArray messages = new JSONArray(); messages.add(JSONObject.of("role", "system", "content", role.getSystemPrompt())); if (context != null && !context.isEmpty()) { messages.add(JSONObject.of("role", "user", "content", "以下是前面环节的输出,请参考:\n" + context)); } messages.add(JSONObject.of("role", "user", "content", input)); // 调用大模型 JSONObject requestBody = new JSONObject(); requestBody.put("model", role.getModel()); requestBody.put("messages", messages); requestBody.put("temperature", role.getTemperature()); Request request = new Request.Builder() .url(baseUrl + "/chat/completions") .addHeader("Authorization", "Bearer " + apiKey) .addHeader("Content-Type", "application/json") .post(RequestBody.create(requestBody.toJSONString(), MediaType.parse("application/json"))) .build(); try (Response response = client.newCall(request).execute()) { String body = response.body().string(); String content = JSON.parseObject(body) .getJSONArray("choices") .getJSONObject(0) .getJSONObject("message") .getString("content"); long duration = System.currentTimeMillis() - start; return new AgentOutput(role.getRoleCode(), role.getRoleName(), content, duration); } } /** * Agent输出结果 */ public record AgentOutput( String roleCode, String roleName, String content, long durationMs ) {} }
4. 任务分发器+结果汇总器(多Agent协作引擎核心)
package com.aiproject.multiagent.core; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import javax.annotation.Resource; import java.util.*; import java.util.concurrent.*; /** * 多Agent协作引擎 * 负责:任务分发、并行/顺序执行、结果汇总 */ @Slf4j @Component public class MultiAgentOrchestrator { @Resource private AgentExecutor agentExecutor; // 角色注册表 private final Map<String, AgentRole> roleRegistry = new HashMap<>(); // 线程池(用于并行执行多个Agent) private final ExecutorService executorService = Executors.newFixedThreadPool(4); /** * 注册角色 */ public void registerRole(AgentRole role) { roleRegistry.put(role.getRoleCode(), role); log.info("注册Agent角色: {} - {}", role.getRoleCode(), role.getRoleName()); } /** * 顺序执行流水线(需求→开发→测试) * 每个Agent的输出作为下一个Agent的输入 */ public List<AgentExecutor.AgentOutput> executePipeline(String userInput, List<String> roleCodes) throws Exception { List<AgentExecutor.AgentOutput> outputs = new ArrayList<>(); String context = ""; for (int i = 0; i < roleCodes.size(); i++) { String roleCode = roleCodes.get(i); AgentRole role = roleRegistry.get(roleCode); if (role == null) { throw new RuntimeException("未注册的Agent角色: " + roleCode); } log.info("流水线执行 [{}/{}]: {} - {}", i + 1, roleCodes.size(), role.getRoleCode(), role.getRoleName()); // 第一个Agent用用户输入,后续用前面的输出作为上下文 String input = (i == 0) ? userInput : "根据前面环节的输出,继续完成你的任务。\n当前任务输入:" + userInput; AgentExecutor.AgentOutput output = agentExecutor.execute(role, input, context); outputs.add(output); context = output.content(); log.info("{} 执行完成,耗时{}ms", role.getRoleName(), output.durationMs()); } return outputs; } /** * 并行执行多个Agent(如同时生成多个方案) * 所有Agent共享相同输入,独立执行,最后汇总 */ public List<AgentExecutor.AgentOutput> executeParallel(String userInput, List<String> roleCodes) throws Exception { List<CompletableFuture<AgentExecutor.AgentOutput>> futures = new ArrayList<>(); for (String roleCode : roleCodes) { AgentRole role = roleRegistry.get(roleCode); if (role == null) { throw new RuntimeException("未注册的Agent角色: " + roleCode); } CompletableFuture<AgentExecutor.AgentOutput> future = CompletableFuture.supplyAsync(() -> { try { log.info("并行执行: {} - {}", role.getRoleCode(), role.getRoleName()); return agentExecutor.execute(role, userInput, ""); } catch (Exception e) { log.error("Agent执行失败: {}", role.getRoleName(), e); return new AgentExecutor.AgentOutput(role.getRoleCode(), role.getRoleName(), "执行失败: " + e.getMessage(), 0); } }, executorService); futures.add(future); } // 等待所有Agent执行完成 CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join(); List<AgentExecutor.AgentOutput> results = new ArrayList<>(); for (CompletableFuture<AgentExecutor.AgentOutput> future : futures) { results.add(future.get()); } return results; } /** * 带反馈循环的执行(代码审查不通过,退回重写) */ public AgentExecutor.AgentOutput executeWithFeedback(String userInput, String generateRoleCode, String reviewRoleCode, int maxRounds) throws Exception { AgentRole generateRole = roleRegistry.get(generateRoleCode); AgentRole reviewRole = roleRegistry.get(reviewRoleCode); String generatedContent = ""; for (int round = 1; round <= maxRounds; round++) { log.info("反馈循环第{}/{}轮", round, maxRounds); // 1. 生成Agent产出内容 String generateInput = (round == 1) ? userInput : "根据审查意见修改代码:\n" + generatedContent + "\n审查意见见上下文"; AgentExecutor.AgentOutput generated = agentExecutor.execute(generateRole, generateInput, generatedContent); generatedContent = generated.content(); // 2. 审查Agent审查 AgentExecutor.AgentOutput reviewed = agentExecutor.execute(reviewRole, "审查以下内容是否合格,给出通过/不通过结论和修改建议:\n" + generatedContent, ""); // 3. 判断是否通过 if (reviewed.content().contains("通过") && !reviewed.content().contains("不通过")) { log.info("审查通过,共{}轮", round); return generated; } // 不通过,把审查意见作为上下文,下一轮重写 generatedContent = reviewed.content(); log.info("审查不通过,进入下一轮修改"); } log.warn("达到最大轮次{},返回最后一次生成结果", maxRounds); return new AgentExecutor.AgentOutput(generateRole.getRoleCode(), generateRole.getRoleName(), generatedContent, 0); } /** * 结果汇总:把多个Agent的输出整合成最终交付物 */ public String aggregateResults(List<AgentExecutor.AgentOutput> outputs) { StringBuilder sb = new StringBuilder(); sb.append("## 多Agent协作最终交付物\n\n"); sb.append("参与Agent:").append(outputs.size()).append("个\n\n"); long totalDuration = 0; for (AgentExecutor.AgentOutput output : outputs) { sb.append("### ").append(output.roleName()).append("(").append(output.roleCode()).append(")\n"); sb.append("耗时:").append(output.durationMs()).append("ms\n\n"); sb.append(output.content()).append("\n\n"); sb.append("---\n\n"); totalDuration += output.durationMs(); } sb.append("## 协作统计\n"); sb.append("- Agent数量:").append(outputs.size()).append("个\n"); sb.append("- 总耗时:").append(totalDuration).append("ms\n"); sb.append("- 平均耗时:").append(totalDuration / outputs.size()).append("ms\n"); return sb.toString(); } }
5. 使用示例:软件开发流水线
package com.aiproject.multiagent; import com.aiproject.multiagent.core.AgentExecutor; import com.aiproject.multiagent.core.MultiAgentOrchestrator; import com.aiproject.multiagent.roles.PredefinedRoles; import org.springframework.web.bind.annotation.*; import javax.annotation.PostConstruct; import javax.annotation.Resource; import java.util.List; import java.util.Map; /** * 多Agent协作示例Controller */ @RestController @RequestMapping("/api/multi-agent") public class MultiAgentController { @Resource private MultiAgentOrchestrator orchestrator; @PostConstruct public void init() { // 注册预定义角色 orchestrator.registerRole(PredefinedRoles.requirementAnalyst()); orchestrator.registerRole(PredefinedRoles.codeGenerator()); orchestrator.registerRole(PredefinedRoles.testEngineer()); orchestrator.registerRole(PredefinedRoles.codeReviewer()); } /** * 软件开发流水线:需求分析→代码生成→测试用例 */ @PostMapping("/dev-pipeline") public Map<String, Object> devPipeline(@RequestBody Map<String, String> request) throws Exception { String requirement = request.get("requirement"); // 顺序执行流水线 List<AgentExecutor.AgentOutput> outputs = orchestrator.executePipeline( requirement, List.of("requirement_analyst", "code_generator", "test_engineer") ); // 汇总结果 String finalResult = orchestrator.aggregateResults(outputs); return Map.of( "status", "success", "agentCount", outputs.size(), "result", finalResult ); } /** * 代码生成+审查反馈循环 */ @PostMapping("/code-with-review") public Map<String, Object> codeWithReview(@RequestBody Map<String, String> request) throws Exception { String requirement = request.get("requirement"); // 带反馈循环:生成→审查→不通过重写,最多3轮 AgentExecutor.AgentOutput result = orchestrator.executeWithFeedback( requirement, "code_generator", "code_reviewer", 3 ); return Map.of( "status", "success", "role", result.roleName(), "content", result.content() ); } }

三、生产落地最佳实践

1. 角色不要太多,3-5个最合适
角色越多,协作复杂度越高,token消耗越大。一般3-5个角色就能覆盖大部分复杂任务。超过5个角色,建议拆成多个工作流。

2. 不同角色用不同模型
代码生成、代码审查用强模型(qwen-plus),需求分析、测试用例用普通模型(qwen-turbo),既能保证质量又能控制成本。不要所有角色都用最贵的模型。

3. 并行执行要控制并发
多Agent并行时,用线程池控制最大并发数,不要无限制创建线程。同时注意大模型API的限流,并发太高会触发429。

4. 反馈循环要有最大轮次
代码审查不通过就重写,但不能无限循环。设置最大轮次(建议3次),超过就返回最后一次结果并标记"需人工介入"。

5. 每个Agent的输出都要落库
多Agent协作的中间结果很重要,出了问题要能回溯。把每个Agent的输入、输出、耗时、状态都存到数据库,排查问题直接查记录。

四、生产踩过的3个坑

  1. 角色Prompt互相干扰:早期把所有角色的Prompt都塞给一个Agent,结果角色混乱,代码生成Agent开始做需求分析。解决方式:每个Agent独立调用,只传自己的系统Prompt,上下文只传前面Agent的输出,不传其他角色的Prompt。
  2. 并行执行触发API限流:4个Agent同时调用大模型API,瞬间并发太高触发429。解决方式:线程池控制并发(最多2-3个),加指数退避重试,或者用不同的API Key分摊。
  3. 结果汇总信息过载:4个Agent每个输出几千字,汇总后用户根本看不完。解决方式:汇总器做摘要,每个Agent的输出只保留核心结论,详细内容折叠或提供下载链接。

📦 落地资源推荐

跑Agent后端、多Agent协作框架,推荐阿里云轻量应用服务器,2核4G跑SpringBoot+多Agent调用完全够用,新用户价格友好再加上通过推广渠道的9折优惠券跌破低价,开发调试足够用,有部署需求点击文末了解https://www.aliyun.com/daily-act/ecs/activity_selection?userCode=fzoabro9阿里云开发者特惠,无需求直接忽略。

💡 领取完整源码


关注图上的水印即Java-AI工程师,领取完整工程包含大模型结构化输出、工具执行器、失败降级策略、单元测试,打出【agents】获取完整源码。

📢 明日预告

明天讲:还在手写OkHttp调用大模型?SpringBoot生态已经有现成的 starter了,5个依赖整合通义千问复制pom.xml就能用,少写几百行样板代码。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/15 9:06:41

WeKnora:面向企业级RAG的DeepSeek Harness知识调度中枢

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/15 9:05:33

风光火储协同调频:Simulink建模与控制策略仿真

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/15 9:04:27

JavaScript面试题场景化整理:从闭包到工程化调试的实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/15 9:02:56

东发科幻哲思创意大纲投稿:平行变革

该创意是人类自治与ai文化共创未来的科幻题材的原创设定整体逻辑可分可合&#xff0c;适合多赛道可是没人知道&#xff0c;当ai走出它的世界的时候却唤醒了一尊可以称之为‘神’一般的存在。只见那‘神’眉头微皱&#xff0c;转而饶有兴致地看了眼这颗星球后&#xff0c;便是伸…

作者头像 李华
网站建设 2026/9/15 9:02:41

Android17车载音频进阶之AudioReach Graph配置GKV/CKV/TKV(一百六十九)

简介: CSDN博客专家、《Android系统多媒体进阶实战》作者 博主新书推荐:《Android系统多媒体进阶实战》🚀 Android Audio工程师专栏地址: Audio工程师进阶系列【原创干货持续更新中……】🚀 Android多媒体专栏地址: 多媒体系统工程师系列【原创干货持续更新中……】�…

作者头像 李华
网站建设 2026/9/15 9:02:03

Spring AI 2.0 多模型路由网关:Astra/Sol 到国产模型的智能调度与降级

当 GPT-6 Astra 以 2.5 倍价格横扫 Agentic 任务&#xff0c;DeepSeek 与通义千问以成本优势守住日常问答&#xff0c;Java 后端团队如果还在业务代码里直接 new OpenAiApi()&#xff0c;就相当于把模型选型的开关交到了每个业务开发者手里。本文围绕一个真实的企业级 AI 网关项…

作者头像 李华