10. 多渠道支持
本章定位
在实际的应用开发中,个人助理往往需要支持多种接入渠道(例如网页端、微信、Telegram 机器人或桌面插件),使用户在不同终端下都能与其交互。
但是,在我们的 L1(Harness 101)阶段中,我们将贯彻“只做接口设计预留,不编写任何具体渠道实现”的原则。
原因在于:
- 我们当前的首要任务是确保核心 Harness 包(
@hachimi/core)中的逻辑与状态机足够干净稳定。 - 多渠道接入属于最外围的“网络输入层”,如果过早将复杂的第三方 Webhook 轮询、Tauri IPC 消息分发等细节引入核心,会极大干扰我们对 Agent 原理的研究。
- 保持项目体量轻量,便于学习和本地调试。
在本章中,我们将简要说明如何通过协议解耦为多渠道做扩展预留。
核心解耦原则:核心不绑定渠道
多渠道架构设计的核心思想是:Harness 核心代码绝不直接依赖任何第三方交互平台协议。
text
┌────────────────────────────────────────────────────────┐
│ 外部渠道层 │
│ CLI Desktop App REST API Server Telegram │
└─────┬────────────┬────────────────┬──────────────┬─────┘
│ │ │ │
└────────────┼────────────────┴──────────────┘
│ 1. 各个渠道适配器拦截请求
│ 封装为统一的 IncomingMessage
▼
┌────────────────────────────────────────────────────────┐
│ Harness 核心包 │
│ (Agent / Memory / Session) │
└──────────────────────────┬─────────────────────────────┘
│ 2. 核心计算完毕
│ 吐出统一的 OutgoingMessage
▼
┌────────────────────────────────────────────────────────┐
│ 渠道转换输出 │
│ stdout Tauri IPC SSE Stream Webhook │
└────────────────────────────────────────────────────────┘Harness 核心本身扮演一个纯净的数据转换层:
- 接收统一的格式输入。
- 返回统一的格式响应。
- 具体的协议转化和通信,完全交由外围的独立包(Channel Adapters)自行实现。
统一输入输出接口
我们在 packages/core/src/types/index.ts 中前瞻性地留下了这两个数据契约:
ts
/**
* 渠道输入定义
*/
export interface IncomingMessage {
sessionId?: SessionId;
userId: UserId;
channel: ChannelType; // 枚举值,标注消息的来路
content: string;
attachments?: Array<{ type: string; url?: string; data?: Buffer }>;
metadata?: Record<string, unknown>;
}
/**
* 渠道输出定义
*/
export interface OutgoingMessage {
sessionId: SessionId;
content: string;
toolCalls?: ToolCall[];
metadata?: Record<string, unknown>;
}在 L1 的 CLI 环境中,我们在 scripts/chat.ts 里所做的事其实就是直接扮演了这个适配器的角色:读取控制台文本,包装送入 agent.run(),拿到文本后再用 console.log 打印出来。
代码目录中的占位预留
为了展示如何在 Monorepo 中规划多渠道结构,我们在工作区中进行了物理目录分层:
packages/channels/cli/、packages/channels/api/(预留占位)apps/cli/(当前已实现的 CLI 客户端)apps/server/(预留用于托管 REST API 或 Express Bot Webhook 的服务器端应用)
通过这种多包机制,后续如果你想要增加 Telegram 支持,只需在 packages/channels/telegram 下编写适配代码,完全不需要改动 packages/core。
本章总结
本章我们:
- 阐述了 Core 与 Channels 分离的解耦理念。
- 了解了
IncomingMessage和OutgoingMessage数据传输契约。 - 规划了 Monorepo 下渠道相关的多包结构。