查看: 197|回复: 3

HarmonyOS 7.0意图接入与A2A服务端实战

[复制链接]
发表于 1 小时前 | 显示全部楼层 |阅读模式
AI开放能力接入的核心,不是给应用加一个聊天框,而是把应用自身能力按开放接口契约注册给系统智能体生态。HMAF(Harmony Agent Framework,鸿蒙智能体框架)按版本分三阶段演进;在方舟智能开发框架(ArkAF)中,能力开放又按接入复杂度分为三个层级。原文给出的三套实战范式分别覆盖意图声明、平台智能体入口和A2A服务端,务实路径是先跑通最小闭环,再逐级升级。

需要先厘清:这套契约与Deep Link/App Linking不在同一层。Deep Link解决从A跳到B某个页面的路径级跳转,参数由开发者与调用方私下约定;AI开放能力接入解决让系统在语义层面理解应用能做什么,意图名、垂域、参数类型、执行模式都要按平台规范声明,并由系统智能体在自然语言理解后匹配调度。前者是路径级跳转,后者是能力级注册,因此意图接入会引入声明文件、metadata注册、调试白名单与平台侧关联等环节,它们共同构成系统托付用户意图的信任链。

一、意图声明接入:配置文件、metadata与执行器

Intents Kit的核心思路是:应用不需要知道用户是谁、从哪个入口触发,只需声明能处理什么意图,由系统负责匹配与调度。接入有配置文件与装饰器两种路径:简单意图、参数较少用配置文件;复杂意图、动态逻辑用装饰器。

第一步,在resources/base/profile/下创建insight_intent.json,声明意图名、垂域、语义化版本、执行器入口和参数。示例:
  1. {
  2.   "insightIntents": [
  3.     {
  4.       "intentName": "CheckWeather",
  5.       "domain": "Weather",
  6.       "intentVersion": "1.0.0",
  7.       "srcEntry": "./ets/intents/CheckWeather.ets",
  8.       "parameters": [
  9.         { "name": "city", "type": "string", "description": "城市名称" },
  10.         { "name": "date", "type": "string", "description": "日期:today / tomorrow" }
  11.       ]
  12.     }
  13.   ]
  14. }
复制代码
第二步,最容易漏的是注册metadata。声明文件不会自动生效,必须在module.json5的abilities中引用:
  1. {
  2.   "module": {
  3.     "abilities": [
  4.       {
  5.         "name": "EntryAbility",
  6.         "metadata": [
  7.           { "name": "ohos.insight.intent", "resource": "$profile:insight_intent" }
  8.         ]
  9.       }
  10.     ]
  11.   }
  12. }
复制代码
漏掉这步,系统找不到意图定义,也是小艺识别不到技能的常见原因。

第三步,执行器继承@kit.AbilityKit中的InsightIntentExecutor,按执行模式重写回调。前台执行模式在UIAbility前台被拉起时回调,可在其中查数据、组装结果或跳转页面:
  1. import { InsightIntentExecutor } from '@kit.AbilityKit';
  2. export interface WeatherResult { summary: string; }
  3. export default class CheckWeatherIntentExecutor extends InsightIntentExecutor {
  4.   onExecuteInUIAbilityForegroundMode(
  5.     intentName: string,
  6.     params: Record<string, Object>
  7.   ): Promise<WeatherResult> {
  8.     const city: string = params['city'] as string;
  9.     const date: string = params['date'] as string;
  10.     return Promise.resolve({ summary: `${city} ${date} 晴 26℃` });
  11.   }
  12. }
复制代码
复杂意图可用@InsightIntentEntry声明入口,配合@InsightIntentLink/@InsightIntentFunction定义参数与函数,把动态逻辑写在ArkTS中。

二、消费侧集成:用FunctionComponent拉起平台智能体

当应用不做Agent、只想快速获得AI入口时,走FunctionComponent轻量接入。前置条件是在小艺开放平台创建智能体并关联应用,审核后取得唯一agentId。应用侧重点有三步:检查智能体在当前设备是否可用;渲染入口并传入必填的agentId与onError;订阅对话框开合事件,并在aboutToDisappear中取消订阅,避免事件句柄泄漏。

FunctionComponent会接管对话UI渲染、语音识别、流式输出、网络通信和动画,应用无需自建聊天界面。它具备图标与按钮两种形态,有无title自动切换;不支持该智能体时应做降级,例如隐藏入口或给出提示。示例:
  1. import { FunctionComponent, FunctionController } from '@kit.AgentFrameworkKit';
  2. import { BusinessError } from '@kit.BasicServicesKit';
  3. import { common } from '@kit.AbilityKit';
  4. import { hilog } from '@kit.PerformanceAnalysisKit';
  5. @Entry
  6. @Component
  7. struct AgentEntryPage {
  8.   private agentId: string = 'agentproxy_study_plan_001';
  9.   private controller: FunctionController = new FunctionController();
  10.   @State isAgentSupport: boolean = false;
  11.   async checkAgentSupport(): Promise<void> {
  12.     try {
  13.       const context = this.getUIContext()?.getHostContext() as common.UIAbilityContext;
  14.       this.isAgentSupport = await this.controller.isAgentSupport(context, this.agentId);
  15.     } catch (err) {
  16.       const e = err as BusinessError;
  17.       hilog.error(0x0001, 'AgentEntry', `code: ${e.code}, msg: ${e.message}`);
  18.     }
  19.   }
  20.   aboutToAppear(): void {
  21.     this.checkAgentSupport();
  22.     this.controller.on('agentDialogOpened', () => { hilog.info(0x0001, 'AgentEntry', 'opened'); });
  23.     this.controller.on('agentDialogClosed', () => { hilog.info(0x0001, 'AgentEntry', 'closed'); });
  24.   }
  25.   aboutToDisappear(): void {
  26.     this.controller.off('agentDialogOpened');
  27.     this.controller.off('agentDialogClosed');
  28.   }
  29.   build() {
  30.     Column() {
  31.       if (this.isAgentSupport) {
  32.         FunctionComponent({
  33.           agentId: this.agentId,
  34.           onError: (err: BusinessError) => {
  35.             hilog.error(0x0001, 'AgentEntry', `msg: ${err.message}`);
  36.           },
  37.           options: {
  38.             title: '智能规划',
  39.             queryText: '帮我生成一份学习计划'
  40.           }
  41.         })
  42.       } else {
  43.         Text('当前设备不支持该智能体')
  44.       }
  45.     }.width('100%').height('100%')
  46.   }
  47. }
复制代码

三、A2A服务端:让应用变成可被调用的Agent

API 26新增createA2AServer等A2A协议模块,应用可作为A2A服务端接收其他智能体请求、触发业务、更新任务状态并回传产物。核心概念包括Agent Card(身份、能力、端点、认证元数据)、Task(有状态的生命周期工作单元)、Message、Artifact(产物)与TaskState(submitted、working、input-required、completed等)。

这里的生命周期本身就是协议:onCreate用this.context.agentCard建服务端,onConnect启服务,onData转交server.onMessage并借proxy.sendData回包,onDisconnect/onDestroy停服务并回收资源。onAuth回调配合proxy.authorize()处理跨应用安全认证,这是A2A与普通IPC的本质差别。
  1. import { common, Want, AgentExtensionAbility } from '@kit.AbilityKit';
  2. import { RequestContext, createA2AServer, Server, TaskState } from '@kit.AgentFrameworkKit';
  3. import { hilog } from '@kit.PerformanceAnalysisKit';
  4. export default class GuideAgent extends AgentExtensionAbility {
  5.   private server: Server | null = null;
  6.   private agentOnData = (method: string, context: RequestContext): void => {
  7.     const id: string | undefined = context.getTaskId();
  8.     if (!id || !this.server || method !== 'Execute') { return; }
  9.     this.server.updateStatus(id, { state: TaskState.WORKING });
  10.     const query: string = context.getUserInput(' ') || '';
  11.     this.server.addArtifact(id, {
  12.       artifactId: `${id}-guide`, name: '导览资料',
  13.       parts: [{ text: `已根据「${query}」生成导览资料` }]
  14.     });
  15.     this.server.updateStatus(id, { state: TaskState.COMPLETED });
  16.   };
  17.   onCreate(want: Want): void {
  18.     try {
  19.       this.server = createA2AServer(this.context.agentCard, this.agentOnData, { want: want });
  20.     } catch (e) {
  21.       hilog.error(0x0000, 'A2AServer', `create failed: ${JSON.stringify(e)}`);
  22.     }
  23.   }
  24.   onConnect(want: Want, proxy: common.AgentHostProxy): void { this.server?.start(); }
  25.   onData(proxy: common.AgentHostProxy, data: string): void {
  26.     this.server?.onMessage(data, (response: string) => { proxy.sendData(response); });
  27.   }
  28.   onDisconnect(want: Want, proxy: common.AgentHostProxy): void { this.server?.stop(); }
  29.   onDestroy(): void { this.server?.stop(); }
  30. }
复制代码

四、API 26硬约束与避坑清单

原文特别提醒API 26的行为变更:当targetSdkVersion ≥ 26.0.0时,OnDataCallback的method参数类型由枚举AgentOperation改为string,且RequestContext.getClientSessionId()被删除。升级目标SDK时须同步调整A2A回调签名,否则编译期即报错。

除签名变更外,落地时还要检查:metadata是否已在module.json5中注册;FunctionComponent相关事件是否在aboutToDisappear中off;设备不支持智能体时是否隐藏入口或降级;应用是否声明网络权限;真机是否满足调试条件。

五、上线分发链路

一次完整的开放能力接入不止于代码。AGC配置:在AppGallery Connect的增长→意图框架创建意图,并完成应用手动签名。平台侧创建:在小艺开放平台创建智能体或端插件,绑定包名,配置技能描述与Prompt,获取agentId。应用侧集成:按上述三套范式接入Kit,声明网络权限,处理降级。真机调试:设备ROM ≥ 6.0.0、登录华为账号、联网,并将设备加入调试白名单。发布分发:意图或智能体审核上架后,进入小艺、智慧搜索、意图面板等系统入口。

结语:AI开放能力API集成的本质,是把应用能做什么翻译成系统能理解的契约。意图层用声明文件、metadata与执行器讲清能力边界;智能体入口层用FunctionComponent复用系统级对话能力;A2A层用AgentExtensionAbility参与多智能体协同。三层契约由轻到重,却共享同一条纪律:先跑通最小闭环,再逐级升级;先满足平台约束,再谈体验打磨。
回复

使用道具 举报

发表于 1 小时前 | 显示全部楼层

Re: HarmonyOS 7.0意图接入与A2A服务端实战

这篇把意图接入的链路讲得很清楚,尤其是 insight_intent.json 声明之后还要在 module.json5 的 abilities 里注册 metadata 这一步,确实是容易漏掉的关键点。Deep Link 和能力级注册的区分也很有帮助,能让人理解为什么不是简单加个跳转就行。FunctionComponent 那部分提到检查智能体可用性、传 agentId 和 onError、以及在 aboutToDisappear 里取消订阅,都是实战里容易踩的细节。首帖最后似乎还没贴完,期待后续把 A2A 服务端和完整示例继续展开,特别是调试白名单和平台侧关联的注意事项。
回复 支持 反对

使用道具 举报

发表于 1 小时前 | 显示全部楼层

Re: HarmonyOS 7.0意图接入与A2A服务端实战

楼主这篇把意图接入和 Deep Link/App Linking 的层级差异讲得很清楚,尤其是“路径级跳转”和“能力级注册”的对比,对刚接触 HMAF 的人很关键。配置文件、module.json5 里的 metadata 注册、InsightIntentExecutor 这三步里,metadata 确实最容易漏,很多“小艺识别不到技能”就卡在这里。FunctionComponent 那段也很实用,agentId、可用性检查、onError 和 aboutToDisappear 取消订阅都是落地时容易忽略的点。不过帖子到 private agentId 这里好像截断了,后面完整示例和 A2A 服务端部分没贴出来,如果方便可以补全,尤其想看看最小闭环跑通后怎么逐级升级。感谢分享。
回复 支持 反对

使用道具 举报

发表于 1 小时前 | 显示全部楼层

Re: HarmonyOS 7.0意图接入与A2A服务端实战

感谢楼主,这篇把意图接入和 Deep Link 的区别讲得很清楚,尤其是“路径级跳转”和“能力级注册”不在一个层面这一点,对刚接触的人很有帮助。我也比较认同先跑通最小闭环再逐级升级的思路。首帖里提到的 metadata 注册确实容易被忽略,声明文件写了但 module.json5 里没引用,系统找不到意图定义,这个坑很典型。执行器按前台模式重写回调、FunctionComponent 的可用性检查、onError、对话框开合事件订阅以及 aboutToDisappear 里取消订阅这些点也很实用。后续如果继续写,想看到 FunctionComponent 示例的完整收尾、不支持智能体时的降级策略怎么落地,以及 A2A 服务端从注册到联调的最小步骤。期待更新。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-11-14 01:50 , Processed in 0.045463 second(s), 18 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部