【HarmonyOS 7新能力|026】Agent Framework Kit工程封装:把接入逻辑放进可维护的分层结构
【HarmonyOS 7新能力|026】Agent Framework Kit工程封装:把接入逻辑放进可维护的分层结构

Agent 原型通常很快:接收一句话、调用几个工具、输出结果。真正进入工程阶段后,问题会集中出现——页面直接拼提示词、工具返回值未经校验、A2A 对端超时拖住主流程、重试导致重复副作用、日志记录了敏感上下文。
本文将 Agent 与 A2A 接入拆成交互、编排、能力、适配、治理和基础设施六层,重点是可维护边界,不虚构具体平台 API。示例类型和调用方式均为应用侧教学封装,不代表 HarmonyOS 7 Agent Framework Kit 的官方签名;能力范围、A2A 接入条件和设备支持应以当前 SDK 与华为官方文档为准。
一、先把 Agent 定义为受控任务系统
Agent 不是可以无限行动的聊天框,而是一个接收目标、生成计划、调用允许能力、验证结果并反馈的任务系统。每个动作都必须能回答:谁请求、允许做什么、预算多少、结果怎样验证、失败后是否重试。
第一版只允许只读查询和本地计算。发送消息、删除文件、支付和外部提交等副作用不自动开放。验收目标是:未知能力拒绝;每个任务有终态;取消能传递;超时不会无限重试;A2A 只发送最小数据;最终结果可追溯到步骤证据。
二、用契约注册能力
能力注册表不只保存函数引用,还要描述输入、输出、权限、风险和超时。编排器只能调用注册且通过策略检查的能力。
type RiskLevel = 'read' | 'write' | 'external'
interface CapabilityContract<I, O> {
name: string
version: number
risk: RiskLevel
timeoutMs: number
validateInput(input: unknown): input is I
execute(input: I, context: ExecutionContext): Promise<O>
validateOutput(output: unknown): output is O
}
泛型帮助应用侧保持类型清晰,运行时校验仍不可省略,因为输入可能来自模型或远端 Agent。
三、任务状态机替代散落的布尔值
使用 isLoading、isDone、hasError 很容易形成矛盾组合。任务状态机明确描述计划、运行、等待协作、取消和终态。
type TaskState =
| 'created'
| 'planning'
| 'running'
| 'waiting-peer'
| 'completed'
| 'failed'
| 'cancelled'
interface AgentTask {
id: string
state: TaskState
revision: number
deadlineAt: number
stepIndex: number
}
每次迁移增加 revision,异步回调落地前检查版本。用户取消或任务重规划后,旧回调即使成功也不能覆盖新状态。
四、编排器只负责决策与调度

编排层把目标拆成步骤、匹配能力、安排依赖和汇总结果,不直接读数据库、发网络请求或调用平台对象。所有副作用通过能力适配器完成。
interface PlanStep {
id: string
capability: string
dependsOn: ReadonlyArray<string>
input: Record<string, unknown>
status: 'pending' | 'running' | 'succeeded' | 'failed' | 'skipped'
}
interface TaskPlan {
taskId: string
steps: ReadonlyArray<PlanStep>
maxParallel: number
}
计划生成后先做静态检查:能力是否存在、依赖是否成环、参数是否符合契约、风险是否超过授权范围。
五、把平台能力放进适配层
平台 Kit、本地数据库、文件系统和网络服务都通过适配器暴露窄接口。编排层不持有 Context,不解析平台原始错误,也不决定权限弹窗何时出现。
interface SearchInput { keyword: string; limit: number }
interface SearchItem { id: string; title: string; summary: string }
interface SearchPort {
search(input: SearchInput, signal: AbortSignal): Promise<ReadonlyArray<SearchItem>>
}
适配器负责把平台结果映射成稳定模型,并将权限拒绝、不可用和超时转换成有限错误码。
六、A2A 是受控能力而非万能转发

只有本地无法完成且策略允许时才进入 A2A。发送前确认对端身份、能力版本、数据最小化和用户授权;接收结果后仍按不可信输入校验。
interface A2ARequest {
requestId: string
capability: string
contractVersion: number
deadlineAt: number
payload: Record<string, string | number | boolean>
}
interface A2AResponse {
requestId: string
status: 'ok' | 'rejected' | 'failed'
payload?: Record<string, string | number | boolean>
errorCode?: string
}
不要把整段会话、用户文件或内部提示词默认转发给对端。请求仅包含完成该步骤必需的字段。
七、来源、授权与能力三重校验
A2A 请求通过传输层到达并不意味着可以执行。服务侧依次验证可信来源、授权范围和目标能力;调用方在业务参数中自报的身份不能作为依据。
interface PeerPolicy {
peerId: string
allowedCapabilities: ReadonlySet<string>
maxPayloadBytes: number
expiresAt: number
}
function canInvoke(policy: PeerPolicy, capability: string, now: number): boolean {
return now < policy.expiresAt && policy.allowedCapabilities.has(capability)
}
身份信息必须来自平台或可信传输层。授权过期、能力不匹配或载荷超限时,在任何业务副作用发生前拒绝。
八、预算约束防止任务失控
任务应同时限制步骤数、总时长、工具调用次数、并行度和外部请求量。预算不是模型提示语,而是编排器强制执行的状态。
interface ExecutionBudget {
maxSteps: number
maxToolCalls: number
maxElapsedMs: number
maxPeerCalls: number
}
function exhausted(budget: ExecutionBudget, task: AgentTask, toolCalls: number, peerCalls: number): boolean {
return task.stepIndex >= budget.maxSteps || toolCalls >= budget.maxToolCalls ||
peerCalls >= budget.maxPeerCalls || Date.now() >= task.deadlineAt
}
达到预算后进入可解释的失败或部分完成状态,不能悄悄继续消耗资源。
九、重试必须与幂等绑定
查询类步骤可对瞬时失败有限重试;写入和外部动作只有在目标能力支持幂等键时才允许自动重试。退避、次数和可重试错误集合都由策略定义。
interface RetryPolicy {
maxAttempts: number
retryableCodes: ReadonlySet<string>
baseDelayMs: number
}
function idempotencyKey(taskId: string, stepId: string, revision: number): string {
return `${taskId}:${stepId}:${revision}`
}
用户拒绝授权、参数无效和能力不存在不是瞬时错误,重复请求只会制造干扰。
十、验证结果而不是相信结果
工具调用成功只说明获得了响应,不说明业务目标完成。输出先通过结构校验,再执行领域规则检查;重要结果还需要第二来源或确定性计算验证。
interface EvidenceRef {
stepId: string
source: string
observedAt: number
digest: string
}
interface VerifiedResult<T> {
value: T
evidence: ReadonlyArray<EvidenceRef>
confidence: 'verified' | 'partial' | 'unverified'
}
无法验证时明确返回“不确定”,不能用语言润色掩盖证据缺失。
十一、可观测性必须保护隐私
日志记录任务号、步骤号、能力名、契约版本、耗时、结果码和预算消耗。会话正文、凭据、个人信息和完整工具结果默认不入日志。
interface StepMetric {
taskId: string
stepId: string
capability: string
elapsedMs: number
outcome: 'ok' | 'failed' | 'cancelled' | 'timeout'
}
跨端链路使用关联 ID 追踪,但关联 ID 本身不包含用户身份。错误日志也先脱敏再持久化。
十二、以失败注入完成验收
测试至少覆盖:计划依赖成环、能力未注册、输入校验失败、权限拒绝、预算耗尽、用户中途取消、本地工具超时、A2A 对端离线、返回结构错误、重复响应、重试中的幂等、旧 revision 迟到,以及日志敏感字段扫描。
还要验证应用重启后的任务恢复策略:只恢复安全且有持久检查点的步骤;可能产生外部副作用的未知状态先进入人工确认,而不是自动重放。
工程化 Agent 的关键不是堆更多工具,而是让每个决策和副作用都经过清晰边界。通过状态机、能力契约、适配器、A2A 最小数据、预算、幂等和结果验证,Agent Framework Kit 接入才能随着业务增长保持可维护、可测试和可审计。
更多推荐




所有评论(0)