一个类,一次注册,搞定 2 个工具 + 1 个 Skill + 1 个 Sub-Agent

发布时间:2026/7/3 2:21:15
一个类,一次注册,搞定 2 个工具 + 1 个 Skill + 1 个 Sub-Agent 「Regnexe 实战系列」第 4 篇共 10 篇对应仓库ExampleReadme04PluginAnnotationTest。上一篇03. Sub-Agent自己的模型自己的工具。痛点能力一多注册代码比业务代码还长前三篇我们分别用withTool、withSkill、withSubAgent注册了工具、Skill、Sub-Agent。如果一个业务模块同时需要这三种能力按现在的写法得分别new三个对象再分三次with*调用——能力一多这部分装配代码很容易比业务逻辑本身还长。Regnexe 解决这个问题的思路很简单像Plugin注解一类工具方法一样把 Skill 和 Sub-Agent 也变成注解而且可以嵌套进同一个类共享同一个pluginId。先复习一下 PluginJava 老用户应该很熟悉这个套路——类上加Plugin方法上加AgentToolPlugin(idweather,nameWeather Plugin,description天气查询)publicclassWeatherPlugin{AgentTool(Get todays weather for a city.)publicStringgetWeather(Stringcity){returnBeijing: sunny, 22 C.;}}这个用法没变。变化在于现在AgentSkill和AgentSubAgent可以作为这个类的内部静态类跟AgentTool方法长在一起。实战代码四种能力一个类一次注册仓库ExampleReadme04PluginAnnotationTest里的WeatherPluginPlugin(idweather,nameWeather Plugin,descriptionWeather, air quality, travel advice, and trip cost estimation)publicclassWeatherPlugin{AgentTool(Get todays weather for a city.)publicStringgetWeather(Stringcity){returnBeijing: sunny, 22 C.;}AgentTool(Get todays air quality index (AQI) for a city.)publicStringgetAirQuality(Stringcity){returnBeijing: AQI 35, excellent air quality.;}AgentSkill(idtravel_advisor,descriptionGives outdoor-activity advice based on the current weather for a city. TRIGGER: Use when the user asks whether the weather is suitable for an outdoor activity.,systemPrompt You are an outdoor-activity advisor. 1. Call get_weather for the city the user mentions. 2. Based on the result, give a short, direct go/no-go recommendation. ,allowedTools{weather.get_weather}// 注意插件内的完整能力 id)publicstaticclassTravelAdvisorSkill{// 不需要 AgentTool 方法——Skill 不能拥有私有工具}AgentSubAgent(idexpense_estimator,descriptionEstimates the total cost of a business trip. TRIGGER: Use when the user asks for a trip budget or cost estimate.,modelaliyun:qwen-plus,systemPrompt You are a travel expense estimator. 1. Call estimate_trip_cost with the trip length and destination. 2. Report the total and a one-line breakdown. )publicstaticclassExpenseEstimatorSubAgent{AgentTool(Estimates total cost for a multi-day business trip.)publicStringestimateTripCost(intdays,Stringcity){return3-day Chengdu trip estimate: 3600 CNY total.;}}}注册只需要一行RegnexeAgentagentregnexeAgentBuilder.withDefaultModel(Vendor.ALIYUN,deepseek-v4-flash).withPlugin(newWeatherPlugin()).withEventListener(newConsoleEventListener()).build();一次withPlugin(new WeatherPlugin())市场里就出现了 4 个能力weather.get_weather、weather.get_air_quality、weather.travel_advisor、weather.expense_estimator全部挂在同一个pluginIdweather下面。两个容易踩的坑坑 1allowedTools要写完整 id。因为travel_advisor和get_weather现在共享同一个 pluginId工具的真实能力 id 是weather.get_weather不是裸的get_weather。这里写错Skill 内部就找不到这个工具表现上会是Skill 选中了但回答里没有真实数据。坑 2AgentSkill类里千万别写AgentTool方法。Skill 设计上就不持有私有工具写了也不会被采集——记住Skill 只能借这条铁律上一篇讲的。这个设计巧妙在哪AgentSubAgent内部复用的是和Plugin完全一样的扫描机制——AgentTool方法照样会被扫描出来只是扫描结果的去向不同长在Plugin类上的AgentTool→ 变成独立的 MCP_TOOL 能力谁都能调长在AgentSubAgent类上的AgentTool→ 变成这个 Sub-Agent 的私有ownTools外面看不到同一套扫描逻辑靠挂在哪个注解下面决定能力的可见性。不需要学两套 API——这正是 harness 设计上的一个好处底层只维护一套扫描/装配机制上层暴露多种语义。小结工具不多、不需要打包管理 → 直接withTool第 1 篇需要按业务模块打包、加标签、做版本管理 →Plugin 嵌套AgentSkill/AgentSubAgent一个类搞定一整套能力AgentSkill/AgentSubAgent也可以单独用不嵌套各自注册成独立的单能力插件下一篇会把视角拉高一层除了写代码注册插件还能怎么打包——纯代码构造、包扫描、文件系统目录三种方式一次讲完。 上一篇03. Sub-Agent自己的模型自己的工具 下一篇05. 插件打包的三种姿势 项目地址https://github.com/flower-trees/regnexe-agent