1. Solon v4.0 到底改了什么,为什么值得在 Agent 场景重跑一遍
Solon 是一个从零构建的 Java 应用开发框架,不走 Java-EE 那套重架构,主打更快、更小、更简单。v4.0 正式发布后,我第一时间把手上一个 Agent 工具链项目从 3.10.x 迁了过来,顺带把 GraalVM 原生镜像的构建流程也重跑了一遍。这篇就按我实际操作的顺序,把项目初始化、native-image 参数、以及通过统一 Key 通道接入 Agent 能力的配置完整写出来,你可以直接照着复现。
先说 v4.0 的核心变化,避免你升级时踩坑。这次大版本的主基调是“做减法”:把长期标记为弃用的方法和类彻底清理掉,框架内核更干净。对绝大多数没用过弃用接口的项目来说,直接升到 4.0.0 就行;如果你之前用过弃用 API,建议先升到 3.10.7,借编译器的提醒把弃用代码替换干净,再升 4.0.0,过渡最平滑。
变化最大的是 Solon AI 体系,把原来的 skill 概念正式改名为 talent。原因是 Agent 生态里 “agent skill” 已经被用来指代另一类东西,撞名容易混淆。对应插件坐标从solon-ai-skill-*换成solon-ai-talent-*,工具类也从WebfetchTool改成WebfetchTalent这类命名。另外新增了mcp-core替换旧的mcp-sdk,新增solon-ai-sandbox做智能体沙盒隔离,MCP 协议升级到MCP_2025_11_25,ReActAgent 的maxSteps更名为maxTurns。
生态规范化这块也值得注意:一批第三方插件回归官方仓库维护,groupId 变了。比如mybatis-plus-solon-plugin现在是com.baomidou:mybatis-plus-solon-plugin,sa-token-solon-plugin变成cn.dev33:sa-token-solon-plugin。升级时如果报找不到依赖,先查这个对照表。
为什么要在 Agent 场景重跑?因为 Solon 的启动速度和内存占用在原生镜像下优势明显,而 Agent 应用往往要频繁启停、按需拉起工具进程,冷启动时间直接决定体验。v4.0 清理了历史包袱后,native-image 的构建成功率比 3.x 更高,反射配置也更好收敛。下面进入实操。
2. 前置准备:项目初始化与 TaoToken 统一通道配置
在动手写代码前,先把两件事准备好:一个是 Solon v4.0 的项目骨架,一个是调用 Agent 能力要用的统一 Key 通道。我这边用 TaoToken 做统一入口,好处是模型对话、coding-plan、console 这些能力走同一个 Base URL 和 Key,不用在多个平台之间来回切配置。
先建项目。用 Maven 的话,pom.xml里把 Solon 版本锁到 4.0.0,父依赖引solon-parent:
<parent> <groupId>org.noear</groupId> <artifactId>solon-parent</artifactId> <version>4.0.0</version> </parent> <dependencies> <dependency> <groupId>org.noear</groupId> <artifactId>solon-web</artifactId> </dependency> <!-- Agent 能力:talent 体系 --> <dependency> <groupId>org.noear</groupId> <artifactId>solon-ai-talent-mount</artifactId> </dependency> <dependency> <groupId>org.noear</groupId> <artifactId>solon-ai-mcp</artifactId> </dependency> </dependencies>注意这里用的是solon-ai-talent-mount,不是旧的solon-ai-skill-*。如果你从 3.x 迁过来,这一步最容易漏。
接下来配置统一通道。TaoToken 的 API 入口是https://taotoken.net/api,控制台在https://taotoken.net/console,Key 在https://taotoken.net/api-keys生成。我习惯把配置写进app.yml,路径和字段名保持和官方一致,方便后面排查:
solon: app: name: solon-agent-demo taotoken: base-url: https://taotoken.net/api api-key: ${TAOTOKEN_API_KEY} model-id: claude-sonnet-4-5 timeout: 60000api-key用环境变量注入,别硬编码进仓库。模型 ID 按你实际要用的填,我这边 Agent 场景常用 claude 系列。如果你要跑长期编码或 Agent 任务,可以看 coding-plan 那条线;只是验证模型通不通,用模型对话页面更快。
这里有个细节:Solon 的配置读取支持${}占位符,启动时如果环境变量没设,会直接报错而不是静默用空值,这点比某些框架友好,能早暴露问题。
前置准备做完,你应该有:一个能编译的 Solon 4.0 骨架、一份带 Base URL 和 Key 的配置、以及确认过坐标没写错的依赖。下一步开始写可复制的接入代码。
3. 可复制配置:Agent 接入的 JSON 与启动参数
这一节给的是能直接抄的配置片段。Agent 接入的核心是把模型通道和 talent 挂载配好,我按文件路径分开写,你对照自己的项目结构放。
先是 talent 挂载的配置。Solon AI 的 talent 体系支持声明式挂载,写在app.yml里:
solon: ai: talent: mount: enable: true packages: - "com.example.agent.talent" mcp: client: enable: true providers: - name: local-tools transport: stdio command: ["node", "mcp-server.js"] allowedTools: - "read_file" - "search_code"注意allowedTools这个字段,v4.0 的 McpClientProvider 新增了工具白名单机制,默认不再启用心跳(之前是 30 秒一次)。如果你依赖心跳保活,得手动打开。McpProviders也改名成了McpClientProviders,老配置里如果写的是前者,升级后会不生效。
然后是模型通道的 JSON 配置。有些场景下配置不在 yml 里,而是走独立的 settings 文件,比如给外部工具链读的:
{ "baseUrl": "https://taotoken.net/api", "apiKey": "env:TAOTOKEN_API_KEY", "modelId": "claude-sonnet-4-5", "maxTurns": 12, "contextCompression": { "enable": true, "trigger": "onReasonStart" } }这里maxTurns就是 v4.0 里从maxSteps改过来的字段,别写错。contextCompression对应的是ContextCompressionInterceptor,v4.0 把压缩时机从onObservation挪到了onReasonStart,并增强了对过期区 tool-use 原子序列的追溯保护。如果你之前手动配过SummarizationInterceptor,现在要换成新名字。
启动参数这块,GraalVM 原生镜像的构建命令我放在下一节,这里先给 JVM 模式的启动参数,方便你先验证逻辑:
export TAOTOKEN_API_KEY=你的Key java -jar target/solon-agent-demo.jar \ --solon.ai.talent.mount.enable=true \ --solon.ai.mcp.client.enable=true三件套要记牢:Base URL 是https://taotoken.net/api,Key 从 api-keys 页面拿,Model ID 按需填。这三个只要有一个不对,后面验证就会失败。我见过最常见的错误是把 Base URL 写成带路径的完整接口地址,其实这里只填到/api就行,具体路径由 SDK 拼。
配置写完先别急着跑,用mvn compile过一遍,确认依赖坐标和配置字段没拼错。Solon 的配置绑定在启动时校验,编译期不报错但启动会报,所以编译通过只是第一步。
4. 验证请求:GraalVM native-image 构建与调用实测
这一节是重头戏,分两步:先用 GraalVM 构建原生镜像,再发一次真实请求验证 Agent 通道通了。
先确认环境。GraalVM 建议用 21 或 25 的版本,Solon v4.0 支持 Java 8 到 Java 25,原生镜像这块 21 最稳。装好后native-image --version能输出版本号即可。
构建命令我实测下来这套参数成功率最高:
native-image \ -jar target/solon-agent-demo.jar \ -o solon-agent-demo \ --no-fallback \ -H:+ReportExceptionStackTraces \ -H:ReflectionConfigurationFiles=src/main/resources/META-INF/native-image/reflect-config.json \ -H:ResourceConfigurationFiles=src/main/resources/META-INF/native-image/resource-config.json \ --enable-http \ --enable-https \ -J-Xmx4g几个参数说明:--no-fallback强制生成纯原生镜像,不生成回退的 JVM 版本,这样能暴露所有反射问题;-H:+ReportExceptionStackTraces在构建失败时给出完整堆栈,排查反射缺失很有用;--enable-http和--enable-https是网络请求必须的,Agent 调用模型通道走 HTTPS,漏了会运行时报错。
反射配置是 native-image 最容易卡的地方。Solon 的 talent 挂载和 MCP 客户端都涉及反射,我建议先用-agentlib:native-image-agent跑一遍 JVM 模式,让它自动生成 reflect-config:
java -agentlib:native-image-agent=config-output-dir=src/main/resources/META-INF/native-image \ -jar target/solon-agent-demo.jar跑完一次完整的 Agent 调用流程,agent 会把用到的反射、资源、代理类都记下来。然后再用上面的 native-image 命令构建,基本一次过。
构建成功后启动原生镜像:
./solon-agent-demo启动日志里应该能看到 Solon 的 banner 和 talent 挂载数量。我这边实测冷启动在 50ms 以内,比 JVM 模式快一个数量级。
接着发验证请求。用一个最简单的 HTTP 接口触发 Agent 调用:
curl -X POST http://localhost:8080/agent/chat \ -H "Content-Type: application/json" \ -d '{"prompt": "用一句话说明 Solon v4.0 的 talent 是什么"}'如果通道配对了,会返回模型生成的文本。返回体里如果带choices字段,说明走的是标准对话格式;如果报reading choices相关错误,多半是响应解析和实际返回结构不匹配,检查 Model ID 是否填对。
我实测下来,从原生镜像启动到第一次成功返回,整个链路在 2 秒内完成。这个速度对 Agent 场景很关键,因为工具调用往往是串行的,每次冷启动省下的时间会累积。
5. 常见报错排查:401、local proxy failed 与 OAuth 问题
这一节按我实际遇到的报错整理,每个都给定位思路。Agent 接入的报错大多集中在认证和网络两层,按顺序排查能省不少时间。
401 Unauthorized。这是最高频的。先确认 Key 有没有正确注入,echo $TAOTOKEN_API_KEY看环境变量是否为空。如果 Key 没问题,检查 Base URL 是不是写成了https://taotoken.net/api/带尾斜杠,某些 SDK 拼接时会出双斜杠导致认证失败。还有一种情况是 Key 复制时带了空格,肉眼看不出来,用cat -A检查一下。Key 在https://taotoken.net/api-keys页面重新生成一个对比测试最快。
local proxy failed。这个报错通常出现在 MCP 客户端连接本地工具进程时。检查app.yml里command字段的路径是否正确,node mcp-server.js这种相对路径在原生镜像里工作目录可能和 JVM 模式不同,建议改成绝对路径。另外 v4.0 默认关闭了 MCP 心跳,如果工具进程需要保活,手动打开心跳配置。如果报错里提到 transport,确认stdio和sse有没有写混。
reading choices 解析失败。这个不是网络问题,是响应结构不匹配。常见原因是 Model ID 填了一个返回格式不同的模型,或者请求里带了stream: true但客户端按非流式解析。先关掉流式,用最简单的请求验证。如果返回体里根本没有choices,检查 Base URL 是否被中间层改写过。
OAuth 相关报错。如果你用的是需要 OAuth 的通道,报错里会出现 token 过期或 scope 不足。这类问题先确认 OAuth 流程是否走完,token 有没有正确缓存。Solon 的配置里如果同时配了 api-key 和 OAuth,优先级要理清,别让两套认证互相覆盖。我建议先用 api-key 模式跑通,再切 OAuth。
native-image 构建期报 ClassNotFoundException。这是反射配置缺失,用上一节的 agent 模式重新生成 reflect-config。如果报的是资源找不到,检查resource-config.json有没有包含app.yml这类配置文件,原生镜像默认不打包资源,得显式声明。
启动报配置绑定失败。Solon 启动时会校验配置字段,报错信息里会指出哪个 key 不合法。v4.0 清理了一批配置项,比如server.session.state.domain换成了server.session.cookieDomain,solon.staticfiles.maxAge换成了solon.staticfiles.cacheMaxAge。对照官方更新说明改就行。
排查顺序建议:先看认证(401),再看网络(proxy failed),最后看解析(choices)。大部分问题在前两步就能定位。
6. 从验证到落地:把 Agent 通道接进你的工具链
跑通验证只是第一步,真正要落地还得把这条通道接进日常工具链。我这边主要接三个地方:本地开发时的模型对话、CI 里的自动化调用、以及长期跑的 Agent 任务。
本地开发时,我习惯用模型对话页面快速验证 prompt 效果,确认没问题再写进代码。这样能避免每次改 prompt 都要重新构建原生镜像。模型对话入口在https://taotoken.net/chat,用同一个 Key 就能进。
CI 里的自动化调用,重点是把 Key 管理好。我用的是环境变量注入,CI 平台的 secret 里存 Key,构建脚本里不出现明文。原生镜像构建和 Agent 调用分成两个 job,构建产物缓存起来,调用 job 直接复用,省构建时间。
长期跑的 Agent 任务,建议走 coding-plan 那条线。这类任务对稳定性和配额要求高,coding-plan 的通道更适合持续调用。配置上把maxTurns设合理,别设太大导致单次任务跑太久,也别太小导致任务中断。我一般设 12 到 20 之间,按任务复杂度调。
接入文档在https://taotoken.net/doc,里面有各语言的示例和字段说明。遇到配置字段不确定的,先查文档再改代码,比反复试错快。
最后说个我踩过的坑:原生镜像里如果用了动态加载的 talent,构建时要把对应的包路径写进反射配置,否则运行时会报类找不到。我一开始漏了com.example.agent.talent这个包,构建成功但调用时报错,排查了半天。后来用 agent 模式重新生成配置就好了。所以每次新增 talent 或 MCP 工具,记得重新跑一遍 agent 模式生成配置,再构建原生镜像。
整套流程走下来,从项目初始化到原生镜像跑通 Agent 调用,熟练后半小时内能完成。v4.0 的清理让这个过程比 3.x 顺畅不少,尤其是反射配置的收敛,构建成功率明显提升。如果你还在用 3.x,建议按前面说的先升 3.10.7 过渡,再上 4.0.0。