聊天 Agent 真正危险的,不是不会写回复,而是草稿明明写对了,却在侧边栏一刷新后发给了错误对象。客服、IM 和协作系统里,这类事故常出现在未读重排、搜索切换和多会话并行处理中:模型还拿着上一轮会话的草稿,当前焦点已经落到另一个联系人。😵
很多团队把它当成一次普通误点,其实不是。草稿一旦脱离原来的会话作用域,后面的发送、转派、补充说明都会围绕错误收件人继续展开。问题核心不是“模型识别差”,而是系统没有证明这段草稿现在仍然属于当前对象。📌
[外链图片转存中…(img-VuHn0Xps-1780118075687)]
错的不是内容,而是收件人绑定 🧭
常见实现只检查输入框里“已经有内容”,就默认可以发送。但聊天界面的输入框通常是共享组件:会话切换后,旧草稿可能短暂保留;搜索结果跳转后,标题更新了,头像和线程 ID 却还没同步。此时草稿本身没错,错的是它不再属于当前会话。⚠️
更隐蔽的是自动补全和模板回复。模型上一秒还在给 A 总结问题,下一秒侧边栏因为新消息把 B 顶到最上面,焦点跟着切走,发送动作却沿用旧上下文继续提交。表面看像“模型说错话”,实际是收件人证明缺失。🔍
用 Draft Scope 把草稿锁回原对象 🛠️
更稳的做法,是在草稿生成时就记录Draft Scope:包含会话标题、联系人主键、线程 ID、最近一条消息摘要和生成时间。发送前再构造Recipient Proof,要求正文头部、侧边栏高亮项和发送框绑定的会话标识同时对齐。只有这组证据一致,发送动作才放行。✅
如果 proof 发现标题一致但线程 ID 不同,或者输入框草稿早于最近一次切会话事件,就直接清空草稿并回到会话确认。这样会多一次校验,却能挡住“内容正确、对象错误”的高代价事故。对生产系统来说,重写一句回复,比错发给客户便宜得多。🧱
draft=build_draft_scope()recipient=collect_recipient_proof()ifrecipient.thread_id!=draft.thread_id:discard_stale_draft()raiseRetryOnConfirmedThread()send_message(recipient.thread_id,draft.text)把三种做法放在一起看,区别会很明显:
| 方案 | 草稿归属记录 | 发送前收件人确认 | 常见事故 |
|---|---|---|---|
| 只看输入框非空 | 无 | 无 | 把旧草稿发错人 |
| 只看标题文字 | 弱 | 弱 | 同名联系人串会话 |
| Draft Scope + Recipient Proof | 强 | 强 | 误发概率最低 |
[外链图片转存中…(img-CKwuKAWw-1780118075722)]
会话 Agent 的门槛在提交链,而不在文采 🚦
笔者认为,聊天 Agent 能不能进生产,不取决于回复写得多像人,而取决于每一次发送前,系统能不能把“这段草稿属于谁”说清楚。只要草稿和收件人还靠界面焦点隐式绑定,侧边栏一变,事故就会发生。🤖
未来 3 到 6 个月,聊天型 Agent 的差距会越来越集中在提交链治理:草稿作用域、收件人证明、附件确认和发送回执会成为标配。谁先把这些约束工程化,谁才有资格把 Agent 放进真实客服和协作链路。📈
如果正在做聊天助手,不妨先检查一个问题:当前系统在点击发送前,验证的是“输入框里有话”,还是“这段话现在就是发给这个人的”。💬