鸿蒙Agent高级技能自定义开发:自定义意图服务/能力注册/Agent技能编排/服务插件开发实战

一、前言思考

1.1 Agent 的"能力"从哪里来

Agent 再聪明,也不能凭空执行任务------它需要"技能"(Skill):打车要调用打车服务、查快递要调用快递接口、控制家电要对接 IoT 协议。这些技能来自 开发者注册到 Agent 的能力插件

让 Agent 具备新能力 = 开发一个"技能插件"并注册:

复制代码
Agent 核心(规划/记忆/对话) 
   │
   ├── 内置技能: 闹钟/计算器/系统设置
   └── 第三方技能插件(开发者开发):
        ├── 打车插件 (开发者A)
        ├── 快递查询插件 (开发者B)
        └── 智能家居插件 (开发者C)

1.2 技能插件的价值

角色 价值
开发者 复用 Agent 的对话/上下文/分发能力,专注业务
用户 一个入口搞定所有服务,不用装一堆 App
平台 生态繁荣,Agent 能力无限扩展

二、底层原理

2.1 技能插件架构

复制代码
┌────────────────────────────────────────────────┐
│              Agent 技能运行时                    │
│  意图分发 → 技能匹配 → 参数校验 → 执行 → 结果回传 │
└──────────┬─────────────────────────┬───────────┘
           ▼                         ▼
┌──────────────────┐      ┌──────────────────┐
│  技能注册表       │      │  技能执行容器     │
│  skillId/能力描述 │      │  沙箱/生命周期    │
│  输入输出schema   │      │  超时/重试/回滚   │
└──────────────────┘      └──────────────────┘

技能三要素:

  • 能力描述(skill manifest):这个技能能做什么、需要什么输入;
  • 输入输出 Schema:参数校验的契约;
  • 执行实现:真正干活的代码。

2.2 技能匹配与分发

Agent 收到用户意图后,需要从技能注册表找到最合适的技能:

复制代码
意图: "帮我打车去机场"
  │
  ▼
技能匹配(基于能力描述语义匹配):
  ├─ 打车技能: 匹配度 0.95 ← 选中
  ├─ 快递技能: 匹配度 0.10
  └─ 家居技能: 匹配度 0.05

匹配基于能力描述的自然语言语义(开发者写清楚"我能做什么"),不是写死的 ID。

2.3 技能生命周期

复制代码
注册 → 启用 → 匹配命中 → 实例化 → 参数校验 → 执行 → 结果回传 → 释放
              │                                          │
              └──── 未命中: 保持休眠(低开销) ◀────────────┘
  • 技能容器是沙箱:插件不能访问 Agent 内核数据;
  • 执行有超时(默认 5s)和重试策略;
  • 执行失败必须回滚副作用(如下了单要能取消)。

三、实战落地

3.1 技能清单声明(Skill Manifest)

json 复制代码
{
  "skillId": "demo.express.query",
  "name": "快递查询",
  "description": "查询快递物流信息,支持输入快递单号或手机号尾号,返回最新物流状态和预计到达时间",
  "version": "1.0.0",
  "inputSchema": {
    "type": "object",
    "required": ["trackingNo"],
    "properties": {
      "trackingNo": { "type": "string", "description": "快递单号" },
      "carrier": { "type": "string", "enum": ["sf", "yt", "zt"], "description": "快递公司(可选)" }
    }
  },
  "outputSchema": {
    "type": "object",
    "properties": {
      "status": { "type": "string" },
      "latest": { "type": "string" },
      "eta": { "type": "string" }
    }
  }
}

能力描述写得越清楚,Agent 匹配越准------这是技能开发最重要的"文案工程"。

3.2 技能实现(执行器)

typescript 复制代码
import { agentSkill } from '@kit.AiKit';

@agentSkill.Skill({
  skillId: 'demo.express.query',
  version: '1.0.0'
})
export class ExpressQuerySkill implements agentSkill.SkillHandler {

  // 参数校验(框架调用前执行)
  validate(params: Record<string, string>): agentSkill.ValidationResult {
    if (!params.trackingNo || params.trackingNo.length < 8) {
      return { ok: false, message: '请输入有效的快递单号' };
    }
    return { ok: true };
  }

  // 执行(核心逻辑)
  async execute(params: Record<string, string>, ctx: agentSkill.SkillContext): Promise<agentSkill.SkillResult> {
    ctx.log('开始查询快递: ' + params.trackingNo);

    // 调用快递 API(可离线规则优先, 在线 API 兜底)
    let result = tryOfflineParse(params.trackingNo);
    if (!result) {
      result = await queryExpressApi(params.trackingNo, params.carrier);
    }

    ctx.remember({ lastExpress: params.trackingNo });   // 记忆, 供多轮使用

    return {
      status: result.status,
      latest: result.latest,
      eta: result.eta,
      speak: '您的快递正在' + result.status + ',预计 ' + result.eta + ' 送达'
    };
  }

  // 失败兜底
  async onError(err: Error, ctx: agentSkill.SkillContext): Promise<agentSkill.SkillResult> {
    ctx.log('查询失败: ' + err.message);
    return { status: 'error', latest: '网络异常', eta: '请稍后重试', speak: '暂时查不到物流信息,请稍后再试' };
  }
}

3.3 技能编排(多技能组合)

一个复杂任务可能涉及多个技能,Agent 负责编排:

复制代码
意图: "查快递到了没, 到了告诉我取件码"
  ├─ 技能1(快递查询) → 物流状态
  └─ 若"已签收" → 技能2(取件码查询) → 通知用户
typescript 复制代码
// Agent 侧编排逻辑(由 Agent 框架执行, 技能作者无需关心)
// 但技能作者可以通过"建议编排"声明组合能力
@agentSkill.Skill({
  skillId: 'demo.express.full',
  description: '快递全流程: 查询 + 签收后自动提醒取件码',
  composeOf: ['demo.express.query', 'demo.pickup.code']
})
export class ExpressFullSkill { /* 组合技能 */ }

3.4 技能调试与热更新

typescript 复制代码
// 开发期: 本地模拟 Agent 调用
const sim = await agentSkill.mockAgent({
  skills: ['demo.express.query']
});
const res = await sim.chat('我的顺丰快递 8888888888 到哪了?');
console.log(res.reply);

// 发布后: 技能版本热更新
await agentSkill.updateSkill({
  skillId: 'demo.express.query',
  version: '1.1.0',      // 新增中通支持
  rollout: { percent: 20 }  // 20% 流量灰度
});

四、性能排查与优化

问题 表现 优化手段
匹配错 意图分到错误技能 能力描述更具体、加示例、负样本
执行超时 技能 5s 无响应 并行请求、缓存、降级规则
参数误填 校验不过 schema 加描述、Agent 先澄清
记忆污染 多轮上下文混乱 命名空间隔离、过期清理
插件崩溃 技能异常影响 Agent 沙箱隔离、异常兜底 onError

4.1 技能匹配优化

typescript 复制代码
// 能力描述 + 示例查询 双重匹配
const skillDoc = skill.manifest.description + '\n示例: ' + skill.manifest.examples.join('; ');
const score = semanticMatch(userIntent, skillDoc);

4.2 执行降级链

复制代码
API 查询失败 → 本地规则解析(部分快递支持) → 返回"稍后重试" → 记录失败供改进

4.3 记忆命名空间

typescript 复制代码
// 每个技能的记忆独立命名空间, 避免互相覆盖
ctx.remember(`express.${params.trackingNo}`, result);
// 上下文查询
ctx.recall('express.8888888888');

五、总结

  1. 技能插件是 Agent 能力的来源:能力描述 + Schema + 执行器三件套,让 Agent 学会新任务。
  2. 能力描述是"文案工程":写得越清楚,语义匹配越准------这决定了技能是否被正确调用。
  3. 编排让技能 1+1>2:复杂任务由 Agent 组合多个技能,技能作者只需聚焦单一能力。
  4. 工程化四要素:沙箱隔离、超时重试、失败兜底、灰度热更新。

一句话记住:描述清楚好匹配,Schema 严谨防误填,兜底到位不崩会话,沙箱隔离保安全。


🚀 演示功能优化(随项目同步更新)

本文对应的 ArkTS 演示页面已随项目整体优化,主要改进:

  1. 独立主题风格:靛蓝深色 · 斜切角卡片荧光强调,与其余章节演示页明显区分,不再千篇一律。
  2. 步骤回放动画:点击演示按钮后,结果行按 260~320ms/步 逐步展示,模拟真实推理过程。
  3. 运行态保护:演示过程中按钮置灰防重复触发,页面退出自动清理定时器。
  4. 结果摘要:演示结束后自动给出「一句话结论」,并 Toast 提示完成。
  5. AI 对话演示:新增 AiChatDemo(根目录 main.py 的 ArkTS 移植),真实 SSE 流式大模型请求,首页「★ AI Chat 流式对话演示」可进入。

对应页面:entry/src/main/ets/pages/AgentSkillDemo.ets


🧪 演示优化:真实 AI 推理接入(v3)

本演示页顶部新增 AI 技能编排师主卡,点击即真实调用云端大模型(SSE 流式),不再是纯模拟回放:

  • 请求链路utils/AiClient.ets(ArkTS 封装 OpenAI 兼容接口)→ POST https://api-ai.gitcode.com/v1/chat/completions,模型 deepseek-ai/DeepSeek-V4-Flash,流式 stream: true
  • 演示场景:技能定义 / 多技能编排 / 冲突仲裁 ------ 每个场景绑定不同 Agent 编排专家 Prompt,返回内容各有差异
  • 交互体验:进入页面自动触发一次真实推理;点场景标签切换并重新请求;按钮手动触发;输出区打字机流式展示
  • 真实标识 :卡片右上角 LIVE 徽标 + 端点/模型名水印,保证"所见即所调"
相关推荐
AI 小老六6 小时前
Agent Runtime 如何用 Session、Memory、User Profile 和 Skill 实现外部学习
服务器·人工智能·学习·ai·架构·自动化
又折桃枝换酒钱6 小时前
CycleChart:一个统一的基于一致性学习的双向图表理解与生成框架(翻译与解读)
人工智能·深度学习·学习
2501_915106327 小时前
iOS 证书类型及作用说明 账号证书与签名配置的完整解读
android·ios·小程序·https·uni-app·iphone·webview
九皇叔叔7 小时前
RHEL9 安装 MySQL 8.4.11.LTS 版本
android·mysql·adb
海兰7 小时前
【数据库】tdsql(MySQL )的事务隔离级别
android·数据库·mysql
什仙7 小时前
Maxwell:提取实体表面,用于扫掠。
笔记·学习·ansys·maxwell
小僧景贤7 小时前
嵌入式C语言 第十一篇:成长路线|嵌入式C工程师完整进阶学习路径(从零到工程级落地|含周期+实战项目)
c语言·开发语言·学习
哆啦A梦z7 小时前
Android BLE 实战:从小米手环 7 踩坑到完整连接框架
android