当数据库迁移悄然摧毁 AI Agent 的世界模型
你的团队在周二执行了一次常规数据库迁移——将 last_login_date 重命名为 last_activity_ts,并扩展其语义以包含 API 调用。没有服务中断。测试通过。仪表盘更新。但你的 AI Agent——那个回答客户关于用户活跃度问题的 Agent——开始悄悄给出错误答案。没有报错,没有告警,没有堆栈跟踪。它只是自信地基于一个已经不存在的世界进行推理。
这就是 AI 工程中几乎无人关注的 Schema 迁移问题。你的 Agent 从工具描述、few-shot 示例和检索上下文中构建了一个隐式的数据模型。当底层 Schema 发生变化时,这个模型就变成了谎言——而 Agent 没有任何机制来检测这种矛盾。
Schema 与 Prompt 之间的隐形契约
每个接触结构化数据的 AI Agent 都在一个隐式契约下运行。工具定义说"这个数据库有一个名为 last_login_date 的 DATE 类型列"。Few-shot 示例演示了对该列的查询。系统提示可能在解释 Agent 能力时引用了它。
这个契约从未被记录、从未被版本控制、从未被测试。它散落在 prompt 模板、示例库、检索索引和工具 schema 中。当 DBA 重命名一个列或工程师添加一个枚举值时,他们会更新迁移文件、ORM 模型和应用代码。但他们不会更新 Agent 的 prompt。他们甚至不知道 Agent 的 prompt 存在。
结果是一类特别隐蔽的故障。传统的 Schema 变更会产生明确的错误——对重命名列的 SELECT 会抛出 undefined column 异常。但 AI Agent 并不总是大声失败。一个 text-to-SQL Agent 可能生成引用旧列名的查询,得到错误后"贴心地"重新构造一个查询,指向另一个恰好存在的列。Agent 返回一个看似合理的答案。它是错的,但没人知道。
为什么标准监控会遗漏这些问题
传统的可观测性能捕获简单的情况。如果一个列被完全删除而 Agent 试图引用它,你会在日志中看到 SQL 错误。但大多数 Schema 变更更加微妙:
- 重命名:
user_status变成了account_state。Agent 的 few-shot 示例仍然引用user_status。如果 Agent 足够智能,能在运行时检查 Schema,它可能会恢复。如果它基于缓存的上下文或静态示例工作,它会生成错误的查询或臆想一个映射。 - 语义漂移:一个列保持相同的名称但含义改变了。
transaction_amount以前是以分为单位,现在是以元为单位。Agent 对阈值和比较的推理偏差了 100 倍,但每个查询在语法上都是有效的。 - 枚举扩展:一个
status字段增加了一个新值pending_review。Agent 的决策逻辑基于只有三个状态值的示例训练,没有考虑第四个。它可能悄悄地将pending_review归类为pending,或者完全忽略这些行。 - 类型变更:
INTEGER变成BIGINT,或者VARCHAR(50)变成TEXT。通常无害,但如果 Agent 已经内化了类型约束(来自 Schema 描述或示例),它可能会应用现在已经不正确的验证逻辑。
这些都不会触发你设置的告警。错误率保持平稳。延迟看起来正常。唯一的信号在 Agent 输出的质量中——这需要大多数团队尚未构建的评估基础设施。
多 Agent 系统中的级联问题
当多个 Agent 共享数据时,Schema-Prompt 耦合问题会急剧恶化。考虑这样一个流水线:Agent A 查询数据库,Agent B 总结结果,Agent C 做出推荐。如果 Agent A 误解了一个重命名的列,它会将看似合理但不正确的数据传递给 Agent B,Agent B 自信地总结了错误的信息,Agent C 据此做出推荐。
Forrester 在 2025 年将这种级联称为"上下文漂移",称其为 AI 加速开发的隐形杀手。链中的每个 Agent 都在不质疑上游上下文的情况下处理收到的输入。错误不是在量级上放大——而是在置信度上放大。当人类看到最终输出时,它看 起来很权威。毕竟,三个 Agent 都同意了这个结果。
这与传统系统中 Schema 变更的传播方式根本不同。在微服务架构中,破坏性的 Schema 变更会在服务边界产生编译错误或运行时异常。错误在引入点被捕获。在 Agent 流水线中,"错误"是一个微妙的语义不匹配,它通过每个边界而不被检测到。
Agent-Schema 边界的契约测试
修复方案借鉴了 API 工程中的一个旧思路:契约测试。正如消费者驱动的契约测试验证 API 提供者仍然满足其消费者的期望一样,Schema-Prompt 契约测试验证数据库 Schema 仍然满足 Agent 的假设。
以下是实践中的做法:
1. 提取 Agent 的 Schema 假设。 解析你的 prompt 模板、few-shot 示例和工具定义,构建一个 Agent 依赖的每个列名、类型、枚举值和语义约束的清单。这就是 Agent 的"契约"——它假设为真的世界模型。
- https://atlan.com/know/context-drift-detection/
- https://dev.to/kuldeep_paul/managing-ai-agent-drift-over-time-a-practical-framework-for-reliability-evals-and-observability-1fk8
- https://medium.com/google-cloud/the-six-failures-of-text-to-sql-and-how-to-fix-them-with-agents-ef5fd2b74b68
- https://pub.towardsai.net/architecting-state-of-the-art-text-to-sql-agents-for-enterprise-complexity-629c5c5197b8
- https://www.getmaxim.ai/articles/a-comprehensive-guide-to-preventing-ai-agent-drift-over-time/
- https://byaiteam.com/blog/2025/12/30/llm-model-drift-detect-prevent-and-mitigate-failures/
