Java 的 AI Agent 反击战:别急着说 Python 不行,先看看是谁的战场

回想之前的事情,朋友打来电话,凌晨两点,声音都是哑的。
「上线了。然后呢?」
他们的 AI Agent 挂了:GIL 锁死、状态全乱、微服务裸奔。
团队用 Python 两周跑通了原型,CTO 当场拍板上线。结果第一个并发高峰,系统直接趴窝。我去他办公室的时候,键盘上 Ctrl+C 那个键帽,你经常复制代码就知道,那个键上的字母会先磨没。他的就是。
屏幕右下角的时间跳得让人心慌。白板上画满了箭头和方块,有些被擦了重画好几遍,边缘糊成一片灰。外卖盒堆在角落里,塑料味混着空调的冷风。
他指着监控屏上一片飘红的数据,停了几秒。
「要不…用 Java 重写吧。」
这句话我这两年听了不下十遍。
01. 不是 Python 不行,是战场变了
Python 在 AI 算法层是王者。这点没得争。
但 AI Agent 这玩意儿吧…本质上就是个工程框架。管对话上下文、编工具调用、处理并发、保数据一致性。这些活,Python 真不是强项。
怎么形容呢。Python 做 AI 就像一把青龙偃月刀,抡起来虎虎生风。但你要拿它当螺丝刀用…方向不太对。
我之前踩过的坑,零零碎碎攒了这么几个。说来也怪,每次都是不同的项目,踩进去的坑却差不多。
类型安全那个事儿最折腾。 Agent 要调工具,工具要传参数。参数错了,轻则崩,重则数据污染。大模型返回的 JSON 里藏着什么幺蛾子你根本不知道。也许今天好好的,明天换个模型版本,输出格式变了一点,全完蛋。Python 的动态类型在这种场景下就是裸奔。换 Java,编译期就给你拦住了。
GIL 那个事儿嘛… 懂得都懂。Agent 之间要独立推理、调工具、读写记忆,全是 IO。Python 的 GIL 一锁,开再多线程也白搭。Java 的虚拟线程倒是天然适合这种活儿。IO 密集型场景下,虚拟线程的吞吐量能提升 60% 以上,延迟降低近 30%,有独立研究数据支撑。
状态管理这事儿最让我头疼。 不是技术难,是 Python 这边没什么成熟的方案。Redis 存会话、数据库做持久化、分布式锁保一致,Java 这边一上来就是现成的。Python 呢?得自己攒。攒出来的东西,你敢直接上生产?
微服务治理那块…算了不说了。 Spring Cloud 生态在那摆着,Python 这边差了多少年积累,大家心里都有数。从 JetBrains 连续多年的开发者生态调研看,Java 在微服务领域的使用率一直在 30% 到 40% 之间,是 Python 的两倍以上。生态这东西,数据会说话。选技术栈跟选房子一样:地段,地段,还是地段。生态就是地段。
还有个事儿:招人。 在国内找个能写好 Python 服务端的,有时候真比找 Java 架构师还难。代码写出来要有人维护,人是绕不过去的坎。
这五个坑,哪个 Python 搞不定?都能搞定。但代价呢?时间、成本、团队耐心。值不值,自己算。
好吧,我的结论已经很明显了。但再说一遍也无妨:AI Agent 在企业级落地这事儿,Java 生态接过 Python 的接力棒,只是时间问题。

02. Java 生态的排面
现在 Java 这边主流的 AI Agent 框架有三个:Spring AI、LangChain4j、AgentScope。
不是「哪个最好」。是「你的场景该用哪个」。这话说起来像废话,但太多人一上来就搜「哪个最强」,然后照着 GitHub Star 数选。选完了才发现不对劲。
Spring AI:老朋友的新玩具
团队全是 Spring Boot 底子的话,Spring AI 最自然。它把 LLM 当基础设施组件,像操作数据库一样操作 AI 模型。
@Servicepublic class KnowledgeService { private final ChatClient chatClient; public String ask(String question, String conversationId) { return chatClient.prompt() .advisors(ad -> ad.param("conversation_id", conversationId)) .user(question) .call() .content(); }}
跟 Spring Data JPA 几乎一样。学习成本?几乎没有。但代价是强绑定 Spring。不是 Spring Boot 技术栈?这东西基本没法用。
LangChain4j:灵活、轻量、哪都能跑
要解耦 Spring,对吞吐量和资源占用有要求,LangChain4j 更合适。
它的设计理念很有意思:定义一个 Java 接口,加几个注解,框架自动给你生成 Agent。
public interface HrAgent { @SystemMessage("你是资深 HR 助理,负责简历初筛") String screen(@V("jobDesc") String jobDesc, @V("resume") String resume);}
底层用动态代理把接口调用转成大模型交互加工具调用的 ReAct 循环。没运行时依赖容器,Quarkus、Spring Boot、甚至纯 Java SE 都能跑,灵活度是几个框架里最高的。
AgentScope:分布式多 Agent 的「核武器」
场景复杂到需要多个异构 Agent 长时间协作,比如自动化研报生成、跨部门智能决策,AgentScope 是唯一认真的选项。
Actor 模型加 A2A 通信协议,Agent 之间可以互相发现、互相调用,像 RPC 一样自然。还有可视化调试平台,能回放 Agent 的完整推理链。
但配置链路和学习曲线…说实话,挺陡的。就做个 RAG 问答的话,杀鸡用牛刀了。
来,理一下思路:
你的场景是什么?├─ Spring Boot 技术栈 → Spring AI├─ 非 Spring / 高吞吐 → LangChain4j ├─ 多 Agent 长周期协作 → AgentScope└─ 混合架构 → 按领域划分,别混着用
别问我哪个「最好」。我说了不算。
但如果非要推一个…LangChain4j 弹性是最大的。不绑定 Spring,往下能跑 Quarkus 追性能,往上能接 AgentScope 做编排,横向还能跟 Spring AI 互换模型层。
当然,这只是我的偏见。你完全可以有不同看法,而且最好有,不然这行业也太无聊了。

03. 讲个案例吧
拿 LangChain4j 写个 HR 简历初筛 Agent。这事我帮朋友做过,不算复杂,但该有的都有了。
业务背景:HR 每天收几百份简历,要自动解析、打分、更新 ATS 状态、发邀约。
先定义工具。每个工具就是一个 Java 方法,加个 @Tool 注解:
@Componentpublic class HrTools { @Tool("提取候选人技能、工作年限和教育背景") public CandidateProfile parseResume( @P("简历原始文本") String text) { return ResumeParser.parse(text); } @Tool("根据岗位要求打分,0到100") public int scoreCandidate( @P("岗位描述") String jd, @P("候选人信息JSON") String json) { return ScoringEngine.score(jd, CandidateProfile.fromJson(json)); } @Tool("更新候选人在ATS系统中的状态") public String updateStatus( @P("候选人ID") String id, @P("目标状态") String status) { atsClient.updateStatus(id, status); return "状态已更新为 " + status; }}
然后框架自动组装:
AiServices.builder(HrAgent.class) .chatLanguageModel(model) .chatMemoryProvider(id -> MessageWindowChatMemory.withMaxMessages(20)) .tools(hrTools) .build();
底层大模型自己判断该调哪个工具、参数怎么传、什么时候追问。
几个工程细节,都是踩过坑才懂的:
异常要返回,不要抛。 工具方法里捕获异常后返回语义化错误信息,大模型收到错误会自己尝试修复参数。抛 NullPointerException?它直接蒙了。
记忆要管理,不要放任。MessageWindowChatMemory 控制上下文窗口大小。正式环境必须接 Redis,不然一重启全丢了。
安全要兜底。 发邮件这种高风险操作,加个 dryRun 参数。默认只生成草稿,人工确认再发。别嫌麻烦。
04. 避坑清单
最后这几条,都是真金白银换的。
① 异常别抛,要返回
// 大模型看到这行字,傻了throw new RuntimeException("参数错误");// 大模型能自己纠正return "参数格式不对,系统要求YYYY-MM-DD,再试一次";
② 大结果集别直接塞给 LLM查出来两万条记录,全塞上下文?模型直接失忆。存缓存,给摘要加指针就行。
③ 多实例部署必须用共享记忆InMemoryChatMemoryRepository 是单机玩具。生产环境 Redis 或 PostgreSQL,以 userId+sessionId 做 Key。
④ JSON 输出不稳定?上两道锁框架层开 Structured Output,底层加正则清洗去 Markdown 标记。基本不崩。
⑤ Token 成本要归因到业务Listener 回调里把 Token 消耗和业务请求绑定。不然月底看账单…根本不知道钱花哪了。
说到这,我想起开头那个朋友。后来他那个系统用 Java 重写了,上线两周,稳了。
但他问我一句话,我没答上来:
「你说,如果当初直接上 Java,是不是能省这两周?」
两周。在创业公司,两周能做好多事。
这个问题我没有标准答案。Python 快速验证、Java 生产兜底,听起来很合理对吧?但真实世界里,没那么多「先这样再那样」的机会。资源就这么多,团队就这些人。
也许最好的策略不是「先 Python 再 Java」,而是从一开始就搞清楚:你到底是验证一个想法,还是交付一个产品。
这是两件事。选错了,后面全是坑。
评论区说说你的情况。你现在在做 AI Agent 吗?用的什么语言?踩过什么坑?说不定你的经验能帮到别人。

延伸阅读:
-
• Spring AI 官方文档 – ChatClient[1]:Spring AI 的核心 API,上手必看 -
• LangChain4j – AiServices 教程[2]:接口即 Agent,这个思路值得每个 Java 开发者了解 -
• Java 虚拟线程基准测试 – InfoQ[3]:虚拟线程快多少,数据说话——Open Liberty 的详细评测 -
• AgentScope 项目主页[4]:国产分布式 Agent 框架,A2A 协议有点东西 -
• 相关标签: #Java开发 #AIAgent #SpringAI #LangChain4j #技术选型
引用链接
[1] Spring AI 官方文档 – ChatClient: https://docs.spring.io/spring-ai/reference/api/chatclient.html[2] LangChain4j – AiServices 教程: https://docs.langchain4j.dev/tutorials/ai-services/[3] Java 虚拟线程基准测试 – InfoQ: https://www.infoq.com/articles/java-virtual-threads-a-case-study/[4] AgentScope 项目主页: https://github.com/modelscope/agentscope
夜雨聆风