ZGent 设计之旅 #1
多端同步与实时协作
王子博
2026 年 4 月 15 日
在中关村人工智能研究院·软件智能研究所,我们在思考并设计下一代 AI agent 的框架、人机界面与生态系统,项目代号为 ZGent。这篇文章是一系列文章中的第一篇,我将会在每篇文章中介绍我们的一个设计理念,以及相应的技术实现。
基于云端的在线应用(例如腾讯文档、印象笔记、滴答清单等)与传统的本地应用相比有许多好处:
- 不需要主动保存,断电、崩溃、误关闭时都不会丢失数据。
- 多端同步,关上电脑打开手机,不需要传输文件,立刻可以接着浏览和编辑。
- 可以多人实时协作,合作者只需打开分享链接即可同时在一份文档上工作。
- 很多云端在线应用可以在浏览器中直接使用,无需复杂安装和升级。
我们相信未来的 AI agent 产品一定也要基于云端,支持以下功能:
- 对话在云端运行,随时关闭窗口和重新打开都不影响进度。
- 可以分享会话让合作者实时围观,或者由合作者接手与 agent 继续对话。
- 不依赖用户设备上安装复杂的开发环境,可以在浏览器和手机上使用。
ZGent 的设计中,客户端都是“瘦”的,只从服务器获取会话当前状态,以及把用户操作发送给服务器。状态存储、agent 循环、工具调用执行等全发生在服务器上。服务器向客户端提供两个获取状态的接口:get 和 subscribe,前者用来拉取最新状态,后者用来订阅某个状态之后的更新事件流。
每个会话本身,以及会话列表界面,分别都用这套模型。对于一个会话,状态就是用户消息、agent 消息、思考、工具调用、图片等内容构成的列表。对于会话列表界面,状态就是每个会话的标题、当前运行情况、消息条数、最后更新时间等元信息。
基于这个模型,ZGent 可以支持各种不同的客户端热插拔,只要客户端调用接口获取状态并自己决定如何显示给用户即可。目前我们开发了 web 界面、命令行界面、桌面软件、手机 app,以及接入钉钉等聊天软件的机器人等,所有这些客户端可以同时打开一个会话,一起看到实时的 AI 输出。
具体实现时有几个需要注意的点:
- 在 get 和 subscribe 接口设计上,需要确保能够拿到某个时刻的状态快照,以及从这个时刻开始的所有更新事件,快照和接下来的事件都要有一致性,不能快照内部不一致或者漏了事件。典型的设计是,为每个事件递增编号,get 返回的快照也带编号,表示是某个事件之后的快照。客户端先启动 subscribe,然后再调用 get,根据 get 返回的快照编号扔掉这之前的事件。
- 客户端可能网络缓慢或不稳定,不能阻塞住服务器。所以 get 接口不能简单锁住内存中表示会话状态的数据结构,而应该立刻拷贝一份或序列化成字节串,然后再慢慢发送。subscribe 接口需要为每个订阅者分别分配消息队列,来解决不同订阅者接收速度不一致的问题。如果某个订阅者太慢以至于消息队列满了,将它踢掉,让它重新同步。
- 同时编辑时的冲突处理问题。目前 ZGent 对于简单操作,例如发送消息,是不解决冲突的,直接依次执行。对于复杂操作,例如回滚对话历史,可以限制只能在 agent 没在工作时进行,并且发送操作时带上前端当前看到的最新事件编号,如果服务器执行时发现这个编号已经过期,中间产生过新的事件,就让操作失败。未来如果发现新消息的编辑框也有必要像协作文档一样实时共享的话,可能需要引入更复杂的编辑冲突处理方案。
一旦实现了这样的客户端热插拔机制,实时协作功能很容易实现,因为不同账号同时打开一个会话和同一个账号的多个客户端同时打开一个会话,在程序逻辑上是相同的,只需要增加权限模型和分享界面即可。
ZGent 还考虑了一个细节:用户发送的每条消息都是带用户名字段的,客户端可以在界面上呈现,agent 也可以根据这一信息更好地理解对话。