很多团队以为 Agent 接上富文本编辑器后,剩下只是“把字打进去”。真到生产环境,事故常出在另一层:模型知道要改哪一句,人却只看到整篇文档被误覆盖。最常见的现象不是不会写,而是改错块、删错段、撤销失控。这类问题一旦进入客服或知识库后台,风险甚至高于普通表单误填。⚠️
富文本编辑器表面像输入框,内部却是 block tree、selection range、history stack 三套状态机。Agent 如果只看 DOM 文本或截图,很容易把“当前光标所在位置”误认为“允许修改的范围”。真正要治理的,不是生成质量,而是写入动作和编辑结构是否被精确绑定。🧭
问题为什么总出在“选区”而不是“文案”
很多富文本编辑器会把段落、列表、引用和表格存成独立节点。Agent 若仅依赖contenteditable的可见文本,就会把“视觉上相邻”误判为“结构上连续”。结果是替换一个 bullet 时,把整个 list node 一起重写;修改摘要时,连后面的引用块也被吞掉。😵
另一类坑来自异步 UI。用户刚点击某一段,编辑器还没完成 selection flush,Agent 已经开始粘贴。此时 DOM 里的 anchor node、浏览器原生 selection、编辑器内部 transaction selection 可能并不一致。根因其实是选区 grounding 缺失。🔍
一套可复现的 Selection Grounding 方案
更稳的做法,是先把编辑动作从“按像素点点击”升级为“按 block id 提交补丁”。每次执行前,先读取编辑器导出的结构化快照:块类型、块顺序、当前 selection 起止位置、最近一次 transaction id。只有当目标 block id、选区范围和 transaction id 同时命中,才允许真正写入。✅
关键实现可以像下面这样:
asyncfunctionguardedReplace(editor,targetBlockId,expectedTxn,text){constsnapshot=editor.exportSnapshot();constblock=snapshot.blocks.find(b=>b.id===targetBlockId);if(!block)thrownewError('block_missing');if(snapshot.selection.blockId!==targetBlockId)thrownewError('selection_drift');if(snapshot.txnId!==expectedTxn)thrownewError('stale_snapshot');editor.replaceBlockText(targetBlockId,text);editor.pushUndoFence({reason:'agent_patch',blockId:targetBlockId});}这段逻辑看着简单,却比“找到编辑器然后 Ctrl+A 粘贴”可靠得多。它把可写范围压缩到单个 block,同时在提交后插入undo fence,保证用户一次撤销只回滚当前 Agent patch。🛡️
实战验证:为什么 Undo Fence 比全量回写更关键
在一个内部知识库编辑流里,团队对比了两种方案:一种是读取全文后重写目标段落,另一种是 block 级 patch + undo fence。前者在 200 次回放中有 11 次误覆盖相邻块,平均一次撤销会回滚 3.4 个编辑动作;后者误覆盖降到 1 次,且撤销粒度稳定在单 patch。📊
| 方案 | 误改相邻块 | 单次撤销回滚动作数 | 用户可恢复性 |
|---|---|---|---|
| 全文回写 | 11 / 200 | 3.4 | 低 |
| Block Patch + Undo Fence | 1 / 200 | 1.0 | 高 |
真正有价值的结论不是“模型更聪明了”,而是写入协议更保守了。富文本场景里,结构隔离往往比生成能力更决定可用性。📌
深度思考:不要把富文本当成普通表单
笔者认为,很多 Agent 产品在富文本场景里迟迟上不了线,不是因为模型不会写,而是因为系统没有把“编辑权限边界”产品化。表单只要字段绑定,富文本却需要 block identity、selection proof、undo segmentation 三层保护。少任何一层,线上就会出现难以复盘的误改。🤔
接下来 3 到 6 个月,这类能力大概率会从“编辑器插件技巧”升级成 Agent 基础设施。谁先把 selection grounding、undo fence、patch ledger 做成通用层,谁就更有机会把 Agent 稳定接进 CRM 和知识库后台。实用建议是:先限制 Agent 只能改单块,再逐步放开跨块操作,不要一上来追求整页自动改写。🚀
以上就是这类问题的核心治理思路。你在接入 Quill、ProseMirror、Slate 或 Notion 类编辑器时,踩过最难复现的坑是什么?欢迎在评论区聊聊。如果这篇文章对你有帮助,记得点赞、收藏和关注,后续会继续拆更难的 Agent 工程细节。⭐