先说个我上个月的实际经历。一套跑了七八年的 Java 订单管理系统,功能稳定,但业务侧每天都要手动处理三件事:审异常单、盯竞品公开价格、发日报。我当时想的就是——能不能用 OpenClaw 给它装个"数字员工",把这些重复劳动自动化掉。陆陆续续折腾了两周,中间踩了不少坑,最后终于跑通了一条"自动审单、爬数据、发报告"的完整链路。这篇就把整个方案的设计思路、部署过程、Java 集成方式和排错记录完整写下来,给同样在维护老系统的朋友一个参考。
这套方案适合谁?手头有 Java 老系统、日常被固定重复劳动消耗、又不想推翻重来的团队。不夸张地说,OpenClaw 加上一个 Spring Boot 桥接服务,就能在不改动老系统代码的前提下,把 AI 能力和业务流程结合起来。下面从痛点开始说。
1. 老系统里"审单、爬数据、发报告"到底卡在哪:三个场景的真实痛点
1.1 自动审单:硬规则好写,订单里的"人话"难判
订单审核表面上看是流程性工作,实际上分两层。第一层是硬规则:订单金额有没有超限、客户信用额度够不够、商品库存是否充足、收货地址是否完整。这些规则很明确,Java 里写 if-else 十分钟就搞定。但第二层就麻烦了——订单备注里经常出现"客户说这批货先发一半,余款下周付""发票不要开给公司,开给分公司""这个颜色发错了,用户要求换成黑色"这类自然语言。老系统没有 NLP 能力,只能靠人工逐条看备注。
这不是一个能用普通脚本解决的需求。它的本质是把"非结构化文本"和"结构化业务规则"放在一起做判断。如果不能理解备注的意图,自动审单就只是一个增加了风险过滤器的批量操作。后来我引入 OpenClaw 来处理这一层"软判断",用本地模型理解备注内容,再结合 Java 侧跑完的硬规则结果输出最终决策。
人工执行的痛点也很明显:审单的人每天上午都要打开几十张订单,逐条核对备注和金额。看漏一条,后面就是客诉和赔款。而且这种重复性工作极其消耗注意力,真正需要经验判断的复杂单反而没有足够精力处理。
1.2 数据采集:最耗时间的反而是"复制粘贴"
项目里还有一个真实需求:每天要盯几个公开页面的价格和库存变化,比如竞品的公开标价、供应商页面的现货量。传统做法是人工打开网页、复制关键数字、粘贴到 Excel。这个工作有三个问题。
第一,极易出错。复制的时候看错一行,后面整张报表都是错的。我见过同事把"库存 120 件"看成"库存 12 件",直接导致采购决策偏差。第二,存在遗漏。页面一多,今天漏看两家是常态,而且没有任何日志记录"今天到底看了哪几家"。第三,时间碎片化。每天几十分钟甚至一两个小时的重复劳动,正好卡在早晨刚上班的黄金时段。
这里多说一句关于合规的问题。采集公开信息本身不违法,但是必须只采集公开可访问的数据,遵守目标网站的 robots 协议和服务条款,控制请求频率,不要做任何绕过登录或权限限制的操作。我在这套系统里把抓取范围限定在几个明确授权的公开页面,并把请求间隔控制在合理范围内。这也是 Java 侧比较容易做到的事——HttpClient 加固定延时,简单可靠。
1.3 发报告:没有技术含量,但不能出错
每天早上十点给业务群发前一天的订单日报,每周一早上发上周汇总,每个月月底发月度经营快报。看起来就是把数据汇总成 Excel,再发出去,但实际做过的都知道麻烦在哪。
口径不统一。同一个"订单金额"在不同人手里可能包含了不同状态的订单,今天算已支付,明天算已发货。格式每次都要改。今天加一列,明天换个标题,Excel 模板永远在"临时调整"的路上。邮件发漏了没人提醒,直到有人问"今天怎么没收到"。这些事适合用 OpenClaw + Java 自动化,核心原因只有一个:流程确定、执行固定、判断简单,但重复次数多、人工执行容易出错。这正好是"数字员工"的价值区间。
2. OpenClaw 在方案里的定位:补上 Java 工程最缺的"编排大脑"
2.1 OpenClaw 是什么:任务编排器,不是语言也不是框架
简单说,OpenClaw 是一个开源的智能体任务编排平台。你可以把它理解成一个"数字员工的排班经理":你给它定义好岗位职责(Skill,技能),告诉它能用哪些工具(比如调 HTTP 接口、读文件、执行命令),它会调用大语言模型来理解任务、拆分步骤、调用技能、返回结果。
它不属于任何特定语言,不是 Java 的替代品,也不要求你把老系统重构一遍。它独立部署,通过 HTTP API 与外部系统交互。Java 侧只需要处理好"提交任务、轮询状态、接收结果"这一层。
和偏开发框架类的工具相比,OpenClaw 更侧重于"开箱即用"的部署形态:有可视化的配置界面,Windows 环境下有 companion 程序辅助管理,有技能机制,可以方便地切换模型 Provider。对 Java 老系统团队来说,这意味着不需要团队里有专门的 AI 背景的人,运维一个独立服务即可,学习成本低很多。
2.2 为什么选 OpenClaw 而不是自己写一套 Agent
这个问题我犹豫过。Java 侧也不是不能写:用 Spring AI 或自己封装本地模型的 API,写一个链式调用,也能实现一部分"任务解析 + 工具调用"。但实际评估下来有三个问题。
第一,Agent 的"任务拆解、上下文管理、技能注册"这些能力,自己写起来工作量非常大。一个足够稳定的 Agent 框架,至少涉及 prompt 模板管理、多轮对话历史、工具调用的结果回填、错误恢复机制。这些 OpenClaw 已经做好了,没必要在项目里重复发明轮子。
第二,大模型返回结果不稳定,需要一套完整的降级与重试策略。自己做等于要从零踩一遍所有坑,而 OpenClaw 的社区已经把这些常见问题踩过一轮了,技能模板、JSON 格式约束这些细节都有现成方案。
第三,可维护性。OpenClaw 的 Skill 可以独立配置、独立升级,Java 侧只管业务逻辑。如果哪天要换模型,从 Qwen2.5 换成别的,OpenClaw 里改配置就行,Java 代码一行不用动。这个解耦对长期维护来说价值极大。
2.3 整体集成架构:数据流向与模块职责
我用文字把整个链路理一遍,不画图,大家对着文字也能在脑子里拼出来:
- 老系统 MySQL:订单表、商品表、客户表、以及后来新增的审单结果表、采集数据表。
- Java 桥接服务(Spring Boot):跑硬规则、读写数据库、调用 OpenClaw 的 HTTP API、发送最终报告。这是整个系统的"手和脚"。
- OpenClaw 服务:负责理解任务、调度技能、调用本地模型。相当于"大脑皮层"。
- Ollama 本地模型(qwen2.5-3b):提供推理能力,数据不出内网。
- 外部数据源:几个公开页面,Java 定时抓取后交给 OpenClaw 判断变化。
- 推送通道:邮件 SMTP、企业微信群机器人 Webhook。
链路如下:定时任务触发 Java 桥接服务 → 桥接服务从老系统拉取订单 → 硬规则跑完 → 对规则无法判定的订单调用 OpenClaw API → OpenClaw 调技能、调本地模型理解备注 → 返回结构化 JSON → 桥接服务解析并把决策回写数据库 → 到达报告时间,Java 汇总数据生成 Excel,同时让 OpenClaw 生成文字摘要 → 一起推送到邮件和群里。
每个环节的职责都很清晰:Java 不碰 AI 推理,OpenClaw 不碰业务数据库。出问题的时候边界分明,排查效率高。
3. 环境准备与部署:Windows 下最容易卡住的三件事
3.1 WSL2 环境检查:PowerShell 两行命令确认
OpenClaw 在 Windows 上依赖 WSL2 环境。我部署时最常遇到的提示就是"环境验证失败"或者"请在 PowerShell 中运行 wsl --status"。
先打开 PowerShell(建议管理员模式),运行:
wsl --status wsl -l -v第一行看 WSL 整体状态,第二行看已经安装的发行版版本。如果显示版本是 1,需要升级到 2:
wsl --set-default-version 2 wsl --update如果提示没有安装 WSL,直接:
wsl --install装完重启终端再检查一次。确认无误后再继续装 OpenClaw,否则后面启动服务会莫名其妙报错,而且报错信息不一定直接指向 WSL,排查起来非常绕。
这里多说一句:很多人卡在这一步是因为 PowerShell 权限不够。建议用管理员身份执行这些安装命令,但日常跑 Node 服务建议用普通用户身份,否则会碰到一堆文件读写权限的坑。两种身份混着用是 Windows 部署最常见的问题来源。
3.2 Node.js 环境与 npm 安装
OpenClaw 本身跑在 Node.js 上。建议装 LTS 版本,不要追最新版,我遇到过 Node 版本过新导致某个依赖编译失败的情况。
推荐用 nvm-windows 管理多版本:
nvm install 20 nvm use 20 node -v然后安装 OpenClaw,这里只说容易出错的地方:npm 全局安装时,PowerShell 的执行策略可能拦截脚本,需要先允许脚本执行:
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser这一步经常被文档省略,但实际部署时大概率会遇到。验证安装成功的标准不是"命令不报错",而是能打开它的管理界面、能看到技能列表。如果只能看到命令行输出但管理界面访问不了,多半是端口被占用,检查一下 Windows 防火墙入站规则。
3.3 接入本地模型:Ollama + Qwen2.5 的选择
模型配的是 Ollama 本地部署的 Qwen2.5-3B。选它的理由有三个:一是 3B 参数规模在普通办公电脑上就能跑,16G 内存的机器很流畅;二是中文理解能力在同量级模型里表现不错,审单备注这种场景够用;三是本地推理,数据不出内网,订单信息、客户信息不会经过外部 API。
拉取模型:
ollama pull qwen2.5:3b ollama serve然后在 OpenClaw 的模型 Provider 配置里指向 Ollama 的本地地址,填上模型名称即可。
关于"OpenClaw 是不是只能用 API 方式使用算力"这个问题——不是。它支持多种 Provider,本地 Ollama 完全可行。区别在于:本地模型响应速度慢一些、推理质量上限低于大厂云端 API,但胜在数据安全、零调用费用。如果跑实时性要求高的场景,可以考虑云端 API;如果做审单这种允许几秒延迟的批处理,本地模型体验反而更稳,不会因为云端限流导致任务失败。
3.4 验证安装:跑通第一个最小 Skill
部署完成后先别着急写 Java。先手动跑通一个最小任务:要求 OpenClaw 执行一个"回复当前时间"的技能,确认整条链路(管理界面 → Agent → 模型 → 返回)是通的。
这一步看似简单,但能提前暴露 80% 的环境问题。我实际部署时,就在这个环节发现模型 Provider 地址配置错了,端口写成了 SQL Server 的默认端口 1433。如果直接进 Java 联调,这个错误会伪装成"任务执行超时",排查成本高得多。
4. Java 侧集成:把 OpenClaw 封装成老系统能用的内部服务
4.1 桥接模块的边界
我不建议在旧系统里到处改代码。新增一个独立的 Spring Boot 模块,它只干四件事:定时触发业务流程、操作老系统数据库(读写订单、回写审核结果)、调用 OpenClaw API 提交任务并接收结果、发送邮件和群消息。
老系统本身一行代码不用改。这个模块就像在老系统旁边接了一个"外挂机械臂",而不是给老系统做心脏手术。边界清晰的好处是出问题容易回滚——把桥接服务停掉,业务立刻回到人工处理模式,老系统完全不受影响。我实际跑了两周,中间有一次 OpenClaw 服务挂了一天,业务侧毫无感知,还是人工在审单,这就是边界清晰的价值。
4.2 实现 TaskClient:提交任务与轮询状态
@Service public class OpenClawTaskClient { private final RestTemplate restTemplate; private final String baseUrl = System.getenv() .getOrDefault("OPENCLAW_BASE_URL", "http://localhost:18080"); public OpenClawTaskClient(RestTemplate restTemplate) { this.restTemplate = restTemplate; } public String submitTask(String skillName, Map<String, Object> params) { Map<String, Object> body = new HashMap<>(); body.put("skill", skillName); body.put("params", params); ResponseEntity<Map> resp = restTemplate.postForEntity( baseUrl + "/v1/tasks", body, Map.class); return String.valueOf(resp.getBody().get("taskId")); } public OpenClawResult pollTask(String taskId, int maxWaitSeconds) { long deadline = System.currentTimeMillis() + maxWaitSeconds * 1000L; while (System.currentTimeMillis() < deadline) { ResponseEntity<Map> resp = restTemplate.getForEntity( baseUrl + "/v1/tasks/" + taskId, Map.class); String status = String.valueOf(resp.getBody().get("status")); if ("done".equals(status) || "failed".equals(status)) { return parseResult(resp.getBody()); } Thread.sleep(2000); } throw new TaskTimeoutException("task " + taskId + " timeout"); } }这段代码是简化示意。真实项目里并发量不高的话,RestTemplate 完全够用;如果预期任务量大,再考虑换成 WebClient 或带连接池的 OkHttp。环境变量配置 baseUrl 是刻意设计的,因为 OpenClaw 的端口可能在测试环境、生产环境不一样,写死会在部署时埋坑。
4.3 结果解析与异常兜底
OpenClaw 返回的 JSON 字段结构,需要在联调时确认一遍。LLM 生成的 JSON 有时候字段顺序会变,甚至会多出解释性文字。所以解析时不要直接强转,要做兜底。
public class LlmResultParser { public static LinkedHashMap<String, Object> parseStrict(String raw) { // 1. 先尝试直接解析 // 2. 如果失败,提取其中 ```json ... ``` 代码块内容再解析 // 3. 还失败,标记为"需人工复核",不让流程静默失败 } }这里有个关键点:LLM 结果解析失败时,千万不要"吞掉异常"。宁可多花几秒走人工兜底,也不要让一个无法理解的判断结果进入业务系统。审单这个场景,一次错误的自动通过可能造成几万元的损失,而一次解析失败最多就是多一个人工点一下。这个取舍一定要想清楚。
4.4 调度触发:Spring 定时任务与 OpenClaw 的分工
定时触发我最后选了 Spring @Scheduled,而不是 OpenClaw 内置的调度:
@Scheduled(cron = "0 30 9 * * *") public void dailyOrderAudit() { // 每天9:30触发审单流程 }原因很简单:Java 侧要掌控业务流程的整体节奏,比如"先审单、再审款、再发报告"这个顺序,用 Spring 的定时方法写顺序逻辑最直观。OpenClaw 的调度适合做自身技能的定期执行,但不适合去编排 Java 侧的业务步骤。如果任务周期不规则,可以考虑用消息队列触发,但对于这种固定周期任务,@Scheduled 已经足够可靠。
5. 三个自动化场景落地:审单、采集、报告的实现细节
5.1 自动审单:硬规则 + LLM 软判断 + 人工兜底三通道
审单流程分为三条通道:
| 通道 | 触发条件 | 处理方式 |
|---|---|---|
| 自动通过 | 硬规则全过,且备注无自然语言需求 | 直接通过,记录日志 |
| 自动驳回 | 硬规则明确不满足(金额超限、黑名单、库存不足) | 直接驳回,记录原因 |
| LLM 判断 | 硬规则通过,但备注含自然语言需求 | 调用 OpenClaw 分析风险,按 risk_level 分流 |
给 OpenClaw 的 prompt 大体是这样:
你是订单审核助手。以下是订单信息: 订单号:{orderId} 金额:{amount}元 客户信用额度:{creditLimit}元 库存状态:{stockStatus} 客户备注原文:{originalRemark} 请判断: 1. 备注中是否存在与系统默认规则冲突的要求? 2. 该要求是否会影响履约风险? 3. 如果有风险,建议处理方式是什么? 只输出JSON格式:{"risk_level": "low|medium|high", "conflict": true|false, "suggestion": "建议"}OpenClaw 返回 JSON 后,Java 侧做最终决策:risk_level 为 low 自动通过;medium 转人工确认;high 自动驳回并通知客服。这个三层分流非常实用,真正需要人工处理的单子只剩一小部分,而且都是真正有歧义的。跑了一周后统计,大约 65% 的订单走自动通过,25% 自动驳回,只有 10% 转人工,但恰恰是这 10% 才是审核员真正应该花时间的地方。
5.2 数据采集:合规、限频、增量三个原则
采集部分前面已经提过合规要求,这里讲实现细节。数据源是几个公开页面,Java 用 HttpClient 定时抓取。
@Scheduled(cron = "0 */30 * * * *") public void fetchPublicPages() { List<String> urls = pageConfigService.getEnabledUrls(); for (String url : urls) { try { Thread.sleep(ThreadLocalRandom.current().nextLong(3000, 8000)); String html = httpClient.fetch(url); String fingerprint = DigestUtils.md5DigestAsHex(html.getBytes()); if (pageSnapshotService.isSame(url, fingerprint)) { continue; } pageSnapshotService.save(url, html, fingerprint); openClawTaskClient.notifyChange(url); } catch (Exception e) { log.error("fetch failed: {}", url, e); } } }要点有三个:请求间隔随机化(3-8 秒),避免固定频率触发对方限流;内容指纹比对,没变化就不重复解析;变化后再调用 OpenClaw 提取需要关注的字段(比如"价格从 12.5 变为 11.9")。这样既减少无效计算,也减少对外部站点的打扰。数据落库之后,报告阶段直接查表即可。
5.3 报告生成与推送:POI 出表、LLM 出摘要、webhook 出门
报告分两半:结构化数据用 Apache POI 生成 Excel,文字摘要交给 OpenClaw 生成。POI 生成 Excel 的核心代码不复杂:
Workbook workbook = new XSSFWorkbook(); Sheet sheet = workbook.createSheet("订单日报"); Row header = sheet.createRow(0); header.createCell(0).setCellValue("订单编号"); header.createCell(1).setCellValue("金额"); // 填充数据行,设置单元格样式文字摘要是亮点。我让 OpenClaw 基于当天的数据变化生成一段 3-5 行的简报,比单纯的数据表格更容易让业务负责人快速了解"今天发生了什么"。具体做法是把当天审单统计、采集变化、异常单列表作为上下文传给 OpenClaw,让它总结成要点式文字。
推送用两条通道:
// 邮件 mailSender.send(prepareDayReportMail(subject, attachment)); // 企业微信群机器人 restTemplate.postForEntity( "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx", buildMarkdownMessage(markdownText), String.class);邮件负责正式存档,群机器人负责让业务群第一时间看到摘要。注意群机器人 Webhook 有频率限制(一般每分钟最多 20 条),日报每天一条完全没压力,但如果设计了失败自动重推,要加最多 3 次重试限制,避免触发限流。发送邮件时不要伪造发件人,用公司 SMTP 服务正常发送,配置好 DKIM 签名,避免进垃圾箱。
6. 联调排错记录:从"跑不通"到"稳定跑两个月"的完整链路
6.1 现象一:任务提交成功但轮询超时
第一次联调,Java 提交审单任务到 OpenClaw,任务状态一直是 running,直到超时。排查过程:先看 OpenClaw 的日志,发现任务确实在执行,但卡在模型调用上。再看 Ollama 的日志,发现模型加载了但推理很慢,原来是不小心把 qwen2.5:3b 的上下文窗口设得很大,导致单次推理要几秒到十几秒。任务一多就排队积压。
解决:调小上下文窗口;Java 侧把轮询超时从 30 秒放宽到 120 秒;审单任务是批量的,一次任务处理多个订单,而不是每个订单提交一个任务。这样任务数量和推理开销都下降了一个数量级。
经验:OpenClaw 这种编排器的性能瓶颈通常不在编排器本身,而在模型推理和外部 IO。排查时先从最下游开始看,先确认模型没问题,再看编排器,最后才是 Java 这边的配置。
6.2 现象二:LLM 返回的 JSON 字段不稳定
跑了一周后开始出现偶发的解析失败。打印出原始返回发现,模型偶尔会在 JSON 外面包一层解释文字,比如先写一句"根据订单信息,分析如下:"再输出 JSON。
解决方式有三层:一是在 prompt 里加"只输出 JSON,不要任何解释文字",能把失败率降到很低但不能清零;二是解析时做宽容处理,提取第一个{到最后一个}之间的内容再解析;三是解析失败时标记"需人工复核",而不是报错终止整个流程。这个经验值得记下来:任何依赖 LLM 输出的系统,都必须把"格式不完美"当作常态来设计,而不是当作异常。
6.3 现象三:Windows 下 Node/WSL 内存吃紧
运行两周后,OpenClaw 服务开始假死,请求无响应。检查发现 WSL 默认内存上限吃满了,Ollama 模型常驻内存加上 Node 进程,再加上 WSL 自身开销,挤在一起。解决:在%UserProfile%\.wslconfig里限制资源:
[wsl2] memory=8GB processors=4 swap=2GB重启 WSL 后稳定很多。另外把不需要的 WSL 发行版关掉,减少常驻内存占用。这个问题在文档里基本不会提到,属于实际部署才会碰到的经验。
6.4 关于卸载与升级:保留数据再动手
最后提一下卸载问题。如果要重装或升级 OpenClaw,先把任务配置、技能定义、模型配置这些导出一份。OpenClaw 的数据目录里有历史任务记录,如果直接卸载会导致这些记录丢失,将来想回溯某一天的审单明细就没有依据了。卸载前最好停掉桥接服务,人工接管业务流程;卸载完成重新部署后再恢复桥接。这个顺序能保证业务不中断。
我实际跑了两周之后,最大的感受是:这类"数字员工"方案的价值,不一定是省了多少钱,而是把团队里最熟练的同事从复制粘贴里解放出来了。负责审单的同事现在每天只需要处理真正需要判断力的异常单,而不是一遍遍地看备注。对我自己来说,OpenClaw + Java 这套组合最舒服的地方在于边界清晰——Java 管数据和流程,OpenClaw 管理解和编排,出了问题各自排查,互不甩锅。如果你们团队也在面对老系统里那些零碎又耗时的重复工作,不妨也考虑装一个这样的"数字员工",先从一个最小的场景跑起来,比规划一个大而全的中台实在得多。