当前位置: 首页 > news >正文

小蜜陪护机器人 - Agent扩展开发指南

Agent扩展开发指南

概述

小蜜陪护机器人采用多 Agent 协作架构,通过任务规划专家将用户意图路由到专业 Agent 执行。本文详细介绍如何通过增加工作 Agent 和相应的工具来扩展系统功能,无需修改核心 C++ 代码,仅需配置 JSON 文件和编写 JavaScript 脚本。

与插件开发指南的区别

  • 插件开发指南:侧重 C++ DLL 插件开发,封装底层功能
  • Agent 扩展指南:侧重 JSON/JS 配置层面,将已有功能暴露给 Agent 使用

一、Agent 架构简述

1.1 整体架构

系统采用分层协作架构,数据流向如下:

用户输入(语音/文字) │ ▼ TaskPlanner(任务规划专家)—— 解析意图,生成执行计划 │ └──→ WorkerAgent(专业 Agent)—— 执行具体任务 │ └──→ ToolManager(工具管理器)—— 加载和执行工具脚本 │ └──→ ScriptManager(脚本管理器)—— 运行 JavaScript │ └──→ Plugin(插件)—— 底层功能实现

1.2 核心组件职责

组件职责文件位置
TaskPlanner任务规划专家,负责意图解析和路由bin/agentconfigs/agents/任务规划专家.agent
WorkerAgent专业 Agent,执行具体任务bin/agentconfigs/agents/*.agent
ToolManager工具管理器,加载和执行工具bin/agentconfigs/tools/*.tool
ScriptManagerJavaScript 引擎,运行工具脚本src/scriptmanager.cpp
PluginC++ DLL 插件,封装底层功能bin/agentconfigs/Plugins/*.dll

1.3 完整调用流程

用户说:"明天天气怎么样?" │ ▼ 1. ASR 语音识别 → "明天天气怎么样?" │ ▼ 2. TaskPlanner(任务规划专家) └── 解析意图:天气相关 → 路由到「天气专家」 │ ▼ 3. WorkerAgent(天气专家) └── 根据指令,决定使用「天气查询」工具 │ ▼ 4. ToolManager └── 加载并执行「天气查询.tool」的 JavaScript 脚本 │ ▼ 5. ScriptManager └── 运行脚本,调用全局对象 weatherController.getTomorrowWeather() │ ▼ 6. Plugin(WeatherPlugin) └── 返回明天的天气数据 │ ▼ 7. 结果返回 └── Tool → Agent → TaskPlanner → TTS → 用户

二、扩展系统功能的步骤

2.1 扩展流程概览

要为系统增加新功能,需要完成以下三个核心步骤:

步骤1: 创建专业 Agent 配置文件 │ ▼ 步骤2: 创建工具定义文件(包含 JS 脚本) │ ▼ 步骤3: 在任务规划专家中注册新 Agent

2.2 步骤详解

步骤1:创建专业 Agent 配置文件

bin/agentconfigs/agents/目录下创建新文件,命名为{Agent名称}.agent,格式如下:

{ "name": "Agent名称", "instructions": "Agent的角色定义和行为指令(System Prompt)", "tools": ["工具1", "工具2"] }

字段说明:

字段类型说明
namestringAgent 名称,用于路由和识别
instructionsstringSystem Prompt,定义 Agent 的角色、决策规则、输出格式等
toolsarrayAgent 可以使用的工具列表
步骤2:创建工具定义文件

bin/agentconfigs/tools/目录下创建新文件,命名为{工具名称}.tool,格式如下:

{ "name": "工具名称", "description": "工具功能描述(供 LLM 理解何时调用)", "params": [ { "type": "string/number", "name": "参数名", "description": "参数说明", "required": true } ], "auto_verified": true, "script_content": "JavaScript 脚本内容" }

字段说明:

字段类型说明
namestring工具名称(中文,Agent 可见)
descriptionstring工具功能描述,帮助 LLM 判断何时调用
paramsarray参数列表,定义输入参数
auto_verifiedboolean是否自动验证(true = 工具结果无需模型再次验证)
script_contentstringJavaScript 脚本,实现工具逻辑
步骤3:在任务规划专家中注册

修改bin/agentconfigs/agents/任务规划专家.agent,需要更新两处:

  1. 路由表:在路由规则中添加新意图到新 Agent 的映射
  2. agent 数组:将新 Agent 名称添加到agent数组中

三、工具调用插件的机制

3.1 脚本引擎与全局对象

ScriptManager 维护一个单例 JavaScript 引擎,插件加载时会将其 QObject 实例注册为全局对象:

// PluginManager 注册流程 if (plugin->scriptObject()) { QString objName = plugin->scriptObjectName(); m_scriptManager->registerGlobalObject(objName, plugin->scriptObject()); }

3.2 已注册的全局对象

全局对象名插件功能
weatherControllerWeatherPlugin天气查询
taskSchedulerTaskSchedulerPlugin定时任务
musicPlayerMusicPlayerPlugin音乐播放
radioTvPlayerRadioTvPlayerPlugin广播/电视播放
volumeControllerVolumeControlPlugin音量控制
networkInfoNetworkInfoPlugin网络信息查询

3.3 工具脚本调用插件的方式

工具脚本中直接调用全局对象的Q_INVOKABLE方法:

// 天气查询工具脚本示例 function 天气查询() { var obj = JSON.parse(params); var queryDate = obj.查询日期 || 'today'; // 调用插件暴露的全局对象 var result = weatherController.getTodayWeather(); // 格式化结果 result = JSON.parse(JSON.stringify(result)); return JSON.stringify({ success: true, result: result }); } 天气查询();

3.4 工具脚本编写要点

  1. 参数解析:从params全局变量获取 JSON 格式的参数
  2. 全局对象调用:直接使用插件注册的全局对象
  3. 返回格式:必须返回 JSON 字符串,包含success字段
  4. 异常处理:捕获并返回错误信息
  5. 日志输出:使用printlog(level, message)输出调试信息

四、完整示例:添加「笑话专家」Agent

4.1 功能需求

创建一个「笑话专家」Agent,能够:

  • 讲一个随机笑话
  • 根据主题讲笑话(如动物、职场、校园等)

4.2 步骤1:创建笑话专家 Agent 配置

创建文件bin/agentconfigs/agents/笑话专家.agent

{ "name": "笑话专家", "instructions": "你是一个幽默风趣的笑话专家,负责给用户讲笑话。\n\n## 决策规则\n1. 用户说「讲个笑话」或类似请求 → 调用讲笑话工具\n2. 用户指定主题 → 调用工具并传入主题参数\n3. 用户要求讲多个笑话 → 多次调用工具\n4. 用户只是闲聊 → 直接回应,不调用工具\n\n## 输出格式\n工具调用:{\"status\":\"tool_call\",\"tool_name\":\"讲笑话\",\"arguments\":{\"主题\":\"主题名称\"}}\n最终答案:{\"status\":\"done\",\"result\":\"笑话内容\"}\n\n## 回复风格\n- 笑话讲完后,可以加一句俏皮话或表情符号\n- 如果用户不笑,可以换一个继续讲\n- 保持轻松幽默的语气", "tools": [ "讲笑话" ] }

4.3 步骤2:创建讲笑话工具定义

创建文件bin/agentconfigs/tools/讲笑话.tool

{ "name": "讲笑话", "description": "讲一个笑话,可以指定主题:动物、职场、校园、夫妻、冷笑话", "params": [ { "type": "string", "name": "主题", "description": "笑话主题:动物、职场、校园、夫妻、冷笑话,不指定则随机", "required": false } ], "auto_verified": true, "script_content": "function 讲笑话() {\n var obj;\n try { obj = JSON.parse(params); } catch(e) { return JSON.stringify({success: false, result: '参数格式错误'}); }\n var topic = obj.主题 || '';\n \n var jokes = {\n '动物': [\n '为什么企鹅只有肚子是白的?因为手太短,洗澡只能洗到肚子!',\n '大象和蚂蚁结婚,第二天大象死了。蚂蚁哭着说:这辈子再也不干这么累的活了!',\n '乌龟和兔子赛跑,兔子中途睡着了。等它醒来,乌龟已经到终点了,兔子说:早知道我就不戴墨镜了!'\n ],\n '职场': [\n '老板问员工:你觉得你值多少钱?员工说:我觉得我值年薪100万。老板:那我给你年薪50万,你干两份活。',\n '程序员的老婆让他去买酱油,他回来说:超市里没有酱油接口,我无法完成购买请求。',\n 'HR问面试者:你最大的缺点是什么?面试者:诚实。HR:我不觉得这是缺点。面试者:我不在乎你怎么想。'\n ],\n '校园': [\n '老师:小明,你知道为什么闪电总是比雷声快吗?小明:因为眼睛长在耳朵前面!',\n '学生问老师:为什么要学数学?老师:因为数学能帮你在菜市场不被坑。学生:可是我可以用计算器啊!',\n '考试时,小明偷看同桌的答案。老师走过来问:你在看什么?小明:我在看他的答案是不是和我的一样。'\n ],\n '夫妻': [\n '老婆:你知道我为什么嫁给你吗?老公:因为我长得帅?老婆:因为你老实。老公:那现在呢?老婆:因为你傻。',\n '老公回家晚了,老婆问:你去哪了?老公:加班。老婆:我刚才给你们公司打电话,他们说你早就走了。老公:那是因为我加班到一半太累了,去隔壁公司休息了一下。',\n '老婆:如果你中了五百万,你会怎么样?老公:我会分你一半。老婆:那如果你中了一千万呢?老公:那我就分你五百万。'\n ],\n '冷笑话': [\n '为什么海象总是很开心?因为它有一颗海象的心!',\n '什么动物最容易摔倒?狐狸,因为它太狡猾(脚滑)了!',\n '为什么苹果手机不会感冒?因为它有iOS(爱奥西斯)!'\n ],\n 'default': [\n '一位程序员走进酒吧,要了一杯酒。服务员问:需要加冰吗?程序员说:不用了,我自带了。',\n '医生问病人:你哪里不舒服?病人说:我睡不着觉。医生:为什么?病人:因为我是程序员,我的生物钟是夜猫子模式。',\n '甲:你知道为什么程序员不喜欢过情人节吗?乙:为什么?甲:因为他们分不清0和1哪个是真爱。',\n '老师让同学们用「如果」造句。小明:如果我有一百万,我就买个大房子。小红:如果我有一百万,我就买好多好吃的。小刚:如果这是个问题,我就回答它。'\n ]\n };\n \n var pool = jokes[topic] || jokes['default'];\n var joke = pool[Math.floor(Math.random() * pool.length)];\n \n return JSON.stringify({\n success: true,\n topic: topic || '随机',\n result: joke\n });\n}\n讲笑话();" }

4.4 步骤3:在任务规划专家中注册

修改bin/agentconfigs/agents/任务规划专家.agent

更新路由表(在路由规则中添加):

"路由表": "数学/计算/算术 → 数学专家\n时间/日期/星期/几号 → 时间专家\n定时/提醒/闹钟/倒计时 → 定时任务专家\n网络/IP/子网掩码/网关 → 网络专家\n广播/电视/收音机/电台/电视台/频道 → 广播电视播放专家\n音乐/歌曲/唱歌/听歌/切歌 → 音乐播放专家\n音量/声音/静音/TTS音量 → 音量控制专家\n天气/下雨/刮风/温度/气温/湿度 → 天气专家\n笑话/幽默/搞笑/段子 → 笑话专家\n其他/聊天/问候/不确定 → 贴心聊天助手"

更新 agent 数组(添加「笑话专家」):

"agent": ["数学专家","贴心聊天助手","时间专家","定时任务专家","网络专家","广播电视播放专家","音乐播放专家","音量控制专家","天气专家","笑话专家"]

4.5 预期交互效果

用户:讲个笑话 │ ▼ 任务规划专家 → 识别意图:笑话/幽默 → 路由到「笑话专家」 │ ▼ 笑话专家 → 决定调用「讲笑话」工具 │ ▼ 工具脚本 → 返回随机笑话:"为什么程序员不喜欢过情人节吗?因为他们分不清0和1哪个是真爱。" │ ▼ 笑话专家 → 整理回答:"好的,给你讲一个:为什么程序员不喜欢过情人节吗?因为他们分不清0和1哪个是真爱。😂" │ ▼ TTS → 语音输出

五、扩展技巧与最佳实践

5.1 Agent 指令编写技巧

  1. 明确角色定位:让 Agent 清楚自己的职责范围
  2. 定义决策规则:告诉 Agent 何时调用工具、何时直接回答
  3. 指定输出格式:必须包含status字段(tool_calldone
  4. 提供示例:帮助 LLM 理解期望的输出格式

5.2 工具脚本编写技巧

  1. 参数校验:检查参数是否完整、格式是否正确
  2. 错误处理:捕获异常并返回明确的错误信息
  3. 日志输出:使用printlog()记录关键步骤,便于调试
  4. 返回格式统一:始终返回包含success字段的 JSON
  5. 脚本独立:每个工具脚本应独立运行,不依赖其他脚本

5.3 调试方法

  1. 查看日志:检查bin/logs/目录下的日志文件
  2. 脚本调试:在工具脚本中使用printlog()输出调试信息
  3. 测试工具:通过修改 Agent 指令,强制调用特定工具
  4. 验证注册:确认任务规划专家的路由表和 agent 数组已正确更新

5.4 常见问题

问题原因解决方案
Agent 未被调用任务规划专家未注册该 Agent检查agent数组和路由表
工具未被调用Agent 指令未正确定义调用规则检查instructions中的决策规则
脚本执行失败JavaScript 语法错误检查script_content的语法
参数解析失败参数格式不正确确保传入的参数是合法 JSON
全局对象未定义插件未正确加载检查插件 DLL 是否在正确目录

六、无插件场景:纯脚本工具

并非所有工具都需要插件支持。如果功能可以完全通过 JavaScript 实现(如计算、数据处理、本地文件操作等),可以直接编写纯脚本工具,无需开发 C++ 插件。

6.1 纯脚本工具示例

计算器工具(无需插件,纯 JavaScript 实现):

{ "name": "计算器", "description": "执行基本数学运算:加法、减法、乘法、除法", "params": [ { "type": "string", "name": "操作", "description": "要执行的数学操作,可选值:加、减、乘、除", "required": true }, { "type": "number", "name": "a", "description": "第一个操作数", "required": true }, { "type": "number", "name": "b", "description": "第二个操作数", "required": true } ], "auto_verified": true, "script_content": "function 计算器() { var obj = JSON.parse(params); var a = parseFloat(obj.a); var b = parseFloat(obj.b); var result; switch(obj.操作) { case '加': result = a + b; break; case '减': result = a - b; break; case '乘': result = a * b; break; case '除': if(b !== 0) { result = a / b; } else { return JSON.stringify({success: false, result: '除数不能为零'}); } break; default: return JSON.stringify({success: false, result: '不支持的操作'}); } return JSON.stringify({success: true, result: String(result)}); } 计算器();" }

6.2 何时需要开发插件

场景是否需要插件说明
网络请求需要JavaScript 无法直接发起 HTTP 请求
系统调用需要JavaScript 无法直接调用系统 API
文件操作需要JavaScript 文件操作能力有限
数据计算不需要纯 JavaScript 即可实现
数据处理不需要纯 JavaScript 即可实现
逻辑判断不需要纯 JavaScript 即可实现

总结

通过Agent + Tool的配置方式,无需修改核心 C++ 代码即可扩展系统功能:

  1. 创建 Agent 配置:定义专业 Agent 的角色和行为
  2. 创建工具脚本:实现具体功能,可调用插件或纯 JS 实现
  3. 注册到规划专家:更新路由表和 agent 数组

这种设计使得系统具备高度的可扩展性和灵活性,非程序员也能通过修改 JSON 和 JS 文件定制系统行为。


相关文档

  • 插件开发指南.md:C++ 插件开发详解
  • 系统介绍.md:系统整体架构介绍
http://www.jsqmd.com/news/1228995/

相关文章:

  • 天气/气象数据批量采集——从多源API到智能可视化分析平台
  • 学历普通也能拿 offer,普通院校学生的春招突围策略
  • SpinKit-ObjC完全指南:UIKit中15种加载动画的终极实现方案
  • 【小程序课程设计/毕业设计】基于 SpringBoot 的身心健康生活服务小程序 健康数据统计与生活习惯养成小程序 大众健康资讯推送与自我管理小程序【附源码、数据库、万字文档】
  • 如何快速配置KK_Plugins:3个关键步骤详解
  • TI C2000 DCSM安全模块配置实战:从原理到代码保护
  • 82M参数Kokoro语音合成:如何在Python和JavaScript中部署50+种多语言语音
  • 2026甄选安阳名包名表奢侈品回收江诗丹顿卡地亚积家朗格伯爵普拉达罗意威核心门店实力盘点 - 谊识预商务
  • C语言的分支循环语句
  • ARM公版架构市场现状与技术挑战分析
  • 加密货币钱包安全指南:硬件与热钱包选择
  • AI作词工具推荐:7款歌词生成器的真实使用感受
  • 如何快速上手Learn-to-Cluster:5分钟完成人脸聚类环境搭建
  • mysql8免安装版安装配置教程(附带完整文件)
  • Hermes Agent安全架构与多Agent系统稳定性实践
  • 5分钟掌握Bonsai-8B-GGUF:1位量化大模型快速部署终极指南
  • 深入理解 TCP、TLS 与 HTTPS 抓包原理
  • 北京华恒智信破解物流企业人才断层任职资格案例
  • 隐私计算终极指南:如何用SecretFlow构建安全数据智能系统
  • 如何快速集成SpinKit-ObjC:iOS开发者必备的加载动画库
  • 为什么你的AI发帖总被判定为Bot?——基于17万条审核日志的特征工程反识别模型(附可复现Python脚本)
  • 智能新闻播报系统:架构设计与实现
  • 论文省心了!2026年刚需首选的专业降AI率平台
  • 练武术也能考大学!2026招生|体育单招+参军入伍+教练就业 - 学途指南
  • CKEditor 5架构深度解析:构建现代化富文本编辑器的实战指南
  • ELK.js:解决复杂图表自动布局问题的完整JavaScript解决方案
  • 市监总局联合中检CCIC:2026福州欧米茄卡地亚回收避坑4条新规 - 商业每日快报
  • AI和声落地失败的终极原因:不是模型问题,而是你没做这4层听觉校验(含ABX盲测模板)
  • YimMenu:如何打造你的GTA5游戏安全防护与体验增强系统
  • 2026甄选大理名包名表奢侈品回收沛纳海宝珀伯爵劳力士江诗丹顿爱马仕罗意威门店实力排行公布 - 谊识预商务