ASCF Agent 详细设计方案

1. 概述

ascf-agent 是运行在 HarmonyOS 设备上的端侧 AI Agent,基于 ASCF (Atomic Service Cross Framework) 开发。它集成了 LLM 对话、Skill 加载、工具调用和 FlexView 卡片渲染能力。

1.1 设计目标

  • 端侧 AI 助手:在 HarmonyOS 设备上运行完整的 AI Agent
  • LLM 客户端:支持兼容 OpenAI API 的 LLM 服务
  • Skill 系统:可扩展的 Skill 加载与执行框架
  • 工具调用:支持 Function Calling 和 MCP Server 工具
  • 卡片渲染:通过 FlexView 卡片引擎实现富 UI 交互

1.2 项目结构

ascf-agent/
├── entry/                     → HarmonyOS 入口 App
│   ├── src/main/ets/
│   │   ├── entryability/EntryAbility.ets
│   │   └── pages/Index.ets    → 主页面
│   └── src/main/resources/
│       └── rawfile/react/     → JS Bundle (FlexUI + React)
├── agent-runtime/             → Agent 运行时库
│   └── src/main/ets/
│       ├── AgentRuntime.ets           → 公开外观类
│       ├── AgentRuntimeConfig.ets     → 配置类型
│       ├── core/
│       │   ├── AgentLoop.ets          → Agent 主循环
│       │   └── AgentTypes.ets         → 类型定义
│       ├── llm/LlmClient.ets         → LLM API 客户端
│       ├── tools/
│       │   ├── ToolRegistry.ets      → 工具注册中心
│       │   ├── ToolExecutor.ets      → 工具执行器
│       │   └── BuiltinTools.ets      → 内置工具
│       ├── cards/
│       │   ├── CardRegistry.ets      → 卡片注册中心
│       │   └── CardRenderer.ets      → 卡片渲染器
│       ├── mcp/
│       │   ├── McpConfigLoader.ets   → MCP 配置加载
│       │   └── McpTypes.ets          → MCP 类型
│       ├── ui/                        → UI 组件
│       │   ├── AgentChatView.ets     → 对话视图
│       │   ├── ChatMessageList.ets   → 消息列表
│       │   ├── ChatInputBar.ets      → 输入栏
│       │   ├── MessageBubble.ets     → 消息气泡
│       │   ├── MarkdownRenderer.ets  → Markdown 渲染
│       │   ├── FlexCardView.ets      → FlexView 卡片
│       │   ├── ChainOfThought.ets    → 思考链展示
│       │   ├── TypingDots.ets        → 打字动画
│       │   └── UIMessageTypes.ets    → UI 数据类型
│       ├── utils/Logger.ets          → 日志工具
│       └── Index.ets                 → 模块入口
├── AppScope/                  → 应用配置资源
├── build-profile.json5        → 构建配置
└── scripts/                   → 构建脚本

1.3 构建配置

ascf-agent 包含两个 HarmonyOS 模块:

// build-profile.json5
{
  modules: [
    { name: "entry", srcPath: "./entry" },
    { name: "agent_runtime", srcPath: "./agent-runtime" }
  ]
}

2. 架构设计

┌──────────────────────────────────────────────────────┐
│                    UI Layer (ArkUI)                     │
│  AgentChatView / ChatMessageList / MarkdownRenderer   │
├──────────────────────────────────────────────────────┤
│                  AgentRuntime (外观)                    │
│  ┌─────────────┐  ┌──────────────┐  ┌─────────────┐  │
│  │  LlmClient  │  │  AgentLoop   │  │CardRenderer │  │
│  └──────┬──────┘  └──────┬───────┘  └──────┬──────┘  │
│         │                 │                  │          │
│  ┌──────┴─────────────────┴──────────────────┴──────┐  │
│  │            Tool & Card Registry                    │  │
│  │  ┌──────────────┐  ┌──────────────┐              │  │
│  │  │ ToolRegistry │  │ CardRegistry │              │  │
│  │  │ ToolExecutor │  │   (FlexView) │              │  │
│  │  └──────────────┘  └──────────────┘              │  │
│  └────────────────────────────────────────────────────┘  │
├──────────────────────────────────────────────────────┤
│              MCP (Model Context Protocol)              │
│  McpConfigLoader → 加载 mcp.json → 注册 Tool + Card   │
├──────────────────────────────────────────────────────┤
│                External Services                       │
│  LLM API (OpenAI Compatible) / MCP Servers            │
└──────────────────────────────────────────────────────┘

3. 核心模块

3.1 AgentRuntime(外观类)

AgentRuntime 是 agent-runtime 库的公开入口,封装了所有内部模块。应用层只需实例化一个 AgentRuntime 即可使用全部功能。

class AgentRuntime {
  constructor(config: AgentRuntimeConfig)
  setContext(context: Context): void
  initialize(): Promise<void>
  run(userMessage: string, history: AgentMessage[], callbacks: AgentRunCallbacks): Promise<void>
  cancel(): void
  handleCardEvent(event: string): string
  getRegisteredCards(): CardRegistryEntry[]
  destroy(): void
}

配置项 (AgentRuntimeConfig):

配置 类型 默认值 说明
baseUrl string? - LLM API 地址
apiKey string? - API Key
model string? deepseek-chat 模型名称
maxIterations number? 15 最大 Agent 循环次数
mcpConfigPaths string[]? [] MCP 配置文件路径

3.2 LlmClient(LLM 客户端)

通用的 LLM API 客户端,支持任何兼容 OpenAI Chat Completions API 的服务。

LlmClient
  ├── config: LlmClientConfig (baseUrl, apiKey)
  ├── chat(messages, tools?, systemPrompt?, model?)
  │   └── 支持 Streaming (SSE) 响应
  ├── cancel()              → 取消当前请求
  └── 支持的模型: deepseek-chat, GPT-4, Claude 等

3.3 AgentLoop(Agent 主循环)

Agent 核心循环实现了标准的 LLM Agent 工作流:

用户消息
  │
  ↓
[构建 messages + systemPrompt + tools]
  │
  ↓
[调用 LLM] ←─────────────────┐
  │                           │
  ├── text_delta → 流式输出文字  │
  ├── reasoning → 展示思考过程   │
  └── tool_calls → 执行工具     │
      │                       │
      ↓                       │
  [ToolExecutor.execute()]    │
      │                       │
      ↓                       │
  [结果追加到 messages] ──────┘
      │
      ↓ (无更多 tool_calls)
[返回最终文本 + 卡片]

AgentPhase 状态:

Phase 说明
THINKING 正在思考/输出文本
TOOL_CALLING 检测到工具调用意图
TOOL_EXECUTING 正在执行工具
IDLE 完成当前轮次

3.4 Tool System(工具系统)

ToolRegistry(工具注册中心)

ToolRegistry
  ├── register(tool)              → 注册工具
  ├── getLLMToolDefinitions()     → 获取 LLM Function Calling 格式的工具定义
  └── execute(name, args)         → 执行工具

ToolExecutor(工具执行器)

ToolExecutor
  ├── execute(toolCalls)          → 批量执行工具调用
  └── 返回 ToolResult[]

BuiltinTools(内置工具)

系统预注册的基础工具,如:

  • 日期/时间查询
  • 设备信息获取
  • 基础计算

3.5 MCP Integration(MCP 集成)

通过 Model Context Protocol (MCP) 加载外部工具和卡片:

McpConfigLoader.loadConfig(mcpJsonPath, toolRegistry, cardRegistry, context)
  │
  ├── 解析 mcp.json
  ├── 注册 Tool (ToolRegistry.register)
  └── 注册 Card (CardRegistry.register)

3.6 Card System(卡片系统)

FlexView 卡片引擎的集成层:

CardRegistry
  ├── register(entry)            → 注册卡片模板
  └── getAll()                   → 获取所有卡片

CardRenderer
  ├── resolve(toolOutput)        → 根据工具输出匹配卡片
  └── 返回 CardRenderData        → UI 层展示

3.7 UI 组件

组件 说明
AgentChatView 对话主界面,组合所有子组件
ChatMessageList 消息列表,支持虚拟滚动
ChatInputBar 输入栏,支持文本和语音
MessageBubble 消息气泡,区分用户/助手样式
MarkdownRenderer Markdown 渲染,支持代码高亮
FlexCardView FlexView 卡片渲染容器
ChainOfThought 思考链/推理过程展示
TypingDots 打字动画指示器

4. 数据流

4.1 对话流程

1. 用户输入 (ChatInputBar)
   │
2. AgentRuntime.run(userMessage, history, callbacks)
   │
3. AgentLoop 启动循环
   │  ├── onTextDelta     → UI 流式显示文字
   │  ├── onReasoningDelta → ChainOfThought 展示
   │  ├── onToolCallStart → 显示工具调用状态
   │  ├── onToolCallEnd   → 工具结果 + 可能的卡片展示
   │  └── onCardReady     → FlexCardView 渲染卡片
   │
4. onComplete(finalMessage) → 消息历史更新

4.2 卡片交互流程

1. 工具返回数据 → CardRenderer.resolve()
   │
2. 匹配到 CardRegistry 中的模板
   │
3. FlexCardView 渲染 FlexView 卡片
   │
4. 用户与卡片交互 (点击按钮等)
   │
5. AgentRuntime.handleCardEvent(event)
   │  └── 将事件格式化为用户消息文本
   │
6. 重新进入 AgentLoop,上下文包含卡片交互信息

5. 构建与部署

5.1 构建命令

# 完整开发周期: 构建 HAP → 安装 → 启动
./build.sh dev-agent

# 仅构建 HAP
./build.sh build-agent

# 清理 + 构建
./build.sh clean-build

# 清理
./build.sh clean

# 查看日志
./build.sh logs

# 状态检查
./build.sh status

5.2 模块依赖

entry → agent-runtime (HarmonyOS 模块依赖)
agent-runtime → 无外部依赖 (纯 ArkTS/TypeScript)

6. 设计决策

6.1 为什么分离 entry 和 agent-runtime?

  • 复用性:agent-runtime 可作为独立库被其他 HarmonyOS 应用集成
  • 关注点分离:entry 负责应用配置和启动,agent-runtime 负责 AI Agent 逻辑
  • 独立测试:agent-runtime 可独立进行单元测试

6.2 为什么用 AgentLoop 而非直接调用 LLM?

  • 多轮推理:Agent 可能需要多次工具调用来完成一个任务
  • 工具编排:AgentLoop 管理工具调用的序列化和上下文传递
  • 可取消性:用户可随时中断 Agent 执行

6.3 为什么选择 MCP 协议?

  • 标准化:MCP 是 Model Context Protocol 的行业标准,工具和卡片定义统一
  • 可扩展:通过 mcp.json 文件动态加载工具,无需修改代码
  • 生态兼容:与 Claude、GPT 等主流 Agent 生态的工具定义兼容

6.4 为什么支持 FlexView 卡片?

  • 富交互:纯文本对话不够,卡片可以提供按钮、表单、图表等交互
  • ASC Framework 原生:FlexView 是 ASCF 生态的轻量卡片引擎
  • 工具结果可视化:将工具返回的结构化数据渲染为可视卡片