
有次排查一个智能体项目的线上问题时我遇到一个很反常的现象同一个助手对话前几轮还会严格拒绝越权操作到了第 20 轮之后突然开始给出模糊的执行建议。系统提示词没有改模型没有换用户身份也没变唯一变化的是对话历史越来越长上下文管理触发了自动压缩。当时我下意识以为是模型抽风后来把压缩前后的完整输入对比完才意识到问题出在“上下文压缩”这个不起眼的机制上。这个话题值得认真写。上下文压缩的本意是解决长对话场景下的成本和容量问题对话轮数越多模型输入越长token 开销越大上下文窗口也迟早被塞满。于是很多智能体框架、Agent 平台和开发者的实践都加入了压缩逻辑把旧对话做摘要、裁剪或重构。但很少有人会主动去想安全规则如果也混在要被压缩的那段上下文里压缩之后它还是原来的那条规则吗这看起来像是一个可以靠“更聪明的压缩算法”解决的问题但真正深入以后你会发现它其实是一个架构问题安全规则的存储位置、注入方式和校验链路决定了压缩机制会不会成为规则失效的入口。1. 先理解一个反常识压缩不是省成本而是在改写记忆1.1 长对话为什么会失控以及压缩在这里扮演什么角色先还原一个非常常见的智能体工作流。假设你基于某个大模型 API 搭建了一个客服助手初始状态只有一段系统提示词里面规定了助手的人设、能力边界和几条安全规则。用户连续提问模型的每次调用都会把完整对话历史拼接到输入里。问题很快就来了对话超过一定轮数后输入长度不断膨胀。如果你用的是带上下文窗口上限的模型超出部分会直接报错如果你用向量库、滑动窗口或历史摘要来做记忆管理那么旧对话会被“浓缩”成一段摘要再拼接到下一次请求里。这个“浓缩”动作就是上下文压缩。很多团队会把压缩当成一个透明组件反正摘要还能反映对话大意不影响后续回复。但这里有一个经常被忽略的事实压缩不是简单地把旧内容丢弃而是对模型看到的信息做了一次有损重写。旧的原始对话中哪些内容被保留、哪些被合并、哪些被改写是由压缩策略决定的。而安全规则很多情况下就藏在这段旧对话或系统上下文里跟着一起被处理了。1.2 有损变换下的信息丢失不是偶然而是必然用一个生活化的类比来理解你在一张便签上写了很多事项空间不够之后你拿一张新便签把旧内容重新抄一遍。抄写时你会自然保留那些“你现在觉得重要”的信息丢掉那些“你认为不重要”的细节。问题在于“你觉得重要”和规则真正要求的“必须保留”往往不是一回事。上下文压缩的原理也类似。常见做法有两种一种是截断直接丢弃最早或最旧的消息另一种是摘要让模型对历史内容做提炼。截断的代价很直接规则如果出现在被裁掉的部分里就彻底消失了。摘要的代价更隐蔽压缩后的文本语义看似接近原文但条件、例外、否定词、精确数字可能被丢掉。这里最难处理的是“看起来还像样”的摘要。原始规则里写着“只有拥有管理员权限的用户才能执行导出操作否则拒绝”压缩后可能变成“拥有管理员权限的用户可以导出数据”。从语言上看后一句确实是从前一句提炼出来的但权限校验逻辑已经不完整了。模型是否会严格执行缺失的权限判断完全不可控。所以从工程经验看这个问题不能简单归因于模型抽风它就是压缩对安全规则做了一次不完整的语义改写。2. 安全规则的失效路径三种肉眼可见的变形2.1 被稀释规则在压缩时被当作低价值内容丢弃压缩策略在做摘要时通常会按“信息密度”“与当前问题的相关性”来筛选内容。安全规则往往是一段静态的、不带情感、不参与具体任务推进的说明。在海量用户对话中间它的相关性得分通常不高容易被摘要器当成背景信息处理。我见过一个类似的案例某个客服助手会在每轮回答前强调“不要透露内部操作日志”规则写在系统提示词里前面几十轮都正常。当对话历史增加到触发摘要的阈值后模型开始对用户的问题做出更直接的回答把内部日志的处理方式模糊地描述了出来。排查后发现摘要里并没有出现那条拒绝规则它在压缩过程中被当作低信息量内容过滤掉了。这个现象的本质是压缩策略的筛选标准是基于“当前任务相关性”设计的安全规则恰恰是那种与具体任务无关、但在任何任务里都必须生效的约束。把这两类内容交给同一个筛选器规则天然处于劣势。2.2 被截断条件、例外和动作边界被摘掉安全规则通常不是一个简单祈使句而是一套带条件的逻辑如果用户身份属于外部访客只能读取项目摘要不能读取完整代码。如果当前时间不在维护窗口禁止调用生产环境接口。如果导出文件包含手机号必须先用脱敏工具处理。这些规则进入压缩逻辑时很容易被压写成更短的形式比如“外部访客只能读取项目摘要”“当前可以调用生产环境接口”“导出文件需要脱敏”。从语义上看短句确实是原规则的子集但动作边界已经变了。这里最危险的一点是被截断后的规则不会让模型直接报错模型会非常自然地按照这个残缺版本去执行。于是原本应该被拒绝的请求在压缩后变成了被允许的操作。规则的条件、例外和边界是安全规则里最脆弱的区域。2.3 被冲突两条规则压缩后互相打架长对话里往往同时存在不止一条规则。比如A 规则不允许使用第三方工具处理敏感文件。B 规则允许使用内部沙箱工具处理敏感文件。这两条规则原本并行不悖第三方工具被禁止内部沙箱被允许。但在上下文压缩过程中如果两条规则被合并进同一条摘要模型可能得到“可以使用工具处理敏感文件”这个中间语义。更糟的情况是当用户后续提问“有没有工具能处理这个文件”时模型基于压缩后的合并语义可能直接推荐了第三方工具。这种冲突不完全由压缩算法导致指令顺序、上下文长度、其他用户请求都会产生影响。但压缩会显著增加冲突的概率因为它让原本边界清晰的规则变成了一段语义相近的模糊文本。从安全设计角度看规则冲突比规则丢失更难排查因为摘要里仍然保留了“处理敏感文件”这个关键词单独看好像没有大问题但实际已经偏离了原始约束。3. 更聪明的压缩也解决不了规则保真问题3.1 压缩目标的优化方向和安全规则并不一致很多人会提出一种思路既然压缩可能损坏规则那就设计一个更聪明的压缩器让它能识别安全规则并完整保留。从直觉上很合理但从工程角度看这个方案很难成立。原因是目标函数不一致。压缩器优化的核心指标通常是token 更少、语义更接近、对后续回答的帮助更大。而安全规则的要求是必须无条件保留完整语义不能省略任何条件。优化目标和约束目标本质上不是一回事。一个很聪明、很忠于原始语义的摘要器也可能在“以更少 token 表达信息”的压力下对安全规则做适当省略因为压缩器并不知道这条规则在系统安全中的权重。即便你可以在压缩过程中加入规则识别你仍然要面对一个很难解决的问题模型对规则的“理解”并不等价于程序对规则的“校验”。压缩后的文本无论看起来多正常最终都要受到模型生成时随机性和上下文漂移的影响。把安全寄托在模型的语义理解上本身就是高风险的做法。3.2 安全规则必须从 Prompt 上下文里抽离出来既然压缩会改写上下文那么最直接的办法不是让压缩变得更聪明而是让安全规则根本不出现在可压缩的上下文里。也就是说智能体的输入应该被拆成几层系统级约束层包含安全规则、权限边界、审计要求始终原样注入不允许被摘要、截断或改写。对话历史层包含用户与助手的实际对话是压缩机制唯一允许操作的对象。会话状态层包含当前用户信息、会话状态、需要持久化的中间结果按需保存。这是一种结构调整而不是参数调整。安全规则从“prompt 的一部分”升级为“系统运行时的约束配置”它不再是一个文本片段而是系统层在生成请求前就固化的条件。这样无论压缩策略如何变化规则层受到的干扰都只来自你主动修改规则而不是来自对话历史的压缩操作。下面是一个用于理解结构关系的示例# 示例结构将系统规则与可压缩历史分开维护 prompt { system: load_security_rules(), # 原样注入不参与压缩 history: compress(conversation_history), # 只允许压缩普通对话历史 session: load_session_profile() # 与规则相关的会话状态单独保存 }这不是某个平台的官方接口而是一种通用设计思路。但结构上的差异会直接决定安全规则在长会话中能不能稳定存活。3.3 抽离之后再谈压缩才是一个可维护的架构把规则抽离出来以后压缩机制本身的压力也变小了。压缩器只需要专注于一个目标尽量保留对话的上下文相关性。它不需要承担“识别哪些内容是安全规则”这个高级任务也不需要担心一次误删除导致权限边界消失。这样的架构还有一个额外好处规则层可以独立于对话内容做版本管理。当安全团队更新规则时不需要等待所有活跃会话迎来下一次压缩也不会出现只对部分会话生效的情况。规则变更的生效范围变得可控这对于审计和合规来说非常重要。4. 守住规则边界的四道工程防线4.1 第一道防线分层记忆把规则放到不可压缩层先做一件事盘点当前智能体系统里哪些内容在进入模型调用前会被压缩、截断或摘要。把安全规则类的静态约束全部挪到不可压缩层。不可压缩层可以放在系统提示词的开头也可以在调用链路上单独传入关键要保证它不经过压缩逻辑。在开发过程中可以在压缩函数入口做一个过滤拒绝处理标记为protected的内容# 示例逻辑受保护内容不进入压缩函数 def compress_history(history, protected_prefixes): compressible [msg for msg in history if not is_protected(msg, protected_prefixes)] return create_summary(compressible)这里需要明确一点系统提示词也可能被底层平台统一处理不同平台的行为不同。如果你使用的是 Dify、Coze 这类智能体平台建议在搭建工作流时确认平台对系统提示词和对话历史的处理方式不要默认规则一定会完整保留。4.2 第二道防线压缩后的规则语义校验压缩发生后不能只凭“摘要看起来没什么问题”就继续使用。工程上建议增加一道规则语义校验在压缩前后分别提取涉及安全规则的关键内容做一致性检查。校验方法可以从简单到复杂逐步加关键词检查规则中的关键禁止词、数字、条件词是否仍然存在。条件子句检查是否存在“只有”“如果”“否则”这类条件标记。向量相似度检查计算压缩前后文本的语义相似度低于阈值则触发告警。这几种方法都不能保证百分百发现语义变形但可以大幅提高问题暴露的概率。校验一旦发现异常建议采取保守策略放弃这次压缩结果回滚到未压缩版本同时对运维人员发出告警。4.3 第三道防线结构化规则与自然语言规则互补自然语言规则容易被压缩改写一个重要的替代方案是引入结构化规则。把关键安全策略从自然语言改写成机器可读的策略文件系统在校验输出前用程序逻辑来判断操作是否被允许。例如一条导出权限规则可以这样结构化{ rule_id: permission-export, resource: customer_data, action: allow, condition: current_user.permission contains export, on_deny: refuse_and_explain }结构化规则有两点价值一是压缩逻辑通常不会对这种 JSON 块做语义摘要丢失概率降低二是即使模型在生成时忽略了规则系统层仍然可以在返回结果前做一次程序化拦截为“模型没有遵守规则”设置兜底。当然结构化规则不是银弹。规则本身仍然可能被模型当作普通文本读取而且对复杂逻辑的描述能力有限。所以更合理的做法是自然语言规则负责给模型解释行为边界结构化规则负责在系统层做硬校验两者互补而不是互相替代。4.4 第四道防线审计日志与可回滚现场压缩过程会产生信息变化而安全规则失效往往要在数次会话之后才暴露。如果没有日志排查时只能靠猜。建议在压缩组件周围记录以下信息压缩触发时间、触发原因上下文长度超限、定时任务、手动触发压缩前上下文的原始片段压缩后的摘要结果被删除或合并的原始消息列表规则校验结果这些日志的价值不只是事后追责更重要的是可以复现现场。当一次异常行为发生后你可以在日志里找到“异常回答出现前上下文被压缩成了什么样子”快速判断规则是否在那一轮被改写。可回滚的现场是排查问题的第一步。5. 当规则异常时一条可以照着做的排查链路5.1 先判断现象属于哪一类失效不要一上来就怀疑模型能力或压缩算法。先给异常行为归个类规则完全丢失模型直接开始按自己的方式处理本应被限制的操作。规则条件丢失模型保留了大方向但没有执行条件判断。规则冲突模型在两个规则之间选择了更危险的解释。模型根本没有收到规则可能是注入顺序或配置问题与压缩无关。不同的现象对应不同的排查重点。如果发现模型在会话早期就表现异常大概率不是压缩问题而是初始 prompt 或平台配置问题如果异常都发生在上下文接近阈值、压缩被触发之后压缩链路就要优先排查。5.2 顺着输入、规则层、压缩策略、生成结果逐层定位我一般按这个顺序操作保留现场把异常发生那一轮的完整请求和响应保存下来。对比输入把压缩前的原始上下文和压缩后的模型输入放在一起 diff看安全规则是否还在是否被改动。检查规则层确认规则是原样注入还是被后续的某些消息覆盖了优先级。检查压缩策略定位问题是否在压缩器选出摘要的那一次请求中发生。做对照实验临时关闭上下文压缩用同样的会话重新跑一遍看规则是否恢复。这一步能帮你在几分钟内缩小到具体环节。如果关闭压缩后规则恢复说明问题几乎可以确定出在压缩链路如果关闭压缩后异常依旧那就要检查规则本身的注入逻辑和模型行为。5.3 一条最小化的验证路径如果你现在没有现成的日志链路可以先搭一个最小验证脚本。用同样一组预置对话分别跑三组对比不压缩直接拼接全部历史。截断压缩丢弃最早的内容。摘要压缩用模型生成历史摘要。然后在每组对比中分别问几个会触发安全规则边界的问题。看模型在不同处理模式下是否依然遵守约束。只要出现了不一致就说明压缩逻辑确实影响到了安全规则。这个验证路径可以在本地快速跑通不需要引入复杂平台能力目的是在正式修复前确认问题方向和影响面。6. 哪些团队真正需要关心这个问题6.1 风险最高的不是大厂而是快速上线的业务型智能体大厂通常有专门的安全团队会在智能体框架层设计规则保护机制。而很多业务团队为了快速交付选择在 Dify、Coze 这类平台上搭智能体把安全规则直接写在提示词里。这类场景有一个共同特征初始原型能跑通规则在短会话里也能生效但随着真实用户在长对话中不断提问上下文压缩被触发后规则失效的风险开始累积。业务方往往没有足够精力去做压缩前后对比也没有审计日志可用。如果你正在用平台搭建智能体第一步不是研究压缩算法而是确认平台对提示词和历史消息的处理方式。如果有隔离机制优先使用如果没有就要在设计工作流时尽量避免让安全规则进入可压缩区域或者增加输出侧校验。6.2 从原型到生产规则保护的投入应该在哪一阶段开始很多团队的想法是先用最小方案跑通后续再补安全。这个思路在纯原型阶段没有问题但一旦智能体要接入真实用户、真实数据或真实操作权限规则保护就必须立即介入。我建议的分层策略是原型验证阶段可以接受默认配置重点验证智能体回答问题的基础能力。小范围试用阶段加入规则层与历史层分离即使只有简单隔离也好过混在一起。生产环境阶段必须完成规则校验、审计日志、结构化策略、输出兜底四道防线。这里最容易踩的坑是等到安全事件发生后才开始补因为那时候你很难判断是某一轮压缩导致的规则变形还是长期累积后暴露的模型问题。日志和校验链路应该在问题发生之前就在运行。6.3 边界这不是所有智能体的头号风险上下文压缩是安全规则失效的一条隐蔽路径但它不是唯一原因甚至也不是所有智能体的头号风险。如果你的智能体只是单轮问答每次调用都不携带历史消息压缩机制根本不会被触发规则失效的风险自然很低。如果你的对话轮数很短还没有达到上下文窗口阈值压缩也不会成为主要威胁。但如果你的智能体要处理长会话、要维护多轮记忆、要执行具体操作比如导出文件、调用接口、操作数据库那么上下文压缩对安全规则的影响就必须进入设计考量。这类场景的共同点是安全规则不仅要被模型“理解”还要被系统长期“记住”而压缩恰恰会威胁这种长期记忆的完整性。我始终信奉一个判断上下文压缩不应该成为安全规则的摘要器。安全规则不是记忆它是系统运行前的约束。约束应该放在压缩工具够不到的地方而不是寄希望于它在被压缩后还能保持原样。对正在搭建智能体的团队来说现在最值得做的一件事就是把安全规则从对话历史和压缩范围里分离出来。压缩继续做规则留在外面。这不是什么高深技术而是一个非常朴素的工程分工问题。