1. 一个Java老兵的AI Agent转型之路1.1 为什么我决定从Java转向AI Agent写了十三年代码Spring全家桶闭着眼睛都能搭出一套微服务架构JVM调优参数比自家WiFi密码还熟。但去年开始身边越来越多项目开始提“智能体”“Agent”“自动化决策”这些词客户的需求也从“帮我做个后台管理系统”变成了“能不能让系统自己分析数据、自己出报告、自己执行任务”。说实话一开始我是抗拒的。第一反应是这玩意儿是不是又要学Python是不是要把PyTorch、Transformer那些东西从头啃一遍我连numpy的axis都记不住这不是要命吗但真正扎进去做了几个项目之后我发现了一个反直觉的事实做AI Agent90%的工作根本不需要写Python更不需要训练模型。你需要的是一套工程化的思维而这恰恰是Java老兵最擅长的东西。这篇文章就是我这大半年踩坑、试错、重构、上线的完整复盘。不讲虚的全是能直接抄作业的实操路径。如果你也是Java背景想切入AI Agent但不知道从哪下手这篇内容应该能帮你省下至少三个月的弯路。1.2 一个普遍的认知误区AI Agent不等于模型训练很多人一听到AI Agent脑子里立刻浮现出这样的画面打开Jupyter Notebook导入PyTorch写几百行代码定义神经网络然后跑几天几夜训练模型。这个画面没错但那是模型训练工程师的工作。AI Agent的核心不是训练模型而是编排能力——把已有的模型能力、工具接口、业务逻辑、状态管理组合成一个能自主完成任务的系统。打个比方模型训练是造发动机AI Agent是造整车。你不需要会造发动机才能造车你需要的是知道怎么把发动机、变速箱、底盘、电气系统整合在一起让它跑起来。而整车工程恰恰是Java工程师的主场。我做的第一个Agent项目是一个自动化工单处理系统。核心逻辑是接收用户工单→调用大模型理解意图→查询知识库→生成回复→判断是否需要人工介入→执行后续动作。整个系统里Python只占不到10%就是调用模型API的那几行剩下90%全是Java写的编排逻辑、状态机、重试机制、监控告警。1.3 本文适合谁读能解决什么问题这篇复盘适合以下几类人Java后端工程师有3年以上经验想切入AI Agent但不知道从哪开始不想从头学Python数据科学栈。架构师/技术负责人需要评估AI Agent在现有Java技术栈中的落地可行性想知道工程上怎么拆解。全栈开发者对AI应用感兴趣但被“必须学Python”的说法劝退过。读完你能得到什么一套完整的Java技术栈AI Agent落地方案包括工具选型、架构设计、核心代码骨架、踩坑记录和排查手册。我不会只讲概念每个环节都会给出可运行的代码片段和配置示例。注意本文假设你有基本的Java开发经验了解Spring Boot和Maven。如果你完全没接触过Java这篇文章的部分内容可能不太好消化。2. 核心思路拆解为什么Java做Agent反而有优势2.1 Agent的本质是编排不是推理先把这个事情说透。一个AI Agent系统拆开来看就是四层层级职责常用技术Java适配度交互层接收输入、返回结果HTTP/WebSocket极高编排层任务分解、流程控制、状态管理状态机、工作流引擎极高能力层调用模型、工具、外部服务API调用、RPC高模型层推理、生成、理解大模型API低但不需要自己写看到没有模型层是最底下的一层而且你大概率是调用现成的API不需要自己训练。上面三层全是Java的强项。我见过太多人卡在“我要先学Python”这个心理门槛上结果三个月过去了还在看Python基础语法。而实际上你完全可以用Java把整个Agent框架搭起来模型调用就是一个HTTP请求的事。2.2 为什么90%的人挂在“工具选型”这个坑上标题里说的“90%的人挂在同一个坑”这个坑就是工具选型。具体表现是一上来就纠结用LangChain还是LlamaIndex用AutoGPT还是自己写用Python还是Java。纠结了两周代码一行没写。我的建议非常直接如果你已经有Java技术栈的积累就用Java写编排层模型调用用HTTP API。不要为了用某个框架而切换语言。框架是工具不是目的。LangChain确实很火但它的核心价值在于提供了一套Python生态的抽象。如果你用Java完全可以用Spring Boot HTTP Client 状态机实现同样的效果而且更可控、更好调试、更容易集成到现有系统。我实测下来用Java写一个支持多轮对话、工具调用、状态管理的Agent核心框架代码量大概在2000行左右。这个量级对于有经验的Java工程师来说两周就能搞定。2.3 Java技术栈做Agent的三大优势第一工程化能力强。Java生态有成熟的依赖注入、AOP、事务管理、连接池、监控体系。这些东西在Agent系统里全用得上。比如你需要给模型调用加重试、熔断、限流Resilience4j直接搞定你需要记录每次调用的耗时和token消耗Micrometer Prometheus一套带走。第二并发处理成熟。Agent系统经常需要并行调用多个工具、同时处理多个会话。Java的线程池、CompletableFuture、响应式编程WebFlux都是经过大规模验证的方案。Python的asyncio虽然也能用但在高并发场景下的稳定性和可观测性跟Java比还是有差距。第三类型安全和可维护性。Agent系统的状态流转、工具参数、返回值格式用Java的强类型系统来描述比Python的字典和动态类型清晰太多。当你的Agent支持20个工具、10种状态的时候类型安全就是救命稻草。2.4 一个反直觉的结论不需要学Python我知道这个结论会得罪很多人但事实就是对于绝大多数AI Agent应用场景你不需要学Python。你需要的是理解大模型的基本能力边界能做什么、不能做什么掌握Prompt Engineering的基本技巧知道怎么调用模型APIHTTP请求会设计工具接口和状态流转这些东西跟Python没有半毛钱关系。你用Java、Go、Node.js都能做。我甚至见过用PHP做Agent的照样跑得挺好。当然如果你要做模型微调、要做深度学习研究、要自己训练模型那Python是必须的。但那是另一个赛道跟AI Agent应用开发是两回事。3. 核心细节解析与实操要点3.1 模型调用层把大模型当成一个HTTP服务这是整个系统里唯一跟“AI”沾边的部分但本质上就是一个HTTP请求。我以调用某大模型API为例给出Java的实现骨架public class ModelClient { private final HttpClient httpClient; private final String apiKey; private final String endpoint; public ModelResponse chat(ListMessage messages, ModelConfig config) { MapString, Object requestBody new HashMap(); requestBody.put(model, config.getModelName()); requestBody.put(messages, messages); requestBody.put(temperature, config.getTemperature()); requestBody.put(max_tokens, config.getMaxTokens()); HttpRequest request HttpRequest.newBuilder() .uri(URI.create(endpoint)) .header(Content-Type, application/json) .header(Authorization, Bearer apiKey) .POST(HttpRequest.BodyPublishers.ofString( JsonUtils.toJson(requestBody))) .timeout(Duration.ofSeconds(60)) .build(); HttpResponseString response httpClient.send(request, HttpResponse.BodyHandlers.ofString()); return JsonUtils.fromJson(response.body(), ModelResponse.class); } }就这么简单。核心就是构造JSON、发POST请求、解析响应。但有几个细节需要注意超时设置。大模型响应时间波动很大简单问题可能2秒返回复杂推理可能30秒以上。我建议连接超时设10秒读取超时设60-120秒。不要用默认值默认值往往太短。重试策略。模型API偶尔会返回429限流或503服务不可用。需要加指数退避重试。我用Resilience4j的Retry模块配置如下resilience4j: retry: instances: modelClient: maxAttempts: 3 waitDuration: 2s enableExponentialBackoff: true exponentialBackoffMultiplier: 2 retryExceptions: - java.io.IOException - java.util.concurrent.TimeoutExceptionToken计数。每次调用都要记录消耗的token数用于成本核算和限流。大部分模型API的响应里会带usage字段直接解析出来存库就行。实操心得不要自己写HTTP客户端用OkHttp或Apache HttpClient。Java 11自带的HttpClient也能用但在连接池管理和超时控制上不如前两者灵活。3.2 工具调用层Agent的手和脚Agent之所以叫Agent是因为它能调用工具。没有工具调用的Agent就是一个聊天机器人。工具调用的核心设计是定义工具接口→注册工具→让模型决定调用哪个工具→执行工具→把结果返回给模型。先定义工具接口public interface AgentTool { String getName(); String getDescription(); JsonSchema getParameterSchema(); ToolResult execute(MapString, Object parameters); }然后实现具体工具。比如一个查询天气的工具Component public class WeatherTool implements AgentTool { Override public String getName() { return get_weather; } Override public String getDescription() { return 查询指定城市的当前天气情况; } Override public JsonSchema getParameterSchema() { return JsonSchema.builder() .addProperty(city, string, 城市名称如北京、上海) .addRequired(city) .build(); } Override public ToolResult execute(MapString, Object parameters) { String city (String) parameters.get(city); // 调用天气API WeatherData data weatherService.query(city); return ToolResult.success(data.toJson()); } }工具注册中心Component public class ToolRegistry { private final MapString, AgentTool tools new ConcurrentHashMap(); Autowired public ToolRegistry(ListAgentTool toolList) { toolList.forEach(tool - tools.put(tool.getName(), tool)); } public AgentTool getTool(String name) { return tools.get(name); } public ListToolDefinition getAllToolDefinitions() { return tools.values().stream() .map(tool - ToolDefinition.builder() .name(tool.getName()) .description(tool.getDescription()) .parameters(tool.getParameterSchema()) .build()) .collect(Collectors.toList()); } }这里的关键点是工具的description和parameter schema会作为prompt的一部分发给模型。模型根据这些描述来决定是否调用工具、调用哪个工具、传什么参数。所以工具描述写得好不好直接决定了Agent的智能程度。我踩过的坑是描述写得太简略模型经常选错工具或者参数传错。后来我把每个工具的描述都写成了“什么时候用这个工具、什么时候不用、参数格式是什么”的完整说明准确率立刻上去了。3.3 状态管理与对话历史Agent不是一次性的问答而是有状态的。它需要记住之前说过什么、做过什么、当前任务进行到哪一步了。我用一个ConversationContext来管理状态public class ConversationContext { private String conversationId; private ListMessage messages; private MapString, Object variables; private AgentState state; private int turnCount; private Instant createdAt; private Instant lastActiveAt; public void addMessage(Message message) { this.messages.add(message); this.lastActiveAt Instant.now(); this.turnCount; } public ListMessage getRecentMessages(int limit) { int size messages.size(); int fromIndex Math.max(0, size - limit); return messages.subList(fromIndex, size); } }状态存储我用Redis因为Agent会话通常需要设置过期时间而且读写频率高。序列化用Jackson把整个Context存成JSON字符串。Repository public class ConversationRepository { private final RedisTemplateString, String redisTemplate; private static final Duration TTL Duration.ofHours(2); public void save(ConversationContext context) { String key agent:conv: context.getConversationId(); String value JsonUtils.toJson(context); redisTemplate.opsForValue().set(key, value, TTL); } public ConversationContext load(String conversationId) { String key agent:conv: conversationId; String value redisTemplate.opsForValue().get(key); if (value null) { return null; } return JsonUtils.fromJson(value, ConversationContext.class); } }注意对话历史不能无限增长。一方面token成本会越来越高另一方面模型的上下文窗口有限。我的做法是保留最近N轮对话更早的对话做摘要压缩。摘要用模型生成把10轮对话压缩成一段200字的总结。3.4 Prompt模板管理Prompt是Agent的灵魂。但很多人把Prompt硬编码在Java代码里这是大忌。我的做法是把Prompt模板放在配置中心或者数据库里支持热更新。模板用简单的占位符语法你是一个专业的客服助手。当前时间是{{current_time}}。 用户信息{{user_profile}} 可用工具{{tool_definitions}} 请根据用户的问题决定是否需要调用工具。 如果需要调用工具请以JSON格式返回工具名称和参数。 如果不需要直接回复用户。 用户问题{{user_input}}Java端用简单的字符串替换public class PromptTemplate { private final String template; public String render(MapString, Object variables) { String result template; for (Map.EntryString, Object entry : variables.entrySet()) { String placeholder {{ entry.getKey() }}; result result.replace(placeholder, String.valueOf(entry.getValue())); } return result; } }这样做的好处是调整Prompt不需要重新部署运营人员也能参与优化。我实测下来同一个模型Prompt优化前后效果差距能到30%以上。4. 实操过程与核心环节实现4.1 环境准备与依赖配置先说一下我的技术栈选型组件选型理由框架Spring Boot 3.x生态成熟集成方便HTTP客户端OkHttp 4.x连接池管理好超时控制灵活JSONJacksonSpring默认性能足够状态存储Redis读写快支持TTL重试熔断Resilience4j轻量配置灵活监控Micrometer Prometheus标准化可视化方便构建Maven团队熟悉Maven依赖dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-data-redis/artifactId /dependency dependency groupIdcom.squareup.okhttp3/groupId artifactIdokhttp/artifactId version4.12.0/version /dependency dependency groupIdio.github.resilience4j/groupId artifactIdresilience4j-spring-boot3/artifactId version2.1.0/version /dependency dependency groupIdio.micrometer/groupId artifactIdmicrometer-registry-prometheus/artifactId /dependency /dependencies4.2 核心执行循环的实现Agent的核心是一个循环接收输入→调用模型→判断是否需要工具→执行工具→把结果返回模型→生成最终回复。Service public class AgentExecutor { private final ModelClient modelClient; private final ToolRegistry toolRegistry; private final ConversationRepository conversationRepository; private final PromptTemplate promptTemplate; private static final int MAX_ITERATIONS 10; public AgentResponse execute(String conversationId, String userInput) { ConversationContext context loadOrCreateContext(conversationId); context.addMessage(Message.user(userInput)); for (int i 0; i MAX_ITERATIONS; i) { // 1. 构造prompt String prompt buildPrompt(context); // 2. 调用模型 ModelResponse response modelClient.chat( context.getRecentMessages(20), buildModelConfig() ); // 3. 解析模型输出 AgentAction action parseAction(response); // 4. 判断是否需要调用工具 if (action.isToolCall()) { ToolResult toolResult executeTool(action); context.addMessage(Message.tool( action.getToolName(), toolResult.getContent() )); continue; } // 5. 生成最终回复 context.addMessage(Message.assistant(response.getContent())); conversationRepository.save(context); return AgentResponse.success(response.getContent()); } return AgentResponse.error(达到最大迭代次数任务未完成); } private ToolResult executeTool(AgentAction action) { AgentTool tool toolRegistry.getTool(action.getToolName()); if (tool null) { return ToolResult.error(工具不存在: action.getToolName()); } try { return tool.execute(action.getParameters()); } catch (Exception e) { log.error(工具执行失败: {}, action.getToolName(), e); return ToolResult.error(工具执行异常: e.getMessage()); } } }这个循环有几个关键设计点最大迭代次数限制。防止模型陷入死循环一直调用工具不返回结果。我设的是10次大部分任务3-5次就能完成。工具执行异常处理。工具执行失败不能直接抛异常中断整个流程而是要把错误信息返回给模型让模型决定下一步怎么做。比如查询天气失败模型可以选择告诉用户“暂时查不到”或者尝试用其他方式获取信息。上下文窗口管理。每次调用模型只传最近20条消息避免token超限。更早的消息通过摘要压缩。4.3 工具调用的参数校验与安全控制工具调用是Agent系统里风险最高的环节。模型可能传错参数也可能被恶意输入诱导调用不该调用的工具。参数校验我用JSON Schemapublic class ToolParameterValidator { public ValidationResult validate(AgentTool tool, MapString, Object parameters) { JsonSchema schema tool.getParameterSchema(); // 检查必填参数 for (String required : schema.getRequired()) { if (!parameters.containsKey(required)) { return ValidationResult.fail( 缺少必填参数: required); } } // 检查参数类型 for (Map.EntryString, Object entry : parameters.entrySet()) { PropertySchema prop schema.getProperty(entry.getKey()); if (prop null) { return ValidationResult.fail( 未知参数: entry.getKey()); } if (!prop.getType().matches(entry.getValue())) { return ValidationResult.fail( 参数类型错误: entry.getKey()); } } return ValidationResult.success(); } }安全控制方面我做了三层防护第一层工具白名单。每个Agent实例只能调用被授权的工具。比如客服Agent不能调用数据库删除工具。第二层参数范围限制。比如查询订单的工具订单ID必须符合特定格式发送邮件的工具收件人必须在允许的域名范围内。第三层敏感操作二次确认。对于删除、修改、支付等敏感操作Agent不能直接执行必须生成确认请求由人工确认后再执行。踩坑记录有一次测试时模型把“删除所有测试数据”理解成了“删除所有数据”差点把生产库清了。幸好加了参数范围限制只允许删除带“test_”前缀的数据。这个教训让我意识到Agent系统的安全控制再怎么强调都不为过。4.4 监控与可观测性建设Agent系统比普通服务更难调试因为它的行为是不确定的。同一个输入模型可能给出不同的输出。所以监控和日志特别重要。我记录的关键指标指标说明告警阈值model_call_duration模型调用耗时P99 30smodel_call_tokenstoken消耗量单次 4000tool_call_count工具调用次数单会话 20agent_iterations循环迭代次数 8agent_error_rate执行失败率 5%conversation_duration会话总时长 5min用Micrometer埋点Component public class AgentMetrics { private final MeterRegistry registry; private final Timer modelCallTimer; private final Counter toolCallCounter; public AgentMetrics(MeterRegistry registry) { this.registry registry; this.modelCallTimer Timer.builder(agent.model.call.duration) .publishPercentiles(0.5, 0.95, 0.99) .register(registry); this.toolCallCounter Counter.builder(agent.tool.call.count) .register(registry); } public T T recordModelCall(SupplierT supplier) { return modelCallTimer.record(supplier); } public void recordToolCall(String toolName) { toolCallCounter.increment(); registry.counter(agent.tool.call, tool, toolName).increment(); } }日志方面我要求每次模型调用都记录完整的prompt和response。这些日志量很大所以只保留最近7天而且做了脱敏处理。public class AgentLogger { private static final Logger log LoggerFactory.getLogger(AGENT_TRACE); public void logModelCall(String conversationId, ListMessage messages, ModelResponse response) { if (log.isDebugEnabled()) { log.debug(convId{}, messages{}, response{}, tokens{}, conversationId, JsonUtils.toJson(messages), response.getContent(), response.getUsage().getTotalTokens()); } } }5. 常见问题与排查技巧实录5.1 模型不调用工具怎么办这是最常见的问题。你定义了一堆工具但模型就是不用直接自己编答案。原因通常有三个工具描述不够清晰。模型不知道什么时候该用这个工具。解决办法是把描述写成“当用户询问XX时使用此工具参数格式为YY”。Prompt没有明确要求使用工具。需要在system prompt里明确说“你有以下工具可以使用当需要获取实时信息或执行操作时必须调用工具”。模型能力不足。一些小模型对工具调用的支持不好。如果条件允许换一个工具调用能力更强的模型。我的排查步骤检查工具描述是否包含“何时使用”的说明检查system prompt是否明确要求使用工具手动构造一个必须用工具的场景测试如果还不行在prompt里加few-shot示例5.2 工具调用参数错误怎么排查模型传错参数是家常便饭。常见错误包括参数名拼错、参数类型不对、缺少必填参数、参数值超出范围。我的排查方法public class ToolCallDebugger { public void debugToolCall(String toolName, MapString, Object parameters, ValidationResult validation) { if (!validation.isSuccess()) { log.warn(工具调用参数校验失败: tool{}, params{}, error{}, toolName, JsonUtils.toJson(parameters), validation.getErrorMessage()); // 记录到专门的调试表用于后续分析 debugRepository.save(ToolCallDebug.builder() .toolName(toolName) .parameters(JsonUtils.toJson(parameters)) .errorMessage(validation.getErrorMessage()) .timestamp(Instant.now()) .build()); } } }然后定期分析这些调试记录找出高频错误针对性地优化工具描述和参数schema。实操心得在工具描述里给出参数示例能大幅降低参数错误率。比如“city参数示例北京、上海、广州”比只写“城市名称”效果好得多。5.3 响应时间过长怎么优化Agent系统的响应时间 模型调用时间 × 迭代次数 工具执行时间。优化要从这三个维度入手。减少迭代次数。优化prompt让模型尽量一次就给出最终答案而不是反复调用工具。我实测下来好的prompt能把平均迭代次数从5次降到2-3次。并行调用工具。如果模型一次返回了多个工具调用请求可以并行执行。用CompletableFuturepublic ListToolResult executeToolsParallel(ListAgentAction actions) { ListCompletableFutureToolResult futures actions.stream() .map(action - CompletableFuture.supplyAsync( () - executeTool(action), toolExecutor)) .collect(Collectors.toList()); return futures.stream() .map(CompletableFuture::join) .collect(Collectors.toList()); }缓存常用结果。有些工具调用结果可以缓存比如查询城市信息、查询产品目录。用Caffeine做本地缓存LoadingCacheString, ToolResult cache Caffeine.newBuilder() .maximumSize(1000) .expireAfterWrite(Duration.ofMinutes(10)) .build(key - executeToolDirectly(key));流式输出。如果模型支持流式返回可以边生成边推送给前端用户感知的响应时间会大幅缩短。5.4 常见问题速查表问题现象可能原因排查方法解决方案模型不调用工具描述不清/Prompt未要求检查工具描述和system prompt优化描述加few-shot示例参数错误schema不清晰查看调试日志加参数示例加强校验响应超时迭代次数过多查看迭代计数优化prompt设最大迭代限制工具执行失败外部服务异常查看工具执行日志加重试返回错误给模型上下文丢失存储过期/序列化问题检查Redis和序列化配置调整TTL检查Jackson配置Token超限历史消息过长查看token计数压缩历史限制消息条数重复调用同一工具模型陷入循环查看调用记录加去重逻辑限制单工具调用次数5.5 几个只有踩过才知道的坑坑一不要用模型做确定性判断。比如“判断用户是否在生气”这种任务模型可能给出不一致的结果。确定性逻辑用代码写模型只负责模糊理解和生成。坑二工具返回值要精简。我一开始把整个数据库查询结果返回给模型结果token直接爆了。后来改成只返回关键字段token消耗降了70%。坑三会话隔离要做好。多个用户同时使用时会话ID必须严格隔离。我见过因为会话ID生成重复导致A用户看到B用户对话的事故。坑四模型版本要锁定。模型提供方会不定期更新模型版本行为可能发生变化。生产环境一定要锁定具体版本号不要用latest。坑五做好降级方案。模型API不可用时系统要能降级到规则引擎或者直接返回预设话术不能整个服务挂掉。6. 从Java老兵视角看AI Agent的未来6.1 工程能力才是稀缺资源做了大半年AI Agent我最大的感受是模型能力正在快速商品化但工程能力依然是稀缺资源。调用模型API谁都会但把模型能力稳定、可靠、安全地集成到业务系统里这是需要多年工程经验积累的。你需要考虑并发、需要考虑容错、需要考虑监控、需要考虑安全、需要考虑成本。这些东西跟做传统后端服务没有本质区别。我甚至觉得AI Agent的出现反而让Java工程师的价值更大了。因为Agent系统对工程化的要求比传统系统更高——行为不确定、依赖外部服务、成本敏感、安全风险大。这些挑战恰恰是Java工程师擅长的领域。6.2 给Java同行的几点建议如果你也想切入AI Agent方向我的建议是不要从头学Python。除非你要做模型训练否则Java完全够用。把时间花在理解Agent的架构模式和工程实践上回报率高得多。从一个小场景切入。不要一上来就做通用Agent平台先找一个具体的业务场景比如自动化工单分类、智能客服辅助、数据报告生成。小场景容易闭环容易看到效果。重视Prompt Engineering。这是Agent开发的核心技能之一。同样的模型好的Prompt和差的Prompt效果差距巨大。多花时间研究Prompt的写法比研究框架源码有用。建立评估体系。Agent的效果很难用传统测试用例来验证。你需要建立一套评估体系包括准确率、响应时间、成本、用户满意度等指标。没有评估就没有优化方向。保持学习但不要焦虑。AI领域变化很快每周都有新框架、新模型出来。但底层的东西变化没那么快——状态管理、工具调用、错误处理、安全控制这些核心问题几年内不会变。把基础打牢新东西来了快速适配就行。6.3 一个值得尝试的扩展方向如果你已经跑通了一个基础Agent下一步可以尝试多Agent协作。思路是把复杂任务拆解成多个子任务每个子任务由一个专门的Agent负责Agent之间通过消息传递协作。比如一个报告生成系统可以有数据查询Agent、数据分析Agent、报告撰写Agent、审核Agent各司其职。Java实现多Agent协作可以用Actor模型比如Akka也可以用简单的消息队列。核心是定义好Agent之间的通信协议和任务分配策略。这个方向目前还在早期但我觉得潜力很大。尤其是对于复杂业务流程的自动化多Agent协作比单Agent更能应对。最后分享一个小技巧在Agent的system prompt里加一句“如果你不确定就说不知道不要编造”。这一句话能减少80%的幻觉问题。简单但极其有效。