在 DMR 的飞书插件中,我们引入了一套轻量的 "tape 子空间" 机制——
,tape.create、,tape.switch、,tapes.list。它不改变 AI 的底层能力,却从根本上改变了人与 AI 协作的粒度。
一、问题背景:单一会话的瓶颈
当你通过一个 IM(飞书/微信/Slack)与 AI 助手长期协作时,所有对话历史都堆在同一个 "tape" 里。这带来几个典型痛点:
上下文污染:上午在聊项目 A 的架构设计,下午问项目 B 的运维问题,模型会把 A 的上下文带到 B 的回答里。 串行阻塞:一个复杂任务正在执行(比如生成报告、等待审批),这期间你没法聊别的事,否则新消息会打断当前任务的推理链。 历史难以检索:所有话题混在一起, tapeSearch搜出来的结果杂乱无章。实验成本:想试一个新思路,但怕把当前干净的上下文搞乱,只能开一个新的群或新的会话。
传统解法是给每个话题建一个群。但这很笨重:群多了管理混乱,_bot 要加入每个群,配置权限也麻烦。
我们想要的,是在同一个聊天窗口里,像操作系统切换线程一样,快速切换不同的上下文空间。
二、Tape Switch 是什么
Tape Switch 是 DMR 飞书插件内置的一组轻量命令:
,tape.create <name> | feishu:p2p:oc_xxx:hello) |
,tape.switch <name> | |
,tapes.list | |
,tape.switch default |
每个子 tape 是完全独立的存储空间:
有自己的对话历史 有自己的 anchor(session/start) tapeSearch只搜索当前 tape 的内容不同 tape 之间并行执行,互不阻塞
三、核心优势
1. 上下文隔离(Context Isolation)
不同 tape 的对话历史完全隔离。你在 project-a tape 里讨论的 k8s 配置,不会泄漏到 project-b tape 的代码评审中。
这相当于给 AI 助手配了多个独立的 "工作记忆区"。
2. 并行执行(Concurrency)
传统模式下,同一个 chat 的所有消息串行排队:任务 A 在等审批,任务 B 必须等 A 结束后才能开始。
Tape Switch 改造了队列模型——**路由键从 chat_id 改为 tape_name**。不同 tape 拥有独立的 worker goroutine:
feishu:p2p:oc_xxx → worker-1(默认 tape)feishu:p2p:oc_xxx:hello → worker-2(hello tape)feishu:p2p:oc_xxx:world → worker-3(world tape)三个任务真正并行,不再互相等待。
3. 状态可辨识(Labeled Reply)
当多个 tape 同时运行时,AI 的回复会自动带上 tape 标签:
**[hello]**项目 A 的部署脚本已生成,请确认是否执行。**[world]**项目 B 的代码扫描结果:未发现高危漏洞。你一眼就知道这条回复属于哪个上下文,不会因为并行而产生混乱。
4. 零成本切换
所有操作都在同一个聊天窗口完成,不需要:
新建群 重新 @bot 重新配置权限
,tape.switch hello 和 ,tape.switch default 来回切换,成本接近零。
四、典型应用场景
场景一:多项目并行运维
你是 SRE,同时负责 3 个微服务的运维。以前的做法:
群 A 讨论 service-a 群 B 讨论 service-b 群 C 讨论 service-c
用 Tape Switch 后,一个单聊搞定:
, tape.create svc-a, tape.switch svc-a这里讨论 service-a 的告警..., tape.create svc-b, tape.switch svc-b这里讨论 service-b 的发布..., tape.switch svc-a切回来继续处理 service-a 的审批...每个项目有独立的上下文,不会串味;三个项目的任务可以并行推进。
场景二:"实验模式" 与 "主线路" 分离
你正在让 AI 写一个核心模块的代码(主线 tape)。突然想到一个新思路,想试试另一种实现,但怕搞乱当前干净的上下文:
, tape.create exp-v2, tape.switch exp-v2尝试另一种实现...(不满意), tape.switch default回到主线继续...实验失败?直接切回默认 tape,主线上下文毫发无损。
场景三:审批流水线与主任务分离
AI 执行一个高风险操作(如 kubectl delete),触发了人工审批。传统模式下:
你回复 y之前,不能发别的消息因为新消息会排在这个任务后面,整个 chat 被阻塞
用 Tape Switch:
AI: 检测到高危操作,请审批:kubectl delete deployment/xxx(当前在默认 tape,等待审批), tape.create side, tape.switch side先处理别的事..., tape.switch defaulty // 审批通过,主任务继续审批等待在默认 tape 的 worker 里阻塞,但 side tape 的 worker 完全不受影响。
场景四:不同角色上下文
让 AI 在不同 tape 里扮演不同角色:
, tape.create reviewer, tape.switch reviewer你现在是严格的代码审查员,只关注安全漏洞..., tape.create writer, tape.switch writer你现在是技术文档作者,请生成 API 文档..., tape.create architect, tape.switch architect请从架构角度评估这个设计...每个角色有独立的系统提示和对话历史,不会因为角色切换导致 "人格分裂"。
五、技术要点
实现并不复杂
核心改动只有三个:
QueueKey 改为 tape name(receiver.go)
// 之前QueueKey: chatID// 之后QueueKey: tape接口增加 tapeName 参数(queue.Handler)
ReplyAgentOutputWithContext(ctx, chatID, triggerMessageID, tapeName, inThread, output)回复时加标签(plugin.go)
if label := shortTapeLabel(tapeName, chatID); label != "" { output = fmt.Sprintf("**[%s]**\n%s", label, output)}
没有引入新的存储层,没有改 tape 的核心逻辑,只是改变了路由策略和呈现层。
审批不受影响
审批的等待/解析基于真实 chat_id,和 tapeOverrides 无关。切换 tape 时,未完成的审批依然会在正确的 chat 里被消费。
六、总结
Tape Switch 不是什么革命性技术,但它解决了一个非常实际的协作问题:如何在同一个 IM 会话中,以零成本管理多个独立的 AI 上下文。
它的设计哲学是:
轻量:不新建群、不重新配置 隔离:不同 tape 互不污染 并行:不同 tape 同时执行 透明:回复带标签,用户始终知道自己处于哪个上下文
如果你正在用 DMR + 飞书做日常协作,不妨试试 ,tape.create——它可能会改变你和 AI 助手的工作方式。
夜雨聆风