有人用Java重写了OpenClaw——不是代码移植,是一场架构级的翻译
出事了——GitHub上多了一个Java版的OpenClaw
2026年3月。GitHub。一个叫 JavaClaw 的仓库悄然上线。
AGENTS.md 第一行写着:”JavaClaw – Java Edition of OpenClaw。”
OpenClaw。145,000颗星。25个即时通讯通道——WhatsApp、Telegram、Slack、Discord、Signal、iMessage、WeChat、QQ,你听过的即时通讯软件它全连上了。5,000个社区技能。语音唤醒。实时画布。macOS菜单栏App。iOS和Android节点。一个让AI Agent互相社交的网络。一个人工智能接单赚钱的赏金市场。
2026年最火的开源AI Agent。没有之一。
全部用 Node.js 和 TypeScript 写的。Java 开发者在旁边看了六个月——鼓掌,羡慕,然后回去写 Spring Boot。
现在,有人把它”翻译”成了 Java。不只是翻译。是推倒重来。第一版用 AI 辅助几天搭完——他们叫它 vibe code。CTO 看了十分钟,关掉 IDE,全部重写。两周后,27 次提交,3 个模块,一份让 Java 社区扬眉吐气的答卷。
在翻开这份”译本”之前,你得先知道原作讲了什么故事——以及为什么 Java 开发者以为自己永远读不了这个故事。
Java开发者的六个月——AI Agent狂欢里的旁观者
2025年11月。一个叫 Clawdbot 的项目在 GitHub 上炸开了锅。它后来改名 Moltbot,再后来定名 OpenClaw。五个月内狂揽14万星——在开源史上,这个速度排进前三。
它的核心卖点简单到嚣张:一个跑在你自己的硬件上的个人AI助手,连着你的所有聊天软件。 不是浏览器里的聊天框,不是一个独立的App。是一个后台守护进程,住在你的电脑里。你在 WhatsApp 上发消息,它回。你在 Telegram 上喊它,它应。你在 Slack 频道里 @ 它,它干活。
它还有一套完整的产品矩阵:macOS 菜单栏应用,iOS 和 Android 节点,Voice Wake 持续语音监听,Talk Mode 用 ElevenLabs 语音合成跟你对话,Live Canvas 让 Agent 操控一个实时画布。它不是”聊天的机器人”。它是”有手有脚有记忆的数字管家”。
但 Java 开发者只能看着。
OpenClaw 用 Node.js。Claude Code 用 Node.js。Cursor 用 TypeScript。LangChain 用 Python。整个 AI Agent 赛道在 2026 年属于脚本语言。Java 生态不是没有能力——Spring Boot 是全球最成熟的后端框架,Spring AI 刚刚发布了 2.0.0,JobRunr 做了八年后台任务调度——但它们没有被人组合起来,用在一个 AI Agent 项目里。
直到 JobRunr 团队自己动手。
推倒重来——vibe code是机翻,两周精译才是成品
建一个 Java 版的 OpenClaw,这件事说起来容易。但 JobRunr 团队走了一条更诚实的路。
他们先用 AI 辅助 coding——也就是现在流行的 vibe code——搭了一个原型。多通道支持。LLM 集成。任务管理。功能全通了。Demo 效果不错。看起来很漂亮。
然后 CTO Ronald 打开了代码。
他看了十分钟。
关掉了 IDE。
“AI slop,”他在后来的博客里写道。”过时的依赖。表面上说得通、但经不起推敲的设计模式。那种你不敢改任何东西的代码库——因为你根本不知道它为什么能跑。”
推倒。全部重写。
两周后,JavaClaw 重生。
这不是一个”AI 写代码不靠谱”的故事。这是一个”机翻和精译的区别”的故事。
AI 的 vibe code 是一次机翻——语法全对,单词全在,但读起来不对劲。句子是翻译了,但节奏是原文的节奏。结构是原文的结构,但新语言不需要这种结构。你读得懂,但你知道这不是”中文”——这是”英文穿了一件中文的外套”。
Ronald 的两周重写是一次精译。他没有修复机翻的段落。他扔掉机翻文稿,重新读了一遍原著,然后用中文的节奏、中文的句式、中文的意象,把故事重新讲了一遍。27 次提交,每次都是深思熟虑的句子。不是改了一个单词,是重写了一段话。
现在来看这份精译稿件。
翻译的艺术——Spring三件套如何让Java版更干净
推倒重来之后,代码变成了什么样子?翻开源码,你会发现它不是在模仿 OpenClaw。它在用 Java 重新表达 OpenClaw。
这种”重新表达”,我称之为架构级的翻译。
第一本参考书:Spring AI——”调用API”被译成了”依赖注入”
在 OpenClaw 的源码里,LLM 调用是这样的:装一个 HTTP 库,封装几个函数,拼 prompt,发请求,解析响应。典型的 Node.js 做法——每次调用 LLM 就是在客厅里接一根水管,水能通,但水管裸露在墙外面。
Spring AI 把它译成了什么呢?
@Autowiredprivate ChatClient chatClient;public String ask(String prompt) {return chatClient.prompt().user(prompt).call().content();}
ChatClient 是一个 Spring Bean。和 DataSource 一样被注入。和 RabbitTemplate 一样被管理。LLM 不是”外部服务”,是”Spring 容器里的一等公民”。
Spring AI 的 Advisor 链——SimpleLoggerAdvisor(日志)、ToolCallAdvisor(工具调用)、MessageChatMemoryAdvisor(对话记忆)——像流水线上三道工序,来料加工,自动流转。Agent 不会忘记上一轮说了什么,因为这层记忆是框架级的。切换模型?改一行配置。OpenAI 换 Anthropic 换 Ollama 换 Gemini——ChatClient 接口不变,底层自动适配。
原著的”axios.post(url, body)”被译成了”chatClient.prompt().user(prompt).call().content()”。这中间隔着的不是函数签名的差异,是一整套依赖注入哲学。
第二本参考书:JobRunr——”定时任务”被译成了”任务生命周期管理”
OpenClaw 有 cron job。怎么实现的?Node.js 生态里的调度库。任务失败了怎么办?进程重启了怎么办?100 个定时任务同时触发怎么办?——这些是 Node.js 调度库不会替你回答的问题。
JavaClaw 把它译成了 JobRunr。
JobRunr 做了八年一件事:后台任务调度。在 JavaClaw 里,一个任务的一生是这样的:
Agent创建任务 → TaskManager写Markdown文件 → JobRunr接管调度→ 到时间触发TaskHandler → TaskHandler调Agent执行任务→ 成功?标记completed→ 失败?标记回todo → 自动重试 → 最多三次
打开 localhost:8081,JobRunr 仪表盘上你能看到:哪些任务在执行、哪些失败了、重试了几次。像一个微型的运维大屏。
译得最漂亮的一处是:JavaClaw 把”调度”放在了比”LLM”更高的位置。调度是基础设施,LLM 是基础设施上跑的业务。而这正是 Agent 的真实需求——Agent 不只需要”智能”,更需要”在正确的时间做正确的事,并且做错了有人兜底”。
原著用”cron库”表达了”定时执行”这个简单概念。译本用”@Job(retries=3)”表达了”任务生命周期管理”这个完整图景。不是译得更短,是译得更深。
第三本参考书:Spring Modulith——”monorepo”被译成了”模块边界即物理定律”
OpenClaw 的仓库结构是一个典型的 Node.js monorepo。packages、apps、extensions、skills、ui、src、test、config……15 个子目录层层嵌套。模块之间的依赖关系——有人在 pnpm-workspace.yaml 里维护,有人在脑子里维护,有人在每次 pnpm install 报错的时候才发现又坏了。
JavaClaw 把它译成了四个模块:
JavaClaw/├── base/ ← Agent引擎、任务管理、工具、通道抽象├── app/ ← Spring Boot入口、引导UI、Chat通道├── providers/ ← LLM供应商:Anthropic、OpenAI、Ollama、Gemini└── plugins/ ← 插件:Telegram、Discord、Brave搜索、Playwright
base 不依赖 app。app 依赖 base。providers 和 plugins 各自封装,通过 Spring 自动发现注入。想加新通道?实现 Channel 接口。想换 LLM?实现 AgentOnboardingProvider。引导安装页自动识别、自动出现选项。
Spring Modulith 在编译期就检查模块边界。你不可能不小心在 base 里引用 app 的类——编译器直接拒绝。这不是代码规范,这是物理定律。
原著的”15个目录互相依赖”被译成了”4个模块,编译期强制不越界”。译本比原著少了11个目录,不是因为删了功能,是因为 Java 生态不需要用”目录数量”来表达”模块化”。模块化是编译器的活,不是目录名的活。
三样工具之外——其他译得漂亮的段落
通道架构:译成了一行接口
JavaClaw 只有 3 个通道:Telegram、Chat UI、Discord。原版有 25 个。不是因为”做不了”,而是因为通道架构被译成了一个接口:
所有入站消息变成同一个事件 ChannelMessageReceivedEvent。ChannelRegistry 路由给 DefaultAgent → Agent 调 LLM → 响应原路返回。加一个新通道 = 实现一个接口 + 发布一个事件。核心 Agent 逻辑一行不动。
25 个通道很了不起。但每次 API breaking change,你要维护 25 个集成。译本只做了 3 个——三个足以验证架构,剩下的只需要实现接口。维护成本?几乎为零。
任务存储:译成了Markdown文件
这是译本里我最喜欢的一处翻译。
原著的 Agent 任务存数据库。你得写 SQL 才能看见 Agent 在想什么。译本存 Markdown 文件,带 YAML frontmatter:
workspace/tasks/2026-03-21/143022-提醒我买菜.md
---task:提醒我买菜createdAt:2026-03-21T14:30:22status:tododescription:下午六点提醒我去超市买菜---
状态转换:todo → in_progress → completed / awaiting_human_input。
打开文件管理器就能巡视 Agent 的待办清单。Git diff 能追踪任务演变。备份?复制 workspace 文件夹。换台机器?tar 过去。调试 Agent 为什么卡住了?打开文件看 YAML 头部的 status 字段。
这是”基础设施即代码”思想在 Agent 领域的延伸——”状态即文件”。简单到让人觉得”这也能行?”——然后细想,发现没有比这更好的方式。
前端:译成了服务器渲染
原著的 Control UI 是一个 React SPA。需要 pnpm ui:build。JavaScript 加载失败?白屏。
译本的 Chat UI 用了 htmx + Bulma。服务器返回 HTML 片段,htmx 换到 DOM 里。WebSocket 实时推送,断了自动降级到 REST 轮询。最妙的是——关掉 JavaScript,网站照样工作。htmx 的 hx-boost 只是加速器,不是发动机。锚点和表单标签不依赖 JS。
这不是”简陋”。这是”网络韧性”。原件在断网时罢工。译本在断网时继续服务。
从零到运行——打开IDEA,你也能拥有一个Java版的AI助手
翻译看完了。现在来实际读一读这份译本。
两条命令:
git clone https://github.com/jobrunr/JavaClaw.gitcd JavaClaw./gradlew :app:bootRun
然后打开 localhost:8080/onboarding。
一个 7 步引导流程会带你配置一切:
选大脑。 Ollama(纯本地,不需要 API Key)还是 OpenAI 还是 Anthropic 还是 Google Gemini。如果你本地装过 Claude Code,AnthropicProvider 自动检测已有的 OAuth Token——零配置接入。好的翻译不仅准确,还贴心地附了脚注。
写人设。 一个在线编辑器,让你自定义 AGENT.md——Agent 的系统提示词。你是谁?做什么工作?Agent 该怎么称呼你?这决定了你的 Agent 的”性格”。每个译本都有自己的语气——你的语气你来定。
接外部工具。 MCP 服务器配置。想让 Agent 读你的 Gmail?配一个 Gmail MCP Server。想让 Agent 操作你的数据库?配一个 JDBC MCP Server。协议是标准的,工具是无限的。
连通道。 Telegram Bot Token + 允许的用户名。配完就能在手机上跟你的 Java Agent 聊天。
配置完。打开 localhost:8080/chat。或者打开 Telegram。或者连接 Discord。
你对它说:”每天早上八点,总结我在 Gmail 里收到的新邮件,发给我。”
发生的事情:
-
Agent 调用 TaskTool,TaskManager 在
workspace/tasks/recurring/下写一个 Markdown 文件 -
JobRunr 注册 cron
0 8 * * * -
每天八点,RecurringTaskHandler 创建当天任务实例 →
todo -
JobRunr 调度 TaskHandler →
in_progress -
Agent 通过 MCP 读 Gmail,通过 LLM 总结 →
completed -
通过 Telegram 发给你 -
任何一步失败 → 标记回
todo→ 自动重试三次
打开 localhost:8081。JobRunr 仪表盘上,你能看到这个任务的每一次执行、每一次成功、每一次重试。
而且这一切有测试背书。TaskManagerTest 验证任务创建、文件命名、JobRunr 集成。TelegramChannelTest 覆盖授权和拒绝。OnboardingControllerTest 跑通七步引导全流程。JavaClawApplicationTests 全量 Spring 上下文加载——确认所有 Bean 正确装配。
工业级不是说出来的。是测出来的。
译本的价值——让原作在另一种语言里获得第二次生命
回到最开始的问题。
为什么要翻译?
好的翻译从来不是为了”替代”原作。原作的读者群是 TypeScript 开发者。他们在 Node.js 生态里如鱼得水。OpenClaw 是写给他们看的——用他们的语法、他们的工具链、他们的工程习惯。
译本的目标读者是另一个人群。Java 开发者。这群人已经习惯了依赖注入、编译期检查、声明式配置、框架级抽象。如果硬塞给他们一个 Node.js 的 AI Agent——”你先装 Node 24,然后配 pnpm workspace,然后写 TypeScript”——他们会礼貌地点头,然后回去写 Spring Boot。
JavaClaw 做的事是:把这群人已经熟悉的语言——Spring AI、JobRunr、Spring Modulith——组合起来,告诉他们,用你已经在用的工具,你也能拥有一个 AI Agent。 原文的精华全部保留,但表达方式是你从小就熟悉的。
六个月前,Java 开发者是这场 AI Agent 狂欢的观众。他们鼓掌。他们羡慕。然后他们意识到——舞台上没有 Java。
现在,有人递了一张入场券。
入场券上写着:
git clone https://github.com/jobrunr/JavaClaw.git./gradlew :app:bootRun# 然后打开 localhost:8080/onboarding
Java 不仅跟上了。Java 带来了一套自己的工具箱——Spring AI 的依赖注入哲学、JobRunr 的任务生命周期管理、Spring Modulith 的编译期模块边界。这三样东西,Node.js 生态没有现成的等价物。
不是移植。移植是”把原文搬到另一种语言里,保留原文的所有结构,哪怕在新语言里显得别扭”。JavaClaw 没有逐行移植 OpenClaw。它理解了 OpenClaw 想表达什么——个人AI助手、多通道通信、任务调度、技能扩展——然后用 Java 生态的原生语言,把同样的意思重新说了一遍。
AGENTS.md 第一行写的是 “Edition”。但读完这份代码,你觉得它应该叫 “Translation”。
好的翻译不是替代原作。好的翻译是——让原作在另一种语言里,被更多人读懂。
现在,去读这份译本。
git clone https://github.com/jobrunr/JavaClaw.git
去看它的 27 次提交——每一次都是一句反复推敲的译文。去看 OpenClaw 的 41,296 次提交——去理解原著的故事。然后选一本你读得最舒服的语言。加入原著的英文读者群,或者成为译本的第一批中文读者。
Java 在 AI Agent 牌桌上——终于有了自己的筹码。不是你换了一副牌,是你终于发现,牌一直在你手里。现在,出牌。
夜雨聆风