技术解构:从多渠道消息到AI操作系统的工程演进

0 阅读9分钟

理解一个复杂系统的设计,最好的方式是沿着它的演化轨迹,看看每一次迭代解决了什么核心问题。这篇文章从一个实际项目——我们暂且称它为“Claw”系统——的演进历程出发,拆解它如何从一个简单的消息中继,逐步成长为能够操控本地桌面的AI操作系统。

图片 5.png

一、演化史:每一次重构都在解决什么

阶段一:消息管道 项目最早的形态非常简单:一个运行在本地机器上的脚本,通过WhatsApp的第三方协议库接收消息,调用一次大模型API,返回文字回复。这个阶段的核心抽象是webhook——消息进来,触发一次函数调用,结束。没有会话管理,没有工具调用,AI只是被当作一个文本生成器。

阶段二:Agent运行时与多渠道接入 真正的质变发生在引入了一个外部Agent框架(这里我们称之为“Pi核心”)之后。这个框架提供了标准化的Agent循环:接收消息→调用大模型→解析工具调用→执行工具→结果回传→继续循环直到结束。系统从一个“一问一答”的脚本,变成了一个有状态、能调用工具的Agent

与此同时,两周内接入了五个消息平台(Telegram、Discord、Signal、iMessage等)。每个平台的消息格式、API风格、能力集完全不同。这催生了两个关键设计:

  • 通道适配器模式:不设计大一统的接口,而是拆分成细粒度能力接口(如发消息、处理群组、获取回执),每个通道只实现它支持的那部分。
  • 统一网关:从命令行工具变为常驻后台服务,所有客户端通过WebSocket统一接入,负责消息路由、会话管理、任务调度。

阶段三:平台化与插件系统 当系统功能膨胀到一定程度,必须引入扩展机制,让新功能以插件形式生长,核心代码库保持稳定。为此落地了三层架构:

  1. 插件系统:社区开发的插件通过实现register(api)函数,可以注册新渠道、新工具、新钩子(在消息流水线特定节点插入逻辑),甚至扩展网关的HTTP路由和后台服务。为了解决Node.js生态ESM和CJS模块格式的兼容问题,采用运行时编译加载器统一处理,插件无需预编译,写完即可安装运行。

  2. 本地记忆机制:让AI拥有跨会话的长期记忆。文本切片后转为向量,存入本地SQLite,用向量扩展做余弦相似度检索。搜索采用混合策略——向量语义匹配与关键词检索(BM25算法)兼顾,既保证“意思相近”又保证“关键词命中”。所有数据留存在本地磁盘。

  3. 技能市场:插件解决了渠道和工具的扩展,但AI的行为模式怎么共享?答案是技能声明文件——本质是注入系统提示词的描述文件,描述AI在特定场景下该怎么做(比如“操控桌面”、“自动测试代码”)。技能有独立的注册中心,安装、加载有明确的优先级规则,社区通过点赞、评论进行治理。

二、核心子系统深度拆解

1. Agent运行时:大脑的构造

Agent运行时是系统的核心,它建立在分层架构之上:

  • 底层是模型抽象层:把十几家模型供应商的API统一成一个流式调用接口。每个供应商实现一个适配函数,将各自私有的流式响应(文本片段、思考过程、工具调用开始/结束)转成标准事件序列。模型注册表是自动生成的,包含每个模型的成本、上下文窗口、支持的多模态类型。
  • 中间是Agent运行时:实现核心循环:用户消息进入→流式调用LLM→解析工具调用→按序执行工具→结果返回LLM→继续循环。工具定义使用模式验证库,运行时自动校验参数。
  • 上层是会话管理层:提供工厂方法组装工具集、上下文钩子和会话存储。会话存储用结构化文本文件记录对话树(每条消息有唯一ID和父ID),支持分支、恢复和压缩。上下文处理分两步:先在消息层面裁剪(比如删除过旧的消息),再把自定义消息类型转成LLM能理解的标准格式。

系统在此基础上包裹了六层能力,让它从通用Agent框架变成多渠道AI助手:消息队列、会话恢复、上下文压缩、群聊管理、文件处理和任务调度。

2. 消息全链路设计

一条消息从进入系统到收到回复,经过的流水线有明确的分层:

两个值得关注的设计细节:

  • 消息转向:当Agent正在生成回复时,如果用户又发来一条消息,普通系统会让后者排队等待。这里通过“转向”机制把新消息实时注入当前正在运行的Agent会话,AI会立刻调整回复方向——就像和人说话时补了一句“等等,我改主意了”。
  • 仿人延迟:回复不是一次性弹出,而是分块发送,块间插入随机间隔,模拟真人打字节奏。在即时通讯场景里,这让对话体验更自然。

3. 通道适配器:统一异构平台的设计模式

WhatsApp有已读回执,Telegram有复杂的群组管理API,Discord有细粒度的权限体系,Signal几乎什么管理接口都没有——每个平台的能力完全不同。

这里的做法不是设计一个大而全的接口让每个通道都实现,而是拆成十种细粒度适配器,每个通道只实现它需要的子集:

  • WhatsApp实现了心跳适配器(因为协议库连接不稳定,需要心跳保活)
  • Discord实现了安全适配器(有复杂的权限体系需要验证)
  • Signal不需要群组适配器(因为没有群管理API)

社区开发新渠道插件时,用插件SDK实现同样的接口即可接入,不需要改动核心代码。

4. 桌面操控能力的技术实现

让AI能够看见并操控桌面,是系统最具突破性的能力。用户在聊天窗口说“帮我看看屏幕上是什么”,AI就能截屏、理解画面内容、告诉你答案。说“点击登录按钮”,它就能找到按钮并点击。

这背后是一个独立的桌面自动化工具,让AI拥有“眼睛”和“手”:

  • 视觉能力:截屏、录屏、标注UI元素(给每个按钮/输入框分配ID),配合AI视觉分析理解画面
  • 操作能力:点击、打字、按键组合、滚动、拖拽,支持定位到具体UI元素
  • 应用管理:启动/切换/关闭应用,管理窗口大小和位置,读写剪贴板

典型工作流是:截屏标注→AI识别元素ID→点击/输入→再截屏确认结果,全程在聊天窗口完成。

这里有一个关键的工程挑战:macOS的屏幕录制和辅助功能权限是按应用授予的,但AI Agent调用的是命令行工具。解决方案是采用“桥接”架构——命令行通过UNIX Socket连接到宿主应用内的桥接进程,桥接进程先验证调用方的代码签名和团队ID,通过后才借出宿主应用已获得的权限执行操作。用户只需在系统设置里授权一次宿主应用。

元素检测的实现也有讲究:截屏时同步遍历系统的辅助功能树,把每个可交互元素按类型编号——按钮B1、B2,输入框T1、T2。遍历有严格的限制(深度8层、子节点200个、150毫秒超时),检测结果缓存1.5秒避免重复遍历。后续点击B1就能直接定位到目标元素。

这个桌面工具本身也内置了独立的Agent循环,可以独立执行多步桌面任务——不经过主系统,直接命令行调用就能截屏→分析→点击→输入→确认,循环直到完成。

5. 调度器:不只是定时任务

系统中的定时任务不是简单的间隔触发,而是一个生产级调度器:

  • 确定性偏移:如果设置了100个“每天早上9点”的定时任务,不会同时触发——用每个任务ID的哈希值做确定性偏移(默认在5分钟窗口内分散),避免所有任务同一秒涌入,导致CPU和API调用瞬间过载
  • 两种执行模式:系统事件模式(把消息注入主会话,像用户发了一条消息)和独立Agent模式(启动独立的Agent运行,互不干扰)
  • 容错机制:失败后指数退避重试(30秒→1分钟→5分钟→15分钟→1小时),连续失败触发告警,临时会话自动回收

6. 上下文引擎:长对话的记忆管理

大模型有上下文窗口限制,聊久了历史就会超出。底层框架提供了基础的上下文处理管线,系统在此基础上实现了自己的上下文引擎,定义了五个生命周期钩子:

  • 初始化
  • 新消息进入
  • 组装发给模型的上下文
  • 上下文太长时压缩
  • 一轮对话结束后清理

默认实现用令牌计数和大模型摘要来压缩历史对话。但整个上下文引擎是可插拔的——社区可以写一个完全不同的实现(比如基于向量检索的长期记忆),替换进去不需要改一行核心代码。

三、结语:意图穿透介质的工程实践

从消息中继到AI操作系统的演化,本质上是在做同一件事:让用户的意图能够穿透不同的消息协议、穿过归一化的流水线、穿过大模型的概率空间、穿过工具调用,最终变成屏幕上的一次点击、磁盘上的一个文件、终端里的一行输出。中间的每一层抽象——通道适配器、Agent运行时、上下文引擎、桥接架构——都是为了减少这条路径上的摩擦。

智能的本质不是计算,而是与环境之间有效的信息交换。这样的系统所做的,与其说是“让AI用工具”,不如说是缩短人的意图与世界的状态之间的距离。每一个技术细节的设计,都是为了让这个距离再近一点。

项目免费体验: www.jnpfsoft.com/?from=001YH…