HarmonyOS智能体端插件开发教程

一、概述

端插件是 HarmonyOS 小艺智能体生态的核心能力,允许用户通过自然语言对话或语音直达 App 核心功能,实现"所说即所得"的 AI 原生交互体验。

本教程介绍端插件的两种实现方式:

类型 说明 适用场景
前台执行 通过 AppLink 拉起应用,参数附在 URL 或 Want 中 页面跳转、触发操作
后台执行 通过 InsightIntentExecutor 执行,支持返回数据 查询统计、后台任务

二、前置准备

2.1 创建智能体

  1. 登录 小艺开放平台
  2. 创建智能体,获取 agentId

首先登陆小艺开放平台后点击如图红框所示按钮

image-20260720214152079

选择单Agent模式

image-20260720214319003

鼠标滚轮滑动根据步骤提示创建智能体,后续步骤这里不多赘述

image-20260720214401673

智能体ID在这里获取

image-20260720223842492

2.2 创建端插件

这部分可以参考官方的教程:
创建端插件-端插件-开发插件-意图框架&MCP-小艺开放平台 - 华为HarmonyOS开发者

2.3 应用内嵌入智能体入口

官方相关文档: 通过Function组件拉起智能体-Agent Framework Kit(智能体框架服务)-AI - 华为HarmonyOS开发者

使用 FunctionComponent 在应用内放置智能体按钮用于应用内唤起智能体:

import { FunctionComponent, FunctionController } from '@kit.AgentFrameworkKit';
import { BusinessError } from '@kit.BasicServicesKit';

@Component
export struct AgentButton {
  private controller: FunctionController = new FunctionController();
  private agentId: string = '你的agentId';

  build() {
    FunctionComponent({
      agentId: this.agentId,
      onError: (err: BusinessError) => {
        console.error(`智能体错误: ${err.message}`);
      },
      options: {
        isShowShadow: true
      },
      controller: this.controller
    })
  }
}

三、AppLink 模式端插件

3.1 云端配置

首先需要你完成端插件的配置,这部分可以看官方的文档:

端插件配置-端插件-开发插件-意图框架&MCP-小艺开放平台 - 华为HarmonyOS开发者

这里我们举一个简单的例子: 通过端插件实现用自然语言操控页面切换
在小艺开放平台配置端插件工具:

字段 说明
工具名 自定义,如 ChangePage
实现方式 AppLink
长链接 https://yourdomain.com/page?
输入参数 声明参数名、类型、描述

输入参数部分这里在做一些说明,为了实现页面切换的功能我们需要一个输入参数让大模型来填入要跳转的页面

举个例子这个参数叫PageNum,类型我们选择整型(Integer),参数描述为页面编号,1=首页 2=上传 3=历史 4=设置,参数描述的作用是告诉大模型应该怎么填写这个参数

image-20260720215908417

注意,在AppLink模式下输入参数一定要配置参数映射类型为URL,否则会导致AppLink链接没有加上输入参数

image-20260720221915315

比如: 用户说帮我切换到上传页面,大模型接收到用户这句话会先去找哪个端插件适合处理用户的需求。那么大模型是怎么知道这个端插件合适的呢?这就要说到我们配置端插件的时候添加的工具描述,找到这个工具之后大模型会去读我们配置的输入参数以及输入参数的描述,然后根据用户提出的需求结合我们填写的参数描述来决定参数填入的数值

image-20260720220220794

由此可知,大模型接收到用户要跳转到上传页面的意图之后会给输入参数PageNum填入2,然后通过AppLink的形式传给我们的APP,此时我们对AppLink做一个读取并处理就可以实现我们想要的自然语言控制页面切换,关于端侧如何实现请接着往后看

**PS:**本次实验使用AppLink,前台执行模式还支持标准实现与DeepLink,具体可以参考官方文档:端插件配置-端插件-开发插件-意图框架&MCP-小艺开放平台 - 华为HarmonyOS开发者

3.2 端侧实现

大模型处理完请求后返回的AppLink链接形式是这样的:

https://yourdomain.com/page?PageNum=1

EntryAbilityonNewWant / onCreate 中处理 AppLink 请求:

private async handleAppLinking(want: Want): Promise<void> {
  const uri = want?.uri;
  if (!uri) return;

  console.info(`收到 AppLinking 请求: ${uri}`);

  // 路由分发
  if (uri.startsWith('https://yourdomain.com/page')) {
    this.handlePageChange(uri, want);
    return;
  }
  // ... 其他路由
}

PS:我们在端插件配置的时候填入的长链接为什么末尾要带上/page ?这个是为了区分识别不同工具传输的AppLink链接,当我们要实现的功能多了是不是就要更多的端插件工具,比如我要实现一句话上传图片,这个时候填入的链接就可以是

https://yourdomain.com/upload

主要是用来区分不同工具的链接来防止功能冲突的,大家可以按自己的心情来命名

3.3 参数解析(兼容 URL 和 Want)

private handlePageChange(uri: string, want: Want): void {
  let pageNum: number = 0;

  // 方式一:从 URL 查询参数取
  try {
    const urlObject = url.URL.parseURL(uri);
    const pageStr = urlObject.params.get('PageNum');
    if (pageStr) pageNum = parseInt(pageStr, 10);
  } catch (err) {
    console.warn(`URL 解析异常: ${JSON.stringify(err)}`);
  }

  // 方式二:URL 没取到,从 want.parameters 取
  if (!pageNum && want.parameters) {
    const raw = want.parameters.PageNum;
    if (typeof raw === 'number') pageNum = raw;
    else if (typeof raw === 'string') pageNum = parseInt(raw, 10);
  }

  // 执行业务逻辑
  // ...
}

3.4 UI 联动

通过 AppStorage 写入状态,页面用 @StorageLink + @Watch 响应:

// StateKeys 中定义
export class StateKeys {
  static readonly INTENT_CHANGE_PAGE_INDEX: string = 'intentChangePageIndex';
  static readonly INTENT_CHANGE_PAGE_TRIGGER: string = 'intentChangePageTrigger';
}

// EntryAbility 中写入
AppStorage.setOrCreate<number>(StateKeys.INTENT_CHANGE_PAGE_INDEX, tabIndex);
const trigger = AppStorage.get<number>(StateKeys.INTENT_CHANGE_PAGE_TRIGGER) ?? 0;
AppStorage.setOrCreate<number>(StateKeys.INTENT_CHANGE_PAGE_TRIGGER, trigger + 1);

// 页面中监听
@StorageLink(StateKeys.INTENT_CHANGE_PAGE_INDEX) intentPageIndex: number = 0;
@StorageLink(StateKeys.INTENT_CHANGE_PAGE_TRIGGER) @Watch('onIntentChangePage') intentPageTrigger: number = 0;

private onIntentChangePage(): void {
  if (this.intentPageTrigger > 0) {
    this.firstLevelIndex = this.intentPageIndex;
  }
}

技巧:用自增触发器而非直接监听索引值,可以解决"连续切换到同一 Tab 不触发"的问题。

四、后台模式端插件

后台模式就只能用标准模式来实现了,这种场景适合不拉起UI来实现一些业务逻辑,比如我最近上传了什么图片之类的,下面我们就举一个例子:实现端插件查询对象存储有多少张图片
官方相关文档:插件工具的对应代码实现-端侧应用实现-端插件-开发插件-意图框架&MCP-小艺开放平台 - 华为HarmonyOS开发者

4.1 配置文件

创建 resources/base/profile/insight_intent.json

{
  "insightIntents": [
    {
      "intentName": "QueryStats",
      "domain": "",
      "intentVersion": "1.0.0",
      "srcEntry": "./ets/entryability/InsightIntentExecutorImpl.ets",
      "uiAbility": {
        "ability": "EntryAbility",
        "executeMode": ["background"]
      }
    }
  ]
}

4.2 module.json5 绑定

EntryAbility 配置中添加 metadata:

{
  "name": "EntryAbility",
  // ...
  "metadata": [
    {
      "name": "ohos.insight_intent",
      "resource": "$profile:insight_intent"
    }
  ]
}

4.3 实现 InsightIntentExecutor

import { insightIntent, InsightIntentExecutor } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';

const TAG = 'InsightIntentExecutorImpl';
const DOMAIN = 0x0001;

class Constants {
  public static readonly INTENT_QUERY_STATS: string = 'QueryStats';
}

export default class InsightIntentExecutorImpl extends InsightIntentExecutor {
  async onExecuteInUIAbilityBackgroundMode(intentName: string,
    intentParam: Record<string, Object>): Promise<insightIntent.ExecuteResult> {
    hilog.info(DOMAIN, TAG, `name: ${intentName}, param: ${JSON.stringify(intentParam)}`);
    switch (intentName) {
      case Constants.INTENT_QUERY_STATS:
        return this.queryStats(intentParam);
      default:
        break;
    }
    return { code: -1, result: { message: 'unknown intent' } };
  }

  private async queryStats(param: Record<string, Object>): Promise<insightIntent.ExecuteResult> {
    try {
      // 业务逻辑
      return {
        code: 0,
        result: {
          totalCount: 115,
          provider: '腾讯云COS'
        }
      };
    } catch (err) {
      return {
        code: -1,
        result: { message: `查询失败: ${(err as Error).message}` }
      };
    }
  }
}

实现逻辑

  1. 继承 InsightIntentExecutor - 系统在后台触发端插件时会调用这个类
  2. onExecuteInUIAbilityBackgroundMode - 后台执行的入口,参数 intentName 是工具名,intentParam 是大模型填入的参数
  3. switch 分发 - 按工具名路由到对应的处理方法
  4. queryStats - 执行实际业务逻辑,返回 ExecuteResult
  5. 返回格式 - code: 0 成功 + result 数据给智能体播报;code: -1 失败 + message 错误信息

智能体拿到返回数据后会根据 result 里的字段生成回复

4.4 返回参数配置

输出参数:返回数据必须包含 code 和 result 字段,code 用于表示业务状态码, result 用于承载具体业务数据。

这个是配置示例
image-20260720223041260

五、两种模式对比

前台执行 后台执行
配置文件 不需要 insight_intent.json
端侧入口 EntryAbility.onNewWant InsightIntentExecutor
参数传递 URL / Want intentParam
返回数据 不支持 ExecuteResult
执行模式 前台(拉起应用) 前台 / 后台
需上架 AGC
适用场景 触发操作、页面跳转 查询、后台任务

六、调试技巧

6.1 工具模拟集

在小艺开放平台网页调试时,端插件无法在网页上执行。配置工具模拟集(Mock 返回数据)即可在网页调试台上测试智能体对话流程:

{
  "code": 0,
  "result": {
    "totalCount": 115,
    "provider": "腾讯云COS"
  }
}

6.2 常见问题

问题 原因 解决
AppLink 参数没传过来 没有配置参数映射类型 参数映射类型配置为URL
意图框架提示"未安装" 可能是云端配置意图版本号与本地不一致 检查两端配置

七、总结

端插件是 HarmonyOS AI 原生交互的核心能力,本教程介绍了两种实现方式:

  • 前台执行(AppLink):简单直接,通过 URL 拉起应用并传参,适合页面跳转、触发操作等场景,无需上架 AGC 即可测试
  • 后台执行(标准实现):通过 InsightIntentExecutor 执行,支持返回数据给小艺播报和卡片展示,适合查询统计等场景

开发建议:

  1. 先在网页端用工具模拟集验证智能体对话流程,再写端侧代码
  2. AppLink 模式注意配置参数映射类型为 URL,否则参数不会拼到链接里
  3. UI 联动推荐用自增触发器 + @Watch 模式,避免状态不刷新
  4. 意图框架模式的 intentName 和 intentVersion 一定要和云端配置完全一致
  5. 后台执行如需访问需要初始化的服务,注意传入 context

希望本教程能帮助你快速上手端插件开发,为用户带来"所说即所得"的 AI 交互体验。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐