很多初学者写鸿蒙 RPC 代码时,最容易出问题的地方不是连接服务,而是消息对象的读写细节。比如客户端 writeString、writeInt 的顺序和服务端 readString、readInt 不一致,就可能导致读到错误数据;异步调用时还想立刻从 reply 里取值,也会出现空结果。

所以第二篇我们专门拆 MessageParcel / MessageSequence、sendMessag

摘要

本文围绕鸿蒙新生态中的 Intents Kit、鸿蒙智能体、小艺开放平台、元服务和服务卡片,分析应用如何从“等待用户打开”升级为“理解意图、主动推荐、服务直达”。文章以医护 AI 服务为案例,给出意图拆分、智能体编排、工具治理、多入口分发、安全合规和质量测试方案,并提供应用侧 ArkTS 架构模板。

关键词:鸿蒙新生态;Intents Kit;鸿蒙智能体;小艺;元服务;服务卡片;智慧分发;医护 AI

文章目录

  • 1. 什么是“鸿蒙新生态”
  • 2. Intents Kit 为什么是生态连接器
  • 3. 鸿蒙智能体与普通聊天机器人的区别
  • 4. 医护 AI 应用如何拆成意图
  • 5. 一次复诊预约的执行闭环
  • 6. 元服务与服务卡片承担什么角色
  • 7. 智慧分发不是无节制推送
  • 8. 医护智能体的安全边界
  • 9. 工程架构要把模型与工具隔离
  • 10. 服务结果要适配不同入口
  • 11. 失败路径与人工兜底
  • 12. 数据闭环与增长价值
  • 13. 测试要覆盖语言与场景差异
  • 14. 本文小结
  • 15. 生态能力与医护场景矩阵
  • 16. 风险与治理策略
  • 17. 90分文章质量自检
  • 18. 代码模板:意图请求模型
  • 19. 代码模板:智能体编排器
  • 20. 代码模板:工具注册与安全策略
  • 21. 代码模板:多入口服务结果
  • 22. 测试清单
  • 23. 参考资料

正文

1. 什么是“鸿蒙新生态”

传统移动生态以 App 图标为入口,用户必须先找到并打开应用,再在多级页面里寻找功能。鸿蒙新生态正在把业务功能拆成可理解、可推荐、可直达的服务:系统通过 Intents Kit 连接应用和元服务内的业务能力,小艺通过对话、搜索、建议等入口分发服务,元服务和卡片负责轻量承载。应用不再只是一个安装包,而是一组可以被系统组合和触达的服务。

图 1  鸿蒙新生态能力地图

2. Intents Kit 为什么是生态连接器

官方将 Intents Kit 定义为 HarmonyOS 级的意图标准体系,用于理解用户显性和潜在意图,并把需求传递给生态伙伴。意图框架已覆盖多种垂域和意图,支持习惯推荐、事件推荐、位置推荐、语音调用和本地搜索。对开发者而言,接入意图不是增加一个语音入口,而是把业务能力变成系统能识别的标准服务。

3. 鸿蒙智能体与普通聊天机器人的区别

普通聊天机器人主要生成文本回答,鸿蒙智能体更强调理解需求、澄清参数、调用工具、执行业务和返回可操作结果。用户说“帮我预约下周的复诊”,智能体不能只回复预约方法,而应询问医院、科室和时间,在获得授权后调用预约服务,并把成功结果写入日程或服务卡片。能完成任务,才是智能体生态的核心价值。

图 2  医护 AI 服务的新生态架构

4. 医护 AI 应用如何拆成意图

医护 AI PPT、健康管理或护理服务应用可以把能力拆成预约复诊、查询报告、生成健康科普、创建护理计划、设置用药提醒、联系人工客服等意图。每个意图都要定义触发表达、必要参数、可选参数、权限要求、执行工具、成功结果和失败兜底。意图颗粒度太大,智能体难以执行;太小,则无法形成完整业务闭环。

5. 一次复诊预约的执行闭环

用户表达需求后,系统首先识别“预约复诊”意图;如果缺少医院、科室、医生或时间,就进入参数澄清;随后校验登录状态、患者身份和授权范围;业务工具调用预约接口;成功后返回预约结果,并通过日程、卡片或提醒继续触达。这个流程体现了意图、智能体、业务服务和系统分发入口的协同。

图 3  复诊预约意图执行闭环

6. 元服务与服务卡片承担什么角色

元服务强调轻量、即点即用,适合一次性或低频服务;服务卡片让重要信息直接出现在桌面,并支持有限的直接操作。医护场景里,预约挂号、报告查询、用药打卡、护理任务和复诊提醒都适合服务化。用户不一定需要完整打开 App,也能完成查看、确认或打卡。

7. 智慧分发不是无节制推送

意图框架支持基于时间、位置、事件和设备状态的系统推荐,但推荐必须满足相关性和克制原则。预约就医前可以推荐导航和材料清单,用药时间可以展示提醒卡片,报告完成后可以提供查询入口;不相关的健康营销不应借推荐能力反复打扰用户。高质量分发是合时宜,不是多曝光。

图 4  同一服务的多入口智慧分发

8. 医护智能体的安全边界

医疗健康内容具有高风险。智能体可以做流程导航、材料整理、科普生成、预约执行和记录辅助,但不应在缺乏专业依据时直接诊断疾病或修改医嘱。涉及患者信息、报告和护理记录的工具调用必须校验账号和权限;敏感信息不应完整进入提示词、普通日志或推荐摘要;不确定或高风险问题应明确转人工或建议就医。

图 5  普通聊天机器人与可信医护智能体对比

9. 工程架构要把模型与工具隔离

页面、智能体、业务工具和数据访问不能混在一起。建议用 IntentRequest 表达用户意图,用 AgentOrchestrator 负责参数澄清和工具选择,用 ToolRegistry 管理预约、报告、提醒等工具,用 PolicyGuard 做授权与风险检查。大模型只负责理解和编排,真正的业务结果必须来自受控工具和可信数据源。

10. 服务结果要适配不同入口

同一个业务结果在小艺对话、搜索、建议、服务卡片和元服务中需要不同展示。对话适合解释和追问,搜索适合标题与摘要,建议适合简短行动入口,卡片适合实时状态与一键操作,元服务适合轻量完整流程。开发者应先定义统一 ServiceResult,再由不同入口转换展示,而不是为每个入口重写业务逻辑。

11. 失败路径与人工兜底

智能体可能无法理解表达、缺少参数、工具超时、权限不足或业务接口失败。失败时不能编造结果。系统应说明当前缺少什么、哪些步骤尚未完成,并给出重新选择、稍后重试、打开完整应用或联系人工的入口。医护场景中的失败提示尤其要清楚,避免用户误认为预约、报告提交或护理任务已经成功。

12. 数据闭环与增长价值

新生态为开发者带来的价值不只是体验升级,也包括更多系统入口和业务转化。意图服务可以通过对话、搜索、建议等方式触达目标用户,元服务降低使用门槛,卡片提高持续可见性。开发者应关注意图识别成功率、参数补全率、工具执行成功率、服务直达转化率、重复使用率和用户关闭推荐率,而不是只统计曝光。

13. 测试要覆盖语言与场景差异

意图测试要覆盖口语、简称、错别字、模糊时间、多轮修改、否定表达和无关问题。例如“下周找上次那个医生”“把复诊改到周五下午”“别提醒我了”都需要正确处理。还要测试未登录、无权限、患者身份切换、接口失败、重复预约和高风险健康问题的人工兜底。

图 6  高分文章与新生态方案自检

14. 本文小结

鸿蒙新生态的核心,是把应用能力从封闭页面中释放出来,成为系统可理解、可推荐、可编排和可直达的服务。Intents Kit 建立意图标准,鸿蒙智能体完成理解与执行,小艺入口负责智慧分发,元服务和卡片承载轻量体验。对于医护 AI 应用,只有同时做好业务拆分、工具治理、隐私安全和人工兜底,才能真正融入新生态。

15. 生态能力与医护场景矩阵

生态能力

医护场景

开发重点

Intents Kit

复诊预约、报告查询、护理计划、用药提醒

意图颗粒度、参数定义、权限和失败结果

鸿蒙智能体

多轮澄清、工具调用、科普生成、流程导航

模型不直接改业务数据,执行必须走受控工具

元服务

挂号、报告领取、健康测评等轻量流程

即点即用,减少注册和页面层级

服务卡片

用药打卡、预约状态、护理任务

信息实时、操作克制、隐私内容可隐藏

小艺智慧分发

语音调用、搜索直达、时间/事件推荐

合时宜推荐,控制频率并支持关闭

16. 风险与治理策略

风险

可能问题

治理策略

意图误识别

执行了错误服务或错误参数

高风险操作二次确认,展示关键参数

模型幻觉

生成不存在的预约结果或医疗结论

业务结果只来自工具;不确定时失败而非猜测

越权访问

查询其他患者报告或护理记录

工具调用前校验账号、角色和数据范围

过度推荐

健康服务频繁打扰用户

设置频控、关闭入口和推荐原因说明

隐私泄露

敏感数据进入提示词、摘要或日志

数据最小化、脱敏、端侧处理与审计

17. 90分文章质量自检

评分项

本篇配置

价值

结构

摘要、关键词、目录、14节正文、小结

层级清晰,适合长文阅读

图文

6张自制生态、架构、流程和对比图

帮助理解复杂生态关系

代码

4组意图、编排、工具和分发模板

给出工程落地边界

表格

场景矩阵、风险治理、质量自检

便于快速比较和检查

官方依据

意图框架、小艺开放平台、元服务等官方资料

避免将概念包装成虚构能力

18. 代码模板:意图请求模型

type MedicalIntent = 'bookFollowUp' | 'queryReport' | 'medicationReminder' | 'nursingPlan';

interface IntentRequest {

  intent: MedicalIntent;

  utterance: string;

  slots: Record<string, string | number | boolean>;

  userId?: string;

  sensitivity: 'normal' | 'medical';

  requestId: string;

}

interface IntentResult<T> {

  success: boolean;

  message: string;

  data?: T;

  missingSlots?: string[];

  requiresConfirmation?: boolean;

}

这里是应用侧业务模型,不等同于 Intents Kit 的具体 API。接入官方意图框架时,应把系统意图参数转换为内部 IntentRequest,让业务层不直接依赖外部协议。

19. 代码模板:智能体编排器

class MedicalAgentOrchestrator {

  constructor(private tools: ToolRegistry, private policy: PolicyGuard) {}

  async execute(request: IntentRequest): Promise<IntentResult<object>> {

    const missing = this.findMissingSlots(request);

    if (missing.length > 0) {

      return { success: false, message: '请补充必要信息', missingSlots: missing };

    }

    await this.policy.authorize(request);

    const tool = this.tools.resolve(request.intent);

    return await tool.invoke(request.slots);

  }

}

编排器先补齐参数,再执行授权检查,最后调用受控工具。大模型负责理解和组织对话,不直接操作数据库或生成虚假的业务结果。

20. 代码模板:工具注册与安全策略

interface AgentTool {

  name: string;

  invoke(slots: Record<string, unknown>): Promise<IntentResult<object>>;

}

class ToolRegistry {

  private tools: Map<string, AgentTool> = new Map();

  register(intent: MedicalIntent, tool: AgentTool): void { this.tools.set(intent, tool); }

  resolve(intent: MedicalIntent): AgentTool {

    const tool = this.tools.get(intent);

    if (!tool) throw new Error(`No tool for ${intent}`);

    return tool;

  }

}

class PolicyGuard {

  async authorize(request: IntentRequest): Promise<void> {

    if (request.sensitivity === 'medical' && !request.userId) {

      throw new Error('请先登录并完成身份校验');

    }

  }

}

工具层是可信边界:预约、报告查询和提醒设置都必须通过工具调用。PolicyGuard 统一处理登录、角色、数据范围和高风险确认。

21. 代码模板:多入口服务结果

interface ServiceResult {

  title: string;

  summary: string;

  actionUri: string;

  status?: string;

  updatedAt: number;

}

function toSuggestion(result: ServiceResult): object {

  return { title: result.title, subtitle: result.summary, uri: result.actionUri };

}

function toServiceCard(result: ServiceResult): object {

  return {

    primaryText: result.title,

    secondaryText: result.status ?? result.summary,

    actionUri: result.actionUri

  };

}

业务层只输出统一 ServiceResult,小艺建议、搜索、卡片和元服务分别转换展示。这样不同入口共享同一份可信业务数据。

22. 测试清单

  • 覆盖口语、简称、错别字、模糊时间、否定表达和多轮修改。
  • 覆盖缺少参数、用户取消、重复预约、工具超时和业务接口失败。
  • 覆盖未登录、身份切换、角色权限不足和其他患者数据越权。
  • 验证模型不会编造预约成功、报告结果或医疗诊断。
  • 验证对话、搜索、建议、服务卡片和元服务结果保持一致。
  • 验证推荐频率、关闭入口、隐私摘要和人工客服兜底。

eRequest、DeathRecipient 和资源释放。把这些点弄清楚,RPC 代码就会稳定很多。

图 3  消息对象的读写顺序

1. MessageParcel 和 MessageSequence 怎么理解

对象

常见用途

注意事项

MessageParcel

旧接口或兼容场景中常见,用于读写基础类型、数组、远端对象等

部分 sendRequest 相关接口在新 API 中已不建议继续使用

MessageSequence

API 9+ 推荐与 sendMessageRequest 搭配使用

客户端和服务端要严格保持字段顺序、类型和接口令牌一致

MessageOption

声明同步或异步调用模式

异步模式下 reply 通常不能按同步返回值理解

MessageSequence 的思路可以类比一个顺序队列:写入端按 A、B、C 放进去,读取端也必须按 A、B、C 取出来。它不会自动根据字段名匹配,也不会帮你判断“这里本来应该是 string”。因此,RPC 协议最怕两端代码各改各的:客户端多写了一个字段,服务端没有同步读取,后面的字段就会全部错位。

如果传输的是复杂对象,建议先把字段拆成基础类型,或者把对象序列化成 JSON 字符串,并在 JSON 中携带 version。基础类型适合高频、小数据量调用;JSON 适合字段经常变化但体积不大的业务对象;如果是大文件、图片、视频,不建议直接塞进 RPC 消息里,更适合传文件描述符、URI 或通过专门的传输通道处理。

2. 服务端处理请求的模板

class BookRemoteObject extends rpc.RemoteObject {

  constructor() { super('com.demo.BookService'); }

  onRemoteMessageRequest(code: number, data: rpc.MessageSequence,

    reply: rpc.MessageSequence, option: rpc.MessageOption): boolean {

    if (code === REQUEST_GET_BOOK) {

      data.readInterfaceToken();

      let bookId = data.readString();

      reply.writeNoException();

      reply.writeString('HarmonyOS RPC Guide: ' + bookId);

      return true;

    }

    return false;

  }

}

3. sendMessageRequest 的同步和异步

官方接口里 MessageOption 可以声明调用模式。同步模式更像普通函数调用:客户端等待服务端处理完,再从 reply 中读取结果。它适合“查询配置”“读取小段状态”“校验一个值”这种短耗时任务。异步模式更适合长耗时任务或跨设备调用,客户端不应该立刻依赖 reply,而是通过回调对象、事件通知或状态查询拿最终结果。

选择同步还是异步,核心看两个问题:业务结果是不是马上要用,服务端处理会不会阻塞。如果页面点击按钮后必须立即展示结果,并且服务端只做轻量计算,可以用同步;如果服务端要扫描设备、上传文件、等待网络响应,就应当用异步。否则用户会感觉界面卡住,严重时还可能触发超时或进程调度问题。

4. 为什么要 reclaim

消息对象底层涉及跨进程通信缓冲区,不应该等垃圾回收器慢慢处理。实践中建议把 data、reply 的释放写进 finally,保证成功、失败、异常路径都会执行。这样做不仅代码整洁,也能避免高频调用时出现资源占用累积。

同样重要的是异常路径。很多示例代码只写 then 里的成功读取,但真实业务中要同时处理 sendMessageRequest 本身失败、服务端写入异常、readException 读到远端异常、reply 字段为空等情况。把这些异常统一封装成业务错误,再返回给 UI 层,会比在页面里到处 try/catch 更可维护。

5. 常见问题排查表

现象

可能原因

建议处理

服务端收不到请求

未连接成功、IRemoteObject 为空、请求码不一致

先打印 onConnect,再统一维护请求码常量

读取参数错位

write/read 顺序或类型不一致

把接口协议写成固定模板,客户端和服务端共用定义

异步调用没有返回值

把异步模式当同步模式使用

确认 MessageOption 模式,异步结果走回调或业务通知

服务重启后调用失败

客户端持有的远端对象已死亡

注册 DeathRecipient,死亡后重新连接服务

6. 推荐写法清单

  • 请求码使用常量集中管理,不要在多处手写数字。
  • 每个接口先写 interface token,服务端先校验 token,再处理业务参数。
  • 读写字段顺序写进注释或 IDL,不要靠记忆维护协议。
  • Promise / callback 中处理 errCode 和 readException,不要只写成功路径。
  • finally 中 reclaim 消息对象,死亡通知中清空代理并触发重连。

7. DeathRecipient 什么时候需要

当服务进程被系统回收、崩溃、升级重启,或者分布式设备离线时,客户端手里的远端对象就可能失效。DeathRecipient 的作用就是让客户端知道“这个远端对象已经死了”。收到通知后,最稳的处理方式不是继续重试同一个对象,而是清空缓存代理、提示业务层进入未连接状态,并按连接流程重新获取远端对象。

如果业务是一次性短调用,死亡通知可能不是必须;如果业务是长连接、设备控制、后台同步、持续订阅,就很有必要注册。注册后也别忘了在不再需要时注销,否则生命周期管理会变得混乱。可以把注册和注销放进连接管理器里,而不是散落在每个页面。

8. 小结

鸿蒙 RPC 的写法看起来是 API 调用,底层却是严格的消息协议。稳定的 RPC 代码通常有三个特征:协议常量清晰、消息读写对称、异常和生命周期处理完整。掌握这三点,再去看官方 @ohos.rpc 文档,很多接口就能自然串起来。

参考资料

  • HarmonyOS 官方文档:@ohos.rpc (RPC) API 参考:https://developer.huawei.com/consumer/cn/doc/harmonyos-references/js-apis-rpc
  • HarmonyOS 官方文档:ServiceExtensionAbility 开发参考:https://developer.huawei.com/consumer/cn/doc/HarmonyOS-Guides/app-service-extension-ability
  • HarmonyOS 文档中心:IPC Kit / Ability Kit 等开发文档入口:https://developer.huawei.com/consumer/cn/doc/
  • 参考写作风格:CSDN 技术博客式的“概念拆解 + 图示 + 表格 + 代码 + 总结”结构。
Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐