HarmonyOS API 26 HMAF 技能 端侧 A2A 消息去重与上下文最小化

适用版本:HarmonyOS API 26。本文讨论侧A2A协作的应用侧契约:消息如何带上理解、能力和权力等键,接收方如何做权限复核,超时或重复消息如何安全回退。示例是ArkTS端风格的纯逻辑模型,不表示完成HarmonyOS编译、系统解析、ArkUI联调或真机测试。

CSDN系列:HARMONYOS-BATCH-161

端侧A2A消息去重封面

消息校验与退回流程

HMAF 技能协作结构

一、A2A的最小化问题域

端完成侧方协作不是把完整上下文给定广播所有技能,而是传递当前动作所需的最大字段,并让接收方重新做权限与最终校验。

二、消息契约

export interface A2AMessage { readonly messageId: string; readonly intentId: string; readonly capability: string; readonly expiresAt: number; readonly args: Readonly<Record<string, string>> }

messageId负责去重,intentId负责关联动作图,expiresAt限制重放窗口。

三、来源与能力验证

发送方声明来源不等于接收方授权。接收方应核对来源、能力白名单、参数模式和当前用户确认状态,再决定是否进入执行队列。

export interface VerifyResult { readonly ok: boolean; readonly reason?: 'expired' | 'unknown_capability' | 'invalid_args' | 'missing_consent' }
export function verifyMessage(message: A2AMessage, now: number, allowed: ReadonlySet<string>): VerifyResult { if (message.expiresAt <= now) return { ok: false, reason: 'expired' }; if (!allowed.has(message.capability)) return { ok: false, reason: 'unknown_capability' }; return { ok: true } }

四、权力等去重表

去重表只保存消息ID、状态和过渡时间,不保存完整的上下文。状态至少包含seen、running、done和rejected。

export type SeenState = 'seen' | 'running' | 'done' | 'rejected'
export interface SeenRecord { readonly messageId: string; readonly state: SeenState; readonly expiresAt: number }
export function shouldDrop(record: SeenRecord | undefined, now: number): boolean { return Boolean(record && record.expiresAt > now) }

五、上下文最小化

消息只说明必要参数。用户原始话术、动作、位置和设备指纹不默认透传给需要它们的技能;必要时使用短期引用并在执行后失效。

六、超时预算

export function remainingBudget(deadlineMs: number, nowMs: number): number { return Math.max(0, deadlineMs - nowMs) }
export function canForward(deadlineMs: number, nowMs: number, reserveMs: number): boolean { return remainingBudget(deadlineMs, nowMs) > reserveMs }

转发前先预备本地清理和回退时间,避免下部等待全部预算后无法向用户解释结果。

七、重放与乱序

接收方按messageId去重,按intentId和版本号处理乱序。旧版本消息只能被记录,不能覆盖已完成的新版本动作。

八、拒绝与回执

拒绝消息应注明稳定原因码,例如EXPIRED、NO_CONSENT、CAPABILITY_DENIED,不返回过度敏感信息。回执只说明状态变化,不回显完整参数。

九、部分成功

多个技能协作时,部分成功处于正常状态。结果应启动完成、跳过和待重试动作,而不是用户可以选择继续或取消,是收到笼系统的失败提示。

export interface A2AResult { readonly completed: readonly string[]; readonly skipped: readonly string[]; readonly retryable: readonly string[] }

十、本地服务器与清理

去重记录按 TTL 清理,应用退出或用户取消授权时清理对应意图。不要把去重表设置为长期业务数据库。

十一、API26版本声明

本文目标版本为HarmonyOS API 26(Version 26)。A2A、HMAF 和 Skill 按应用侧模型讨论,具体平台能力、权限和生命周期仍需以官方文档为准。

十二、UI状态映射

至少页面区分waiting、verifying、running、partial、rejected和done,每个非成功状态都提供原因与可恢复动作。

十三、安装场地

export interface A2AEvidence { readonly traceId: string; readonly messageId: string; readonly state: SeenState; readonly latencyMs: number; readonly reason?: string }

日志不保存原始话术和敏感参数,只保存诊断所需的带宽、状态和时间。

十四、回归矩阵

覆盖重复消息、过渡能力消息、乱序版本、未知、缺少确认、超时转发、部分成功、撤销授权和小窗口恢复。每条退出记录输入、判定和回。

十五、纯逻辑验证边界

此处未执行HarmonyOS编译、系统解析、ArkUI联调或真机测试;本地验证仅针对消息校验、去重、预算与状态映射。

十六、官方资料

十七、小结

端侧A2A的可靠性来自最小上下文、接收方复核、权力等去重和明确回执。围绕API 26固化这些应用侧契约,才能在接入器真实技能时保持可解释、可恢复能力和可回归。

十八、纵向队列的边界

发送队列只负责排序、中间检查和取消,不负责解释自然语言。解析器输出稳定的intentId后,队列才接续消息生命周期;这样可以把模型移动与执行可靠性隔离开。

export interface QueueItem { readonly message: A2AMessage; readonly enqueuedAt: number; readonly cancelled: boolean }
export function isExpired(item: QueueItem, now: number): boolean { return item.message.expiresAt <= now || item.cancelled }

十九、接收方的二次确认

即使上游已经确认,接收技能仍应在本地检查当前账号、设备状态和权限范围。拒绝时返回稳定错误码,调用方可以选择修改参数而不是盲目重试。

二十、版本迁移

消息契约升级时增加schemaVersion,接收方仅兼容明确声明的版本;不支持的版本进入CONTRACT_MISMATCH,并保留原消息摘要提供人工复盘。

export function supportsSchema(version: number, supported: ReadonlySet<number>): boolean { return supported.has(version) }

第二十一、端侧安全日志

日志以traceId、messageId、能力名和结果码为主,不记录完整话术、股票或文件内容。日志导出前需经过脱敏和权限检查,诊断能力避免变成隐私泄露入口。

二十二、交付前检查表

交付前确认:API 26版本是否写明;A2A消息有幂等键;接收方是否二次校验;隔壁与乱序是否可预测;用户是否能取消成功;部分是否可恢复;日志最小化是否可恢复;日志最小化;本地测试是否覆盖拒绝和重试。如果没有证据,均应保留为后续任务。

export function dedupeKey(message: A2AMessage): string { return `${message.intentId}:${message.messageId}` }

二十三、最小落地顺序

建议先在单进程内实现消息契约和去重表,再接入跨能力通道;先让拒绝、过渡和重复消息在本地回放,再增加真实执行器。这样即使平台能力或权限配置发生变化,动作图、回执和用户提示稳定的测试接入。接入API 26目标设备时,应把窗口变化、应用切后台并授权撤回作为回归独立场景,不要把一次成功运行当成长期兼容。证明

每轮恢复都保留输入消息摘要、去重表快照、最终状态和用户必要可见提示。对失败样本只保存的诊断字段,原始内容在测试结束后立即清理,为了避免追踪问题而扩大数据留存范围。

如果接收方拒绝了消息,发送方应收到强制回执,并能在动作中看到拒绝原因。对于可重试错误,重试必须耗费明确预算;对于权限和契约错误,只能引导用户修改输入或重新授权,不能用自动重试忽略边界问题。

套件边界也适用于多设备:设备切换时重新验证和授权,不直接恢复使用旧会话上下文。

因此,消息协议、机状态和用户提示应一起评审,不能只看传输是否成功。

最终验收以真实目标设备和官方能力说明一致,本文不虚构任何系统联调结论。这也是可审计协作的最后一个边界。请保留复盘记录。并标记负责人。

二十四、接入前检查清单

HarmonyOS AP正式接入前,工程侧要过一遍检查清单:SDK版本与目标API版本匹配、权限在清单中声明且其次申请、能力切换在专用配置层管理、包体积增量匹配预算。任何一项不过先停,带着不匹配的版本往上冲,排错会翻倍成本。

interface PrecheckItem { name: string; pass: boolean; note?: string }
const checklist: PrecheckItem[] = [
  { name: 'SDK/API版本匹配', pass: false },
  { name: '权限声明完整', pass: false },
  { name: '开关集中管理', pass: false },
  { name: '包体积增量<预算', pass: false },
]
const allPass = checklist.every(x => x.pass)

检查清单跑通的标志是:新建工程按清单接入一次成功,且不依赖任何辅助经验。做不到,说明文档还缺少关键步骤。

二十五、常见坑与版本装备记录

HarmonyOS AP最常践的坑集中在三处:样本代码用的旧接口在新版本被拆分、默认配置与生产预期不一致、调试环境与真机行为存在差异。每践一个坑就记进版本发票表,涉坑点、影响版本、修复方式与验证方式。

interface Pitfall { issue: string; sinceApi: string; fix: string; verifiedOn: string[] }
const pitfalls: Pitfall[] = []
function knownPit(api: string): Pitfall[] { return pitfalls.filter(p => p.sinceApi === api) }

车辆表的价值在升级时兑现:每次目标版本变更,先对照表过一遍已知坑,能省下一轮整轮盲目排查。

二十六、恢复口径与停止线

HarmonyOS AP的任何序列合入前都要回答相同问题:怎么证明没有把好的部分改坏。回归口径必须重复纸面:上一版通过的例子清单全量跑重、上一版记录的基线值全量对比、增加能力补一条典型例子。三件事缺一件,回归就是穿越场。

interface RegressionGate { lastPassedCases: number; rerun: number; baselineCompare: 'PASS' | 'FAIL'; newCaseAdded: boolean }
function gateOk(g: RegressionGate): boolean { return g.rerun === g.lastPassedCases && g.baselineCompare === 'PASS' && g.newCaseAdded }

停止线同样要提前写明:同一问题打回三次、恢复连挂两轮、或验证环境与目标环境共振,满足其一停止来复盘,流程是继续硬修。停止把线当成流程的一部分,才能避免在小问题上消耗掉整块的排期。

Logo

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

更多推荐