惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Stack Overflow Blog
Stack Overflow Blog
Recent Announcements
Recent Announcements
Microsoft Security Blog
Microsoft Security Blog
L
LINUX DO - 最新话题
P
Privacy & Cybersecurity Law Blog
Google DeepMind News
Google DeepMind News
Security Archives - TechRepublic
Security Archives - TechRepublic
云风的 BLOG
云风的 BLOG
酷 壳 – CoolShell
酷 壳 – CoolShell
博客园 - Franky
PCI Perspectives
PCI Perspectives
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
TaoSecurity Blog
TaoSecurity Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Attack and Defense Labs
Attack and Defense Labs
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
P
Proofpoint News Feed
小众软件
小众软件
A
Arctic Wolf
C
Cybersecurity and Infrastructure Security Agency CISA
F
Fortinet All Blogs
T
Threatpost
Security Latest
Security Latest
V
Vulnerabilities – Threatpost
B
Blog RSS Feed
MongoDB | Blog
MongoDB | Blog
WordPress大学
WordPress大学
Forbes - Security
Forbes - Security
H
Hackread – Cybersecurity News, Data Breaches, AI and More
C
CERT Recently Published Vulnerability Notes
AI
AI
博客园 - 三生石上(FineUI控件)
T
Threat Research - Cisco Blogs
Recent Commits to openclaw:main
Recent Commits to openclaw:main
S
Schneier on Security
I
Intezer
The GitHub Blog
The GitHub Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
V
V2EX
aimingoo的专栏
aimingoo的专栏
量子位
NISL@THU
NISL@THU
N
News and Events Feed by Topic
O
OpenAI News
Microsoft Azure Blog
Microsoft Azure Blog
C
Check Point Blog
Schneier on Security
Schneier on Security
S
Secure Thoughts
The Cloudflare Blog
J
Java Code Geeks

InfoQ - 促进软件开发领域知识与创新的传播

Meta 收购 Manus 这事儿泡汤了 5.5万 Star 开源项目 Ghostty 被迫出走,GitHub 正在终结一代技术人的乌托邦 Slack 长时运行多智能体系统的上下文管理方案 从 T+1 到分钟级:金城银行基于 Apache Doris 构建高可靠、强一致的实时数据平台 谷歌云推出 Agents CLI,简化 AI 智能体开发全流程 Claude官方击穿高薪、高学历的安全防线!Anthropic点名10大高危职业,但有群人暂时稳了 亚马逊云科技终止 WorkMail 服务,并将 App Runner 转入维护模式 OPPO小布记忆:全模态碎片化内容的理解与智能整理实践|AICon上海 模力工场038周AI应用周榜:工具在消失,工作流在出现 Akamai CEO Tom Leighton:Agent 时代来临,云基础设施正从“中心化”转向“分布式边缘” 日均数百亿入库背后:从“人肉调度”到K8s弹性架构,度小满金融基于OceanBase重构入库架构实践 百度文库网盘发布GenFlow 4.0:月活用户超1亿,要把网盘变成全端AI工作台 Altman 投的 Agent 终端 Warp 开源了!斩获3.5万star 哪些客户需要拒, 敢让龙虾决定吗?_AI&大模型_InfoQ 中文站_InfoQ精选视频 从开发到生产:为什么越来越多的机器学习团队纷纷迁移到 Snowflake | BUILD 2025_AI&大模型_王玮_InfoQ精选视频 探索多智能体工作流:LangGraph Snowflake Cortex AI | BUILD 2025_AI&大模型_王玮_InfoQ精选视频 腾讯云分布式缓存数据库:AI Agent - 从提示词工程到 Harness 工程 | 腾讯云数据库 DBTalk_腾讯_凌敏_InfoQ精选视频 基于 Streamlit 为 CSV 数据构建分析智能体 | BUILD 2025_AI&大模型_王玮_InfoQ精选视频 AI 智能体:告别文档缺漏 | BUILD 2025_AI&大模型_王玮_InfoQ精选视频 构建 AI 驱动的数据管道:深度探讨 Snowflake Openflow 与非结构化数据 | BUILD 2025_AI&大模型_王玮_InfoQ精选视频 云端太贵、本地不够聪明,英特尔押注“端云混合AI”:智能体PC会替人完成工作 不到10%的存储投入,可能拖垮90%的GPU投资!IBM把AI Agent塞进存储系统,算清企业最容易忽略的一笔账 Snowpark 上手实战 | BUILD 2025_大数据_王玮_InfoQ精选视频 ClickHouse + Langfuse,构建 Agent 可观测基石 腾讯云分布式缓存数据库:Cluster Proxy 共享连接架构深度解析 | 腾讯云数据库 DBTalk_腾讯_凌敏_InfoQ精选视频 AI 写代码太烧钱了:Copilot、Claude 一起涨价,不如把程序员请回来? 英特尔发布至强600系列工作站处理器与锐炫Pro B70 GPU,全新AI工作站来了 腾讯云分布式缓存数据库:从 Redis 到 Valkey - 开源社区如何快速创新 | 腾讯云数据库 DBTalk_腾讯_凌敏_InfoQ精选视频 印奇这次要“从0重做”智驾模型!首谈阶跃和千里双公司布局:中国AI商业闭环要靠车跑出来 从Cursor返聘归来,90后华裔女高管带Claude开启日更模式:token成本比工程师工资低多了! 从 Coding 到 Agent:QCon 北京 2026 全景复盘,优秀出品人 & 明星讲师名单揭晓 全链路支撑大模型国产化“Day 0适配”,商汤大装置构建全栈能力底座 凌晨,OpenAI 与亚马逊云科技史上最大联合发布来了 HashiCorp Vault 2.0 发布:引入新身份联邦机制,迈入 IBM 生命周期体系 Yelp 实现超 1,000 个 Cassandra 节点零停机升级 写了 17 年开源代码,我为什么认为 Coding Agents 堆功能是在瞎折腾? 基于 Apache Camel 编排智能体与多模态 AI 管道 面向智能体与人类用户的AI记忆系统:架构设计与核心场景实践|AICon上海 Anthropic 推出 Managed Agents,简化 AI 代理部署流程 阿里HappyHorse开启灰测,720P视频生成低至0.44元/秒 讯飞联合清华团队押注量子AI:不看营收、不设KPI,一群“无人区”科学家,抢夺下代AI算力入口 小米万亿模型全面开源:MIT 协议、1M 上下文,但还是打不过 DeepSeek Cortex Code 入门指南:面向数据工程师的实践路径 | 技术实践 openJiuwen社区首发Team Skills,定义Coordination Engineering新范式 用 Snowflake Cortex Agents 释放结构化数据的最大价值 | 技术实践 Grafana 利用 Kafka 对 Loki 进行了架构重构,并发布了一款命令行工具,旨在将可观测性引入编码代理 ClickHouse重构全文索引:对象存储上跑出高性能 Full-Text Search 可观测性和遥测技术如何提升软件工程实践 Dropbox 与 GitHub 合作,将单体库大小从 87GB 缩减至 20GB Agent 的下一站:基于长期记忆系统 EverOS 的自我演进|AICon上海 同一赛道,四种收费:Agent 控制层(Harness)开始分裂 Cloudflare Sandboxes 正式发布,为 AI 代理提供持久化隔离环境 Agent 的“记忆断片”困局,该怎么破?_AI&大模型_AICon 全球人工智能开发与应用大会_InfoQ精选视频 数据分析师如何快速建立在 AI 时代最值钱的能力:一份可落地的行动路线图 摩尔线程最新财报:研发占比超86%,万卡级大规模智算集群落地 当云区域失效:地缘动荡环境下的高可用重构 Slack 重构通知系统,设置参与度提升 5 倍 智能体工程的隐性技术债务 “我把所有模型都换成了DeepSeek V4”:月账单将降 90%,效果还更好 阿里云智能集团高级技术专家刘少伟已确认出席AICon上海站,并分享如何构建企业 Agent 的自动化行动架构 构建生产就绪的 tRPC API:Apollo Federation 的 TypeScript 替代方案 Anthropic推出面向Claude Code的基于智能体的代码审查功能 北京车展直击:斑马智能甩出车载Agent短剧,比亚迪率先落地,AI让智能座舱又热起来了 Snowflake 作为智能体运行时:从静态管道迈向自主数据系统 | 技术实践 Snowflake 上的本体体系:基于 Cortex Code 能力实现从架构到部署 | 技术实践 Cloudflare 公布 MCP 架构方案,应对企业面临的安全与治理风险 复杂的项目管理怎么做到「AI 友好」?飞书项目用「开放」给出答案 Snowflake Cortex Code 的规范驱动开发:将 SDLC 方法论引入 AI 辅助工作流 | 技术实践 Copilot 不让注册了:从“随便用”到“全面限”,agent 把原有订价模型顶穿了 当互联网用AI卷效率时,这家公司先问了一连串“能不能” Meta 开始记录员工每一次点击:AI 要接管工作,先监控会工作的人 Meta“Token榜”逼疯打工人,一夜烧掉公司几万刀!AI时代Token焦虑越来越离谱 智源FlagOS完成DeepSeek-V4-Flash在八款芯片Day0适配,实现三重技术突破 DeepSeek V4 重磅开源!首次打通华为Ascend,也没丢掉英伟达,百万上下文夺回国产模型话语权 李志飞的“新实验”:当超级个体撞上真实组织 GPT-5.5 登顶时刻,Anthropic 亲口承认 Claude 变笨了!网友群嘲:太敷衍 那些没空写的小需求,龙虾真能做吗?_AI&大模型_InfoQ 中文站_InfoQ精选视频 从 Pandas 到生产:使用任意 IDE 进行可扩展的 ML 数据管道与分布式处理 | BUILD 2025_AI&大模型_王玮_InfoQ精选视频 pnpm 11 候选版本发布,带来 ESM 分发、供应链默认设置以及新的存储格式 银行业PDF表格提取方案重构:基于Java的分层方案 GPT-5.5 赢了 Opus 4.7 和 Mythos?奥特曼晒黄仁勋内部信:英伟达全员用上 Codex! Cloudflare 推出 Think:一款面向 AI 代理的持久化运行时 1850亿美元天价支出、75%代码由AI生成!谷歌正式宣告:全面转向智能体工作流 xAI落后太多,马斯克“开大”重金求购Cursor,100亿美金“分手费”都敢签! Pulumi 新增对 Bun 运行时的全面支持 姚顺雨腾讯模型首秀!不卷参数只做 “听话打工人”,Hy3 preview登场 | 附实测 老板让你“忽悠”投资人,你敢发给龙虾吗?_AI&大模型_InfoQ 中文站_InfoQ精选视频 Gemini CLI 引入子代理机制,实现任务委派与并行代理工作流 清华系团队星工聚将完成数千万天使轮融资,轮式机器人拿下头部制造企业亿级大单 Pretext.js 绕过 DOM 布局重排,实现 120 FPS 的高级交互体验 靠“AI 云”爆红的 Vercel,栽在一个第三方AI工具手里!IPO前夕遭黑,200万美元赎金谈崩? 高能研讨会|端侧 AI 正在重写实时感知效率上限_AI&大模型_王玮_InfoQ精选视频 2050大会看这篇就够了|报名、交通食宿指引大全 Java 近期资讯:OpenJDK JEP、Jakarta EE 12、Spring Framework、Micrometer、Camel、JBang 金融智能的架构编排:基于 Snowflake Cortex Agents 实现结构化与非结构化数据统一分析 | 技术实践 在AK大神爆火的任务里,摸清国产AI真实水平 百灵Ling-2.6-flash 正式发布:高 Token 效率,以 1/10 消耗实现 SOTA 级 Agent 能力 当 PM 懂AI,当技术懂产品:AI 时代产品力的双向进化|PM x AI产品力领航者大会即将开幕 为 AI 智能体设计记忆机制:揭秘 LinkedIn 的认知记忆智能体 获奖名单公布|2026主题征文第一期|分享你最有价值的龙虾场景与核心 Skill_热门活动_InfoQ写作社区官方_InfoQ写作社区
Spring 创始人重回一线做 AI 框架,却说:这是人类亲自选择的最后一代框架
傅宇琪Tina · 2026-06-04 · via InfoQ - 促进软件开发领域知识与创新的传播

Rod Johnson 又回到了一线。

他是 Spring 的创造者,曾经几乎重新定义了企业 Java 应用该怎么写。二十多年后,他重新创业,做了一个面向企业 AI Agent 的开源框架 Embabel,试图把 LLM 放进真实的业务系统里,让它不只是会调用工具,而是能在可控、可解释、可审计的流程里工作。

有意思的是,这一次他做的仍然是框架,但他对“框架”的未来并不乐观,至少不再是过去那种乐观。在他看来,模型还会继续变强,工具也会越来越多地替开发者做选择。Embabel 会不会被更强的模型追上?企业还需不需要这样一层 harness?未来的框架到底是由开发者挑选,还是由 AI 工具自动决定?这些问题,都绕不开他在访谈里说出的那句话:这可能是最后一波由人类亲自选择的框架。

这句话放在别人嘴里,可能只是又一次 AI 时代的夸张判断。但从 Spring 创始人口中说出来,意味就不一样了。因为 Rod Johnson 亲手参与过框架时代的兴起,也见过一个框架如何变成企业软件开发的基础设施。现在,他回到战场,却认为选择权正在转移:开发者未必会消失,但开发者亲自挑框架、搭技术栈、决定系统骨架的时代,可能正在进入尾声。

本文基于该播客视频整理,经 InfoQ 编辑。

核心观点如下:

  • 如果我要用 TensorFlow 做模型训练、微调、某些数据处理和摄入,我当然会用 Python。但 GenAI 应用层赋能这件事,更适合在应用原本的语言里完成,如果应用是用 Java 写的,那就在 Java 里完成。

  • 一旦你进入复杂的应用程序,如果你不保持那种架构上的监督,你很快就会陷入一团乱麻。你的 Agent 会愉快地添加新功能,但每添加一个新功能,设计就会退化,代码就会变得非常糟糕。

  • 开发者不应该花大量时间在编写代码上,因为你可以通过专注于你独特增加价值的地方来获得更大的杠杆。

  • 每个开发者原则上都应该每隔一两年学一门新语言,因为它真的会改变你的思维方式。

  • 这可能已经是“最后一代由人类主动选择的框架”了。以后越来越多的技术选型,都会由我们的工具替我们完成。

Spring 创始人回归一线创业

Simon:我翻你的履历时发现,你在创建 Spring 之前,拥有一个关于 19 世纪巴黎钢琴音乐的博士学位。

Rod:是的,我的第一个学位是音乐和计算机科学双专业,当时完全没办法决定往哪个方向走。后来我拿到了澳大利亚的研究奖学金去读音乐博士,还在悉尼音乐学院教过两年音乐史。然而,写代码的冲动一直没停过。90 年代中期我还写过共享软件,真有人寄支票过来。

后来我清醒地认识到,要是继续待在音乐学术界,我大概一辈子都在悉尼买不起房。于是我做了一个决定:这两件事里,一个当爱好,一个当职业——而我当时正好搞反了。不过接下来有十年我几乎没碰过钢琴,因为职业生涯实在太忙了。

Simon:所以这并非什么奇怪的弯路或别的什么,只是碰巧你很有创造力,无论是写代码还是音乐,你都很享受这两者。

Rod:从 80 年代中期第一次写代码到现在,我差不多从未中断过编程,因为我就爱这件事。即便现在绝大部分代码是由 AI Coding Agent 替我写的,我仍然能获得一模一样的兴奋感,因为掌控权还在我手里,我还在创造和塑造东西。哪怕不再亲手敲出每一行,只要结果是相同的,这对我而言同样令人满足。

Simon:在 SpringSource 被收购后,你做了很多年董事会和投资的事情,然后创办了 Embabel,是什么让你觉得“就是现在,这个时机到了”?

Rod:我认为是因为行业正处在一个巨大的转折点上。当 GPT‑3 和后来的 ChatGPT 突然变得真正实用、不再重复自己或陷入奇怪的死胡同时,我立刻意识到,怎么把这项技术真正用来解决企业问题,是很难的问题。其实在这之前两年,出于个人兴趣,我已经写了不少 TensorFlow 代码,和底层 AI 技术打了很多交道这自然而然地演化成了创建一个框架来帮助解决这些问题的想法。

Simon:说到企业,现在很多团队被要求抛下 Java,用 Python 重写一切。你公开讲过这是错误的,甚至说过“这是 Python 在 AI 领域主导的最后一年”,为什么?

Rod:你要解决一个业务问题,就必须考虑这个问题本身的“邻接性(Adjacency)”。你在和什么打交道?你大概率在和数据库、企业服务、现有代码库打交道。同时,你还要处理一个新东西:LLM。可 LLM 并不在你那个 Python 进程里运行——宇宙毁灭之前,Python 都没法自己执行推理。LLM 只是一个非常简单的 HTTP 调用,所以我一直很困惑,为什么人们会认为某门语言在发起一个极其简单的 HTTP 调用时会有天然优势。

事实上,大家已经开始逐渐意识到这一点了。OpenClaw 就不是用 Python 写的,Peter Steinberger 用的是他偏爱的语言。对大量企业应用而言,它们很明显是用 Java 写的,关键的邻接性就在于已有业务逻辑、已有企业服务。那正确的做法很显然,就是从你的 Java 栈里发起一个简单的 HTTP 调用。

我认为人们产生这种混淆的根本原因,是没有把“数据科学”和“企业 AI 应用”区分开,它们是两件完全不同的事。在 Embabel 之前我写了大量 Python,两年前我的 Python 甚至比 Java 流利得多。如果我要用 TensorFlow 做模型训练、微调、某些数据处理和摄入,我当然会用 Python。但 GenAI 应用层赋能这件事,更适合在应用原本的语言里完成,如果应用是用 Java 写的,那就在 Java 里完成。

Simon:Embable 是用 Kotlin 写的,对吧?

Rod:Embabel 核心几乎全部是用 Kotlin 写的。但我们的大多数示例是 Java。我们投入了大量精力来确保对 Java 用户来说,它是完全无缝的 —— 正如你预期的那样,我们绝大多数用户群都在用 Java。你不会看到 companion object、`.kt` 文件,不会看到任何奇怪的东西。它就像非常优雅、流畅的 Java。所以当我在核心框架上工作时,我用 Kotlin;当我在示例应用上工作时,我用 Java。老实说,Java 风格的 API 非常棒,即使在 Kotlin 里使用这个框架时,它和其他语言的体验也差不多。

Simon:而且它们之间的集成本来就很无缝,你可以直接从 Kotlin 跳到 Java。

Rod:大概十三年前,我大量使用过 Scala。我很喜欢 Scala 这门语言,但事实是它与 Java 的集成很痛苦。每次你处理一个集合,那都是折磨。而 Kotlin 的创造者在 Java 互操作性方面做得非常出色,他们没有引入 Scala 曾有的那些问题,破坏性变更、缺乏二进制兼容性等等。所以,是的,我觉得 Kotlin 是一门非常好用的语言。

不过,我也认为指出 Java 已经改进很多这件事很重要,我觉得人们喜欢拿 Java 当稻草人来攻击很烦人。很多人在假装 Java 没有进化,而 Java 实际上已经进化了很多。

Coding Agent 正在毁掉你的代码库

Simon:你之前谈到 AI 基本上是被当作一个断开的层硬塞进去的,而不是更深入地集成到现有系统中,结果这导致了一些失败案例。你认为真正的企业 AI 失败案例是什么样的?

Rod:我认为最大的问题就出在,当高层下达“AI 一切”的指令,团队却在没有真正业务案例、没有确认 AI 是否合适的情况下,盲目开展 AI 项目。一个主要的反模式就是“我们必须用更多 AI”这种念头,却从来不去问一句:为什么要用?用来干什么?虽然我非常热爱并且着迷于 AI,但如果能不用 LLM 就完成一件事,那你当然应该不用 LLM,这样更便宜、更确定、更快。

所以组织首先要做的,是思考“我们怎么从这儿走到那儿去”。举个例子,我们在澳大利亚的一个客户,他们一开始识别出一类小问题:网站上有某张特定表单,客户填写完后需要人工审核才能继续。95% 的情况其实非常简单,虽然用正则表达式处理起来稍微麻烦了点,但本质上很简单。于是他们把这个摩擦点消除掉了,在 95% 的场景里让客户即时推进,不再需要等人工处理。我觉得这是非常棒的起步案例:先在小事上拿到结果,慢慢建立起信任。

另外,对于“异构技术栈(Alien Stack)”问题,它会在两个方向上造成伤害。第一,技术上让一切都变难;第二,它往往还会把战略权交到错误的人手里那些根本不懂核心业务、可能从来没见过任何核心业务应用的人,却在主导战略。当你要赋能这些应用的时候,这条路完全走不通。

去年我和一家澳大利亚大公司的首席 AI 架构师聊过,他是一名 Python 开发者。他礼貌地听完了我的介绍,却没什么兴趣。通话结束时,他试图表现得友善一点,说:“我敢肯定我们公司什么地方有 Java,我回去问问看。”我从来没在那家公司工作过,但作为业内人士我太清楚了,那家公司大约 70% 的代码是 Java 写的,剩下的是 .NET,而且他们正逐步淘汰 .NET。这个人入职将近一年了,却从来没想过要去问一句:“顺便问一下,我们的软件是用什么语言写的?”对他来说,这似乎根本不重要。

Simon:现在有一种越来越普遍的现象,我们作为开发者,与实际编写的代码实现之间出现了巨大的脱节。因为我们对 AI 过度依赖或授权,让 AI 做了太多决策,把太多东西都外包出去了。很多知识实际上在 AI 那边,而我们却被抽象掉了。你认为这个问题有多严重?

Rod:我认为开发者需要掌握的一项核心技能,就是以这种新方式工作,同时保留那些真正重要的控制权。确实可以用 Vibe Coding 来做一些事情,比如某些类型的 UI 应用,它们本来就是一次性的,Agent 在这方面非常非常擅长。但你无法用 Vibe Coding 来编写严肃的软件。

我是一个 Coding Agent 的积极用户,我可能最多只写 5% 的代码,也许更少,但我牢牢掌握着控制权。我发现,从设计的角度来看,Agent 出错的时候比正确的时候多。

我们仍然需要理解架构、清楚正在发生什么、并且不要过于信任。因为一旦你进入复杂的应用程序,如果你不保持那种架构上的监督,你很快就会陷入一团乱麻。你的 Agent 会愉快地添加新功能,但每添加一个新功能,设计就会退化,代码就会变得非常糟糕。

Simon:你提到你只写 5%的代码,其余是 AI 生成的。你这样做是有意为之吗?是因为你不想写更多,因为你想对写出来的东西有更多控制权?

Rod:在开源项目里,我手写的比例更高一些,可能会更保守。但在我们的一些内部应用中,AI 生成的比例接近 95%。要是你读那些代码,你会觉得那是我写的,设计风格非常清晰。我会坐在那里看 diff、看输出,然后经常停下来纠正它:“不对,你把这个硬编码了,这里应该是一个策略,提取出来。”

我相信这种模式有可能产生比纯手工或者纯靠 Coding Agent 更好的结果。我用 Coding Agent 写代码的速度比我手动快得多,而且质量也更好。但如果反过来,我把一切完全丢给 Coding Agent,我深信质量会大幅下降,最终连速度也会降下来。

Embabel 的核心:来自一个游戏 NPC 规划算法

Simon:我们来谈谈 Embabel 里面的核心组件“规划器(planner)”。这是一个叫 GOAP (Goal-Oriented-Action-plann)的寻)寻路算法,最早是为游戏里的 NPC 设计的吧?关键点是,它是确定性的。而其他框架比如 LangChain、Crew.ai,则更多是由 LLM 来决定下一步做什么、怎么规划。为什么你会从游戏 NPC 领域里挑出这个算法?

Rod:我最开始考虑的确实是最显而易见的方法——状态机(state machine)。平心而论,LangGraph 就是确定性的,你提前定义好状态机。所以我也一度用过那种办法。不过我们先退一步,谈谈为什么要做规划。

当然,你可以直接把一堆工具扔给模型,让一个 Agent 循环来全权处理一切,在某些场景下这确实合理。但对于自动化业务流程这类需要一致性和可预测性的场合,这远远不够,因为你压根不知道 LLM 会以什么顺序调用你给它的工具,也不知道它会传什么参数给那些工具。

所以我们的想法是,让用户把流程拆成多个步骤。这些步骤可能是调用一个或多个 LLM,也可能是纯代码步骤。在这一层面上,LangGraph、Crew.ai、Microsoft Semantic Kernel 做的都是类似的事——把大问题切分成小步骤。这也意味着,如果你在某一步中使用 LLM,可以为不同需求使用不同模型。比如你可以在自己的防火墙后面使用本地 LLM 来处理那些足够小、且高度敏感的任务,从而永远不让客户数据流出企业边界,这里面有大量好处。

但问题回到了:怎么规划这些步骤,怎么决定执行顺序?你可以用状态机,但我发现,当我在做类似 LangGraph 的东西时,修改状态机,比如增加更多状态和转换,非常麻烦,你必须重新连线来扩展它。其次,状态转换和每个动作状态所需的类型,通常都是正交的,这会在类型系统上制造麻烦。

GOAP 规划方式有两个很不一样的点。第一,它是动态的,规划发生在运行时。第二,它与类型系统完全集成。我们允许用户创建自定义条件,但动作的排序通常由 Java 方法的参数类型和返回类型决定,这意味着一个动作永远不会在缺少所需参数时被调用。

GOAP 本质上是一个 A* 算法。我们识别出目标,然后查看从当前世界状态出发,哪些步骤可以通向目标。目标有前置条件,世界状态中必须满足某些条件。动作也有前置条件和它承诺的后置条件。前置条件是绝对硬性的,除非条件被满足,否则你不能声明目标已达成,也不能调用某个动作,而后置条件则是动作承诺会产生的副作用。

规划器从当前世界状态出发,找到一条通往目标的路径。它也可能告诉你“不存在可行动路径”,这本身就是一个很有价值的信息。然后它执行第一个动作,再重新规划,在执行每个动作之后,查看世界状态,重新评估怎么到达目标。大多数情况下,快乐路径会照常运作,动作承诺的后置条件得到满足,规划器确认一下,然后迈进下一步。

Simon:这一切都是自动化的?

Rod:完全自动化。通常 Java 开发者不需要了解规划器的内部细节,他们只需要定义“动作方法”来提供输入,用注解标记 Java 方法,方法的参数和返回类型就给规划器提供了链式调用的信息。在某些情况下,你还可以定义自定义条件来进一步控制工作流。这意味着可能存在多条路径能到达同一个目标,而规划器可以选择成本最低的那条路径,因为你可以给每个动作分配成本。成本甚至可以是动态的,如果某个动作需要调用一个负载很高的系统,你就可以将其反映为一个动态成本值,这样一来,规划器也许就会自动选择另一条路线。

Simon:基于当前世界状态在运行时做动态决策,这非常有意思。另一个好处是,因为它是确定性的,当被问到“为什么会做出这个决定”时,你们能提供非确定性规划器无法给到的诊断信息?

Rod:我们可以完整展示规划的整个路径,以及我们观察到的世界状态,是如何导致我们制定出那份计划的。规划器和整个 Embabel 会发出大量事件,你可以编写监听器来持久化这些信息,或者把它们用于审计日志。所以你完全可以解释它为什么做了某件事,并且确保它每次都做同样的事。

当然,一旦进入动作步骤内部,如果你调用了 LLM,那部分就不会是完全确定性的,但这也让你能够“适度”地调用 LLM。如果你像聊天机器人那样,用长达三页纸的提示词和 30 个工具来工作,你永远不可能获得完全的可预测性。而如果你用一段小提示词加上三个工具去完成一件事,可预测性就会非常高。虽然不可能 100% 确定,但你会发现花在提示工程上的时间会大幅减少。所以整体上,系统会变得可解释得多,也确定和可预测得多。

为什么对 MCP 持怀疑态度

Simon:每个人似乎都把 MCP 当作灵丹妙药,好像它能解决 Agent 的所有问题。你认为在这个领域,大多数开发者还没有看到的差距是什么?

Rod:我认为 MCP 在赋能整个生态系统方面发挥了极其重要的作用,它确实是一个催化剂,让更多的人了解到你可以用工具实现什么。然而,我出于几个原因对 MCP 持怀疑态度。

首先,如果你在做“用 AI 赋能企业系统”这件事,为什么要通过 MCP 来运行?你可以用 Embabel、Spring AI 或 LangChain4J,任何框架都可以轻松地将一个 Java 方法暴露为工具。所以你必须问一个问题:如果做起来这么容易,为什么还要多此一举?特别是当你可以在领域对象上暴露工具时,你先通过仓库调用检索到了正确的领域对象,然后暴露这个对象上的方法,这是 MCP 不那么容易做到的事。所以,很多时候,你在暴露任何工具时,第一个想法应该是:“我能用我的技术栈直接暴露它。”“我为什么不直接暴露一个 Java 方法或 Python 函数呢?”完全可以做到。

其次,MCP 的卖点是“一个专门为 Agent 设计的 API 规范”。但如果它是 API 规范,我们已经有了 OpenAPI、Swagger、GraphQL,为什么还需要一个新的?MCP 的论点是"因为它是专门为 Agent 设计的"。但我最近开始得出一个结论:对于一个特定 Agent 来说,唯一完美适合的东西,很可能就是这个 Agent 独有的。比如,你可以有一个 MCP 服务器去暴露服务,但如果已经存在一个 OpenAPI 规范,你也可以连接到那个规范,然后根据你特定 Agent 循环的需求来塑造你自己的工具。

我认为 MCP 对推动行业进步有巨大贡献,但它不是那种一刀切的解决方案。在很多场景下,直接使用现有的 API 规范更有意义,而永远放在首位的方案应该是:从你当前的技术栈里直接暴露逻辑。

Simon:我记得 Karpathy 发过一条推文,大意是模型正在跑在基于模型构建出来的产品前面。现在你在 Embabel 构建的是编排层。这是否意味着,你们其实已经落后于模型了?

Rod:这是一个有意思的问题。当然,如果你看我们现在如何构建软件,coding agent 的规划能力提升得比我原本预期要明显得多。大概在去年 11 月底、12 月那段时间,确实出现过一次非常剧烈的跃迁。我认为模型肯定在变得更好,但我也认为,很多根本问题仍然存在。如果你在自动化业务流程,那么把规划从模型的控制之外移出来,转而使用某种确定性方法,我认为这仍然有价值。可解释性依然很重要。所以我确实认为,即使模型继续进步,模型之上的框架、agent harness、各种框架仍然非常重要。

一个很好的例子是 Claude Code。当然,Sonnet 4.6 比之前的模型强得多。但 Claude Code 本身也强得多。如果你把今天的 Claude Code 和四五个月前的 Claude Code 相比,它的工作方式已经完全不同,而这种不同确实让它更有效。所以我其实并不认为模型变聪明和 harness 变聪明之间存在冲突。我认为我们需要在两个地方同时推进。

我认为你确实会看到一些模型“吃掉 harness”的场景,也就是在那些是否确定并不那么重要的地方。你可以直接给模型一堆工具,即使它有点不可预测也没关系。所以我确实认为,有一块空间里,模型会需要更少的外围基础设施。但我认为,那块空间与企业应用并没有特别大的关系。

AI 擅长批评,不擅长原创

Simon:今年一月,你提到你的 Claude Code 工作流程涉及很多设计对话:和 Claude Code 来回讨论、长时间的规划,然后才开始编码,结果往往比手写更好。但 Claude 并不理解某些事情,比如 companion objects。所以当你用 Claude Code 构建 Embabel 而 Claude 不完全理解你架构的某些部分时,那种感觉如何?

Rod:我认为它工作得很好,因为我完全理解架构,并且我经常纠正它。我确实想知道,如果开发者越来越多地选择“不理解架构”那条简单的路,会发生什么。我处于一个非常有利的位置,我完全理解代码库中的架构,我非常了解 Kotlin 这门语言,我们构建在 Spring 之上,我对 Spring 也很了解。我实际上非常了解技术栈的每一个部分,这使我能够有效地掌控局面。我个人会非常担心那些不理解这些的人,保持控制权非常重要。我认为开发者不应该花大量时间在编写代码上,因为你可以通过专注于你独特增加价值的地方来获得更大的杠杆。

Simon:AI 有没有让你感到惊讶的时候,比如给过一个你没想到的设计或架构建议,让你转向了完全不同的方向?

Rod:不经常。然而,有一件事一直很有用,那就是来回的讨论。确实有很多次它想到了我没想到的问题。比如我们在讨论一个提议的变更时,它指出了我没想到的一点。它更擅长批评,而不是提出原创想法。

总的来说,我非常满意,但有些时候我也会感到沮丧。过去几天,我试图为一个内部产品构建一套相当复杂的测试基础设施,在测试容器里用真实 LLM 进行测试,伪造所有工具等等,而 Claude Code 表现得非常糟糕。我认为原因之一是它以前没见过这种场景,这可能是一种相当新的测试形式。

要让你的 Coding Agent 获得最大的自主性,你需要对测试非常执着。而我这次碰到的,既是它见过的更极端的测试量,而且某些类型的测试可能也是它以前没见过的。尽管有明确的指示,它似乎还是出奇地挣扎。

Simon:你有没有尝试过用技能和上下文来引导它,试图让它提供更接近你想要的建议?

Rod:我试过用 Skills 和 Claude.md 来配置 Coding Agent 的行为,但有点不幸的是,当上下文越变越大,Coding Agent 就会开始忘东西。有个特别奇怪的现象:它老是想在代码体里写全限定名,可我非常讨厌这个,我更喜欢用 import。我已经把这个偏好写进了 claude.md 配置文件里,但大概有 50% 的时间它还是照忘不误。

Simon:就算那是 Agent 必须读取的强制性指令,它也做不到渐进式学习。

Rod:对,注意力就是会衰减。

语言之争

Simon:我记得你曾经说 TypeScript 是当今最重要的语言,因为它能让一个普通 JavaScript 开发者的水平翻倍。既然你认为 TypeScript 比 Java 更重要,那你怎么同时做到既坚持在 JVM 上构建,又相信 TypeScript 是最重要的语言

Rod:TypeScript 是门非常聪明的语言。有意思的是,你看曾经静态类型与动态类型语言的那条路线,现在某种程度上正在趋同。现代 Python 大量使用类型提示,Python 的类型系统也相当不错了;TypeScript 显然给 JavaScript 加上了一层类型。

TypeScript 是一门优美的语言,它的确非常重要。但我还会不会说它依然是最重要的?这得看应用的类型。如果我从零开始写很多类型的应用,我很可能会用 TypeScript 去写服务端和 React。但你去看企业级应用,没多少是用 Node 写的,也不应该用 Node 去写。在 JVM 上,Java、Kotlin 会给你一堆对这个类别的应用极有价值的东西。TypeScript 再漂亮,在这件事上也帮不上什么忙。

所以我认为,第一,现代 Java 肯定比我当初说那些话的时候好得多;第二,Kotlin 是一门值得认真考虑的出色语言。Kotlin 和 TypeScript 大概旗鼓相当,我仍然会想念联合类型,我可以长篇大论地论证密封层级绝对不如联合类型好,但 Kotlin 同样有很多比 TypeScript 强的地方。TypeScript 的另一个问题是,尽管他们做得非常好,底层仍然有一层疯狂的东西,你偶尔就会撞见,而且没法掩盖。而 Kotlin 是一门现代化语言,它建立在更健壮、更可预测的基础之上。

Simon:你认为 AI 的进步会在五年内改变这些语言格局吗?有没有足够多的变化来颠覆这些既定事实?

Rod:我不知道我的观点是什么,我可以说服自己语言不重要,也可以说服自己语言很重要。

先说很多人想象的那个图景,以为训练语料库会让热门语言拥有天然优势,然后这种优势会被固化下来,这绝对不对。我使用 Coding Agent 的三种语言是 Java、Kotlin 和 Python,而毫无悬念,Coding Agent 做得最好的恰恰是 Kotlin,这完全超乎你的预想。

你想,Java 和 Python 都存在了很久,而且最近几年进化得都很快。你不应该写出 2019 年的 Java,当然也不应该写出 2019 年的 Python。训练数据太多了,你可以说“永远用值类型”“永远用增强 switch 语句”“Python 里永远用类型提示”,但正因为训练数据体量太大,你实际上是在对抗它。我倒不是说他俩不好,Java 和 Python 仍然非常好。

可 Kotlin 更好,这让我非常吃惊,因为 Kotlin 的语料库并不大。Kotlin 本身也没怎么进化,因为它从一开始就是一门现代语言。其次,早期用 Kotlin 的大概率是技术非常娴熟的人,因此没有那么多糟糕的 Kotlin 代码,不像 Java 或 Python 那样。

所以,我不认为热门语言会因为训练数据就被固化。LLM 对任何它们见过足够多的东西都极其擅长,而我们听说过的所有编程语言,它们都见过很多。但这就引出了另一个问题:既然如此,你干嘛不用完美的语言去写每一件事?就像我们之前说的,有些东西我绝对不会用 Python 写,而会用 Java 写。既然 LLM 在每一门语言里都是大师级别,为什么不挑最理想的语言来写每一个服务?用 Rust 写这个服务,用 Go 写那个。(但我不认为现在还有值得用 Go 写的东西了。

问题在于,这就像我们曾经看到过的微服务狂热——还有其他成本。你现在会引入极为庞大的维护成本,除非我们愿意完全信任我们的机器,但我不觉得我们该那样做,我不认为那是个好主意。

Simon:还有技能问题。光是技术栈的多样性,以及人们需要维护这些技术栈,就已经足够头疼了。还有安全,每引入一门新语言或一个新库,威胁面就成倍扩大,而且这种风险会跨语言蔓延。

Rod:至少就目前而言,我们选择语言和技术栈的根本性理由,可能不会改变太多。因为当你把它们投入生产、为它们背书的时候,那些最根本的东西并没有变。

开源生存法则

Simon:你之前提过,开源项目背后的公司需要从第一天起就有商业模式,这对 Embabel 来说是什么样的?

Rod:最可能的模式是开放核心。我认为开源的纯支持模式一直就非常困难,有了 Coding Agent 之后,还会难得多,所以我觉得会存在比框架层面更上一层的产品。我们目前的思路是,把框架作为一种竞争优势,去构建可能甚至不针对软件开发者的产品,而是针对更广泛的知识工作者。框架本身是 Apache 许可证,和 Spring 一样。我们欢迎社区贡献,我们有活跃的 Discord、GitHub 和问题跟踪器,欢迎任何感兴趣的人来贡献和加入社区。

Simon:Spring 前后经历了 VMware、Pivotal 再到如今 Broadcom 的收购。你觉得是什么让它挺过了这些收购?很多开源项目在被收购之后就枯萎甚至死亡了。

Rod:我觉得在 2009 年底那笔首次收购发生时,Spring 已经是一个庞然大物了,它已经是事实上的标准。早期的采用率和围绕它建立的社区,显然有着巨大的惯性。

但有帮助的一点是,有相当多技术娴熟的开发者被全职雇来开发 Spring。这意味着那些不那么令人兴奋的事情也会有人去修,因为这是某个人工作的一部分,不管他们感不感兴趣。我仍然坚信,开源确实能从背后的商业支持中受益。让 Spring 变得可靠的关键,它非常健壮,任何严重问题都会迅速被修复,部分正反映了我们不依赖志愿者。社区贡献当然很棒,但我认为背后的这种专业性至关重要,它给出了那种完整产品式的开发方法。

“这是人们选择的最后一波框架”

Simon:你认为 JVM 最被低估的东西是什么?Python 世界完全不知道自己错过了什么?

Rod:性能当然是其中一个方面。但更严肃的回答是:运行在它上面那些代码,业务逻辑、领域模型,对于理解关键业务,有着难以估量的价值。

Simon:关于 AI Agent,你有什么不受欢迎的观点吗?

Rod:我对 MCP 持有一种相对怀疑的态度。倒不是说我觉得 MCP 不好,而是我觉得现在大家已经把 MCP 当成了“万能锤子”,于是看什么都像钉子。

Simon:如果有 Java 开发者被老板命令“去学 Python,因为 AI 要用 Python”,你会给他什么建议?

Rod:我会让他去读读我的博客。我写了一系列文章,用完全相同的任务来对比 Python 和 Java 的实现——文件处理、API 调用、数据管道。结果非常清楚:Java 代码在性能、可读性和生态成熟度上完全不输 Python。你可以直接把其中一篇文章甩给你的老板,或者更好一点,自己亲手写一段。很多时候你会发现,Java 的代码竞争力其实一点不差。

Simon:如果是已经在线上生产环境跑着的项目,你会选 LangGraph 还是 Embabel?

Rod:Java 项目还是 Python 项目?如果是 Java 项目,那我肯定选 Embabel。否则你就是在往系统里硬塞一个 “Alien Stack”。现在 Embabel 已经到 0.3.5 了,离 API 稳定其实非常近。我会很惊讶如果从现在到 1.0 之间还有什么重大 breaking changes,估计再过四到六周就会到 1.0。

所以说实话,我不觉得现在采用 Embabel 是什么高风险的事。反倒是,如果我有一个 Java 项目,却要引入一整套完全不同的技术栈,再让它去和现有 Java business logic 对接,我会觉得这风险大得多。等你把这一大堆东西折腾完,Embabel 可能都已经 1.0 了,到时候你只会特别懊恼:“我当初到底为什么要这么搞。”

Simon:今天启动一个全新的企业项目,用 Kotlin 还是 Java?

Rod:这取决于团队规模。如果团队少于 20 人,我会认真考虑 Kotlin。如果团队更大,而且大家原本也不熟 Kotlin,那我可能还是会继续用 Java。

Simon:以前 Java 开发者转 Scala 的学习曲线其实挺陡的,现在 Java 转 Kotlin 还有那么难吗?

Rod:老实说,我不太确定。因为我接触 Kotlin 的时候,其实已经写了很多别的语言,尤其是 Python。我虽然也写过几个月 Java,但后来又回到了 Kotlin。所以我并不是一个“纯 Java 背景”转过去的人。不过我可以明确地说:Kotlin 绝对比 Scala 容易学,Kotlin 本身其实是一门相当容易上手的语言。

而且还有两点我一直很认同。第一,我觉得每个开发者原则上都应该每隔一两年学一门新语言,因为它真的会改变你的思维方式。第二,现在学习新语言的门槛已经低到前所未有,LLM 可以极快地帮助你掌握任何语言,所以整体门槛其实已经被大幅降低了,比如我从来没读过 Kotlin 的教程书。

Simon:你刚刚提到让 LLM 去批判代码,有时候相比让它“直接生成”,这种方式反而更值。我也觉得,尤其是在学习新语言的时候,让 LLM 给你解释“这里为什么这么写”“背后的机制是什么”,很多时候比直接说“帮我生成一段代码”更有效。否则你最后只能对着生成结果猜:“它为什么要这么写?”

Rod:尤其是对于有经验的开发者来说,更是这样。我学新语言的时候,经常会问 LLM:“这个语言里有没有某个特性的等价实现?”比如我会问:Python 里有没有类似 TypeScript type guard 的东西?如果你本身已经理解这些概念,那 LLM 特别擅长帮你把这些概念映射到另一门语言上。

Simon:你每天都会用、最喜欢的 AI 工具是什么?除了 Claude Code 之外。

Rod:大概率还是 Claude Desktop。主要是它能让我同时调用一堆工具做 competitive research,我很多事情都会用它来处理。

Simon:关于 Spring,有什么你后来觉得“当初做错了”的地方?如果重做一次,你会在 Embabel 里换一种方式吗?

Rod:有个挺小、但我觉得挺有趣的点。当年我一直想给 Spring retrofit 一套“基于事件的 logging 机制”,但那个时候已经太晚了,架构上不好再改。但在 Embabel 里,我们一开始就这么设计了。这样做的好处是:所有 event 都是完整的。你可以通过 SSH stream 出去,可以监听,可以订阅。而且更有意思的是,我们甚至可以修改你的“logging personality”,比如让你的日志全都用尤达大师的语气输出。

某种程度上,Embabel 的整体风格其实是建立在现代 Spring 的经验之上,只是加了一些在 Kotlin 里更容易实现的东西。比如我们基本不怎么用 builder pattern,因为 Kotlin 可以把这些东西写得更优雅,哪怕最后还是给 Java 用户使用也一样。

Simon:如果 Embabel 五年后不存在了,你觉得是什么杀了它?

Rod:我完全不知道五年后 Embabel 是否还会存在。五年后,人们还会亲手写应用吗?还是他们违背了我的建议,让机器完全接管了一切?我甚至会说:这可能已经是“最后一代由人类主动选择的框架”了。以后越来越多的技术选型,都会由我们的工具替我们完成。但说实话,我们正处在一个几乎独一无二的时代。别说五年,一两年后的预测都可能是错的。

访谈视频原链接:

https://www.youtube.com/watch?v=UcvxYltiS7E