当 AI Agent 加入 Yjs 房间时,三个假设会失效
将 LLM 作为一等公民级别的 Yjs peer 是一种明智的架构选择。然而,它打破了你的协作栈对 peer 对称性所做的默契假设。
大多数系统都假设所有 peer 都在人类的速度下工作。当一个 AI agent 每分钟生成 3,000 个单词时,它会破坏三个核心领域:吞吐量、撤销所有权以及 presence 节奏。
以下是修复方案。
- 停止写饥饿 (Write Starvation)
在 CRDT 模型中,没有中央服务器来限制客户端。Agent 可能会通过不断的写入使同步周期过载。这会剥夺人类用户在收敛窗口中的份额,导致光标滞后和更新丢失。
修复方案应位于应用层,而非传输层。在 LLM 流与 Yjs 写入之间使用令牌桶 (token bucket) 来限制 agent 的速度。
• 为队列操作设置容量。 • 设置填充速率,使 agent 的速度保持在人类饥饿阈值以下。
- 隔离撤销历史 (Undo History)
如果 agent 与用户共享同一个 origin,Ctrl+Z 就会变得一团糟。你无法区分人类的错误和 AI 的建议。
给 agent 一个独立的 origin。为 agent 使用一个单独的 UndoManager。
• 用户的 UndoManager 仅跟踪人类操作。 • agent 的 UndoManager 处理 AI 特有的操作。 • 将“拒绝 AI 建议”作为一个独立的 UI 按钮呈现,而不是将其绑定到默认的 Ctrl+Z。
- 合并 Presence 更新
AI agent 产生位置变化的速度超过了人类的视觉感知。广播每一次变化会在你的渲染周期中产生噪音。
你必须以不同的方式管理 agent 的 presence:
• 以固定间隔而非每次操作来合并 awareness 更新。
• 在 awareness 状态中添加一个 type 字段(例如 type: 'agent')。
• 利用这个 type 告诉你的渲染层以不同的方式处理光标。
agent-as-peer 模式是正确的构建方式。挑战在于使你的假设显性化。不要将速率限制、撤销隔离和 presence 合并视为边缘情况。要将它们视为核心需求。
Source: https://dev.to/norfolkd/when-an-ai-agent-joins-your-yjs-room-three-assumptions-break-50h8