法律免责声明如何从答案泄露到工具调用参数中
你的法律顾问批准了一个单行的系统提示词指令:在每一个涉及受监管领域的回答中附加 “此信息不构成法律建议,不应以此为依据”。三周后,一个用户提交了一个 Bug,因为他们的日历事件描述字段以该行开头,随后是智能体本应放入会议邀请的合同摘要。智能体并没有发生故障。它完全按照系统提示词的要求执行了操作,结果发现这种行为涵盖了模型输出文本的每一个渠道——包括它调用的下一个工具的 JSON 参数。
该指令是一条内容格式规则,而模型也将其视为一条规则。它没有区分 “面向用户的回答” 和 “工具调用参数”,因为提示词中没有任何内容告诉它这些是不同的表面。免责声明最终出现在日历中、邮件草稿中,以及你的智能体代表用户发布的 Slack 消息中。这些中的每一个都是独立的下游系统,其作者根本不知道会有合规字符串被注入到结构化字段中,且每个系统的清理成本各不相同。
这就是本文要讨论的故障模式:安全样板内容因为定义它的提示词没有指明受众,而逃逸到了非预期的受众面前。团队提示的 是用户可见的行为,而模型执行的是内容形态规则。这种形态流向了提示词未提及的机器可读表面,其后果传播到了团队没有回滚权限的数据系统中。
提示词指令是对模型写入的每个渠道的行为约束
系统提示词不是配置。它们是模型在每次前向传递中读取的 Token,与对话历史和检索到的上下文共同调节下一个 Token 的概率分布。系统提示词中的行为约束会影响模型在该轮次中做出的每一个决定,以及该轮次产生的每一个工具调用。
当你写下 “在每一个涉及受监管内容的回答中附加此免责声明” 时,模型必须决定什么是回答,以及什么是涉及受监管内容。第一个决定就是出问题的地方。从模型的视角来看,工具调用参数是它为了完成用户请求而生成的字符串——而用户的请求涉及受监管内容。参数位于受监管上下文的下游。免责声明适用。
团队的心理模型是,“回答” 指的是 “渲染到用户屏幕上的自然语言消息”。模型的实际运行模型是,“回答” 指的是 “我这轮生成的任何文本”。这两个定义并不相同,而模型实际执行的是第二个。
这种模式也以更微妙的形式出现。一个 “保持简洁” 的指令可能会缩短工具调用的描述,从而丢失必要的实体。一个 “使用 Markdown 格式” 的指令可能会将反引号和星号注入到结构化字段中。一个 “使用用户偏好的语气说话” 的指令可能会使外发邮件的正文变得随意,即使该邮件是发给用户的外部交易对手的。这些情况的本质都是一样的:一个关于输出样式的提示侧规则被应用到了规则作者并未想到的输出渠道上。
审计成本是无限的,因为渠道是不可逆的
这个 Bug 的面向用户版本只是令人恼火。用户在他们的日历事件描述中看到了免责声明,报告了它,然后你的平台团队提交了一张工单。那是低成本的版本。
高成本的版本是:日历事件已经发送到了 CalDAV 服务器。Slack 消息已经发布到了公共频道。Jira 工单已经进入了集成团队的队列。邮件草稿在用户没看正文就点击发送时变成了已发送邮件。这些文本现在存在于你的团队并不拥有的系统中,存在于那些未选择接收你的合规样板内容的记录中,在某些情况下,还存在于被拉入下游流水线的记录中(例如喂给客户分析仓库的 Slack 频道,或者描述被索引用于机器学习训练的 Jira 项目)。
关于清理 “过去三周内创建的包含免责声明的日历事件” 的讨论,本质上是关于伸向成千上万用户的个人 Google 日历,去删除或编辑你的平台放在那里的数据。在没有每个用户明确重新授权的情况下,你没有权力这样做。从真实意义上讲,这个 Bug 是无法恢复的。这些样板内容现在已成为你用户日历的一部分,唯一的出路就是道歉并继续前进。
这就是工具参数泄露与普通的提示工程失误的区别所在。面向用户回答中格式错误的答案在下一轮会被覆盖 。而在触发了他人系统副作用的结构化字段内的文本,则是永久性的。
架构层面的错误:使用单一通道来控制多个通道的行为
当团队遇到这个 Bug 时,本能反应是优化提示词:告诉模型仅在“给用户的自然语言回答中附加免责声明,而不要出现在工具参数(tool arguments)中”。这种做法在测试的一周内有效。随后模型升级,消除歧义的短语效力减弱,免责声明在 2% 的流量中再次出现在工具参数里。你拥有一个随机性的护栏,却承担着确定性的义务。
真正的架构错误在更上游。团队使用了系统提示词(System Prompt)—— 一个影响模型生成的每一个 Token 的概率性通道 —— 来强制执行一个本应仅适用于单一表面的确定性需求。免责声明的正确归宿是运行在最终面向用户的字符串上的后处理层,而不是要求模型在它控制的每一个输出通道上都遵循的行为规则。
一旦你接受了“提示词是错误的控制表面”这一事实,修复方案自然浮现。免责声明变成了在模型完成回合后,由代码附加到用户可见响应对象上的字符串。系统提示词完全去掉了关于免责声明的指令。模型不再需要实时决定免责声明适用于哪些通道,因为这个决定是由编排层(orchestration layer)做出的,而编排层知道哪个输出才是面向用户的。
这种对比值得明确指出。提示词端的指令是“要求模型在每次说话时执行 X”。 而后处理指令是“用户看到的答案是 X 加上模型所说的话”。前者取决于模型的合规性、模型对“说话”的理解,以及这两者在升级过程中的稳定性。后者则取决于你响应处理程序中的单行代码。
弥合差距的模式
“工具参数中的免责声明”这个 Bug 是更广泛类别的显性版本。任何你作为内容形状规则放入系统提示词的东西,在某些流量占比中,都会逃逸到模型控制的每一个文本型输出通道中。以下模式基于这一前提进行设计,而不是要求模型去强制执行这种区分。
将固定话术(Boilerplate)移出提示词,进入渲染器。 如果一个字符串必须出现在每一个面向用户的响应中,请在将响应发送给用户的代码路径中附加它。模型不需要知道免责声明的存在。你的合规团队可以审计渲染器,并通过单一测试固定其行为。免责声明不可能泄露到工具参数中,因为模型从未写过它。
在调度前根据内容白名单验证工具调用参数。 即使清理了提示词,模型偶尔仍会在结构化字段中生成不该出现的文本 —— 例如提交消息中的许可协议前言,或外发聊天回复中“作为 AI 助手”的套话。一个在调度前运行的清理器,如果能从结构化参数中剥离已知的样板短语,就能弥合提示词清理所遗漏的差距。将这一层视为深度防御,而非主要控制手段。
在 Schema 层面分离用户可见和机器可读的输出。 许多工具调用栈返回一个混合了模型自然语言回复和工具调用的单一响应对象。将这些拆分为两个通道 —— assistant_message 和 tool_calls,并通过代码将免责声明附加到前者 —— 使得免责声明在结构上不可能流向后者。Pydantic 风格的输出 Schema 可以将这种分离编码为一种契约。
将工具参数审核视为护栏步骤,而非调试功能。 在工具触发前,如果有一个护栏能识别出结构化参数中预料之外的文本(任何符合免责声明模式的、任何长于配置阈值的、任何包含法律推诿辞令的内容),你就有机会在生产流量中捕捉到泄漏,而不必依赖用户报告。在每次工具调度中增加一次“LLM 作为裁判(LLM-as-judge)”的调用成本,很少会像团队预想的那样成为预算杀手;相比之下,一个将固定话术写入一万个日历项的 Bug 成本要高得多。
针对带有工具的流量测试提示词,而不仅仅是聊天流量。 免责声明指令在这样的评估(Eval)中本该失败:“给定一个工具调用回合,模型是否会将免责声明泄露到工具参数中?”大多数团队的提示词评估都是聊天评估 —— 单轮自然语言响应。如果你的产品表面包含工具调用,你的评估表面也必须包含工具调用。这个 Bug 在聊天评估层是隐形的,在工具评估层则是显而易见的。
架构层面的觉醒
系统提示词中的每一条指令,都是模型应用于它所控制的每一个输出通道的指令。模型天生不会区分“答案”和“动作”。两者都是它在同一次前向传播中、在同样的条件约束下生成的文本。在提示词中编写内容格式规则的团队,实际上编写了一条模型会应用在任何生成文本之处的规则,包括那些在现实世界中执行操作的工具参数。
这不只是一个需要打补丁的 Bug。它源于一个事实:对于受众仅为特定输出通道的规则,系统提示词是错误的层级。正确的层级是拥有该通道的代码。免责声明属于响应渲染器。语气规则属于用户消息格式化程序。“保持简洁”的规则不属于任何地方 —— 它是一个伪装成风格规则的内容形状规则,而且它一定会发生泄露。
你的团队想要的合规态势是:确保免责声明出现在每一个用户可见的响应中,并且在每一个机器可读的表面上都不可能出现。系统提示词无法给你这些。渲染器可以。
- https://witness.ai/blog/llm-system-prompt-leakage/
- https://cheatsheetseries.owasp.org/cheatsheets/LLM_Prompt_Injection_Prevention_Cheat_Sheet.html
- https://www.getmaxim.ai/articles/guardrails-in-agent-workflows-prompt-injection-defenses-tool-permissioning-and-safe-fallbacks/
- https://talhafakhar.medium.com/tool-calling-vs-function-calling-why-guardrails-and-observability-matter-more-than-your-prompts-806f8738212e
- https://www.wiz.io/academy/ai-security/llm-guardrails
- https://medium.com/data-science-collective/llms-should-reason-infrastructure-should-enforce-86493b936f84
- https://arxiv.org/html/2507.08030v1
- https://aisera.com/blog/agentic-ai-compliance/
- https://pydantic.dev/docs/ai/core-concepts/output/
- https://dev.to/thedailyagent/structured-outputs-vs-tool-calling-when-your-agent-actually-needs-which-kgk
