小蜜陪护机器人 - 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/任务规划专家.agentWorkerAgent专业 Agent执行具体任务bin/agentconfigs/agents/*.agentToolManager工具管理器加载和执行工具bin/agentconfigs/tools/*.toolScriptManagerJavaScript 引擎运行工具脚本src/scriptmanager.cppPluginC DLL 插件封装底层功能bin/agentconfigs/Plugins/*.dll1.3 完整调用流程用户说明天天气怎么样 │ ▼ 1. ASR 语音识别 → 明天天气怎么样 │ ▼ 2. TaskPlanner任务规划专家 └── 解析意图天气相关 → 路由到「天气专家」 │ ▼ 3. WorkerAgent天气专家 └── 根据指令决定使用「天气查询」工具 │ ▼ 4. ToolManager └── 加载并执行「天气查询.tool」的 JavaScript 脚本 │ ▼ 5. ScriptManager └── 运行脚本调用全局对象 weatherController.getTomorrowWeather() │ ▼ 6. PluginWeatherPlugin └── 返回明天的天气数据 │ ▼ 7. 结果返回 └── Tool → Agent → TaskPlanner → TTS → 用户二、扩展系统功能的步骤2.1 扩展流程概览要为系统增加新功能需要完成以下三个核心步骤步骤1: 创建专业 Agent 配置文件 │ ▼ 步骤2: 创建工具定义文件包含 JS 脚本 │ ▼ 步骤3: 在任务规划专家中注册新 Agent2.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需要更新两处路由表在路由规则中添加新意图到新 Agent 的映射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 工具脚本编写要点参数解析从params全局变量获取 JSON 格式的参数全局对象调用直接使用插件注册的全局对象返回格式必须返回 JSON 字符串包含success字段异常处理捕获并返回错误信息日志输出使用printlog(level, message)输出调试信息四、完整示例添加「笑话专家」Agent4.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 指令编写技巧明确角色定位让 Agent 清楚自己的职责范围定义决策规则告诉 Agent 何时调用工具、何时直接回答指定输出格式必须包含status字段tool_call或done提供示例帮助 LLM 理解期望的输出格式5.2 工具脚本编写技巧参数校验检查参数是否完整、格式是否正确错误处理捕获异常并返回明确的错误信息日志输出使用printlog()记录关键步骤便于调试返回格式统一始终返回包含success字段的 JSON脚本独立每个工具脚本应独立运行不依赖其他脚本5.3 调试方法查看日志检查bin/logs/目录下的日志文件脚本调试在工具脚本中使用printlog()输出调试信息测试工具通过修改 Agent 指令强制调用特定工具验证注册确认任务规划专家的路由表和 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 代码即可扩展系统功能创建 Agent 配置定义专业 Agent 的角色和行为创建工具脚本实现具体功能可调用插件或纯 JS 实现注册到规划专家更新路由表和 agent 数组这种设计使得系统具备高度的可扩展性和灵活性非程序员也能通过修改 JSON 和 JS 文件定制系统行为。相关文档插件开发指南.mdC 插件开发详解系统介绍.md系统整体架构介绍