你完美地执行了弃用指南。提前六个月发布公告邮件。包含四种语言代码示例的迁移指南。在每个 v1 响应中添加了 Sunset 响应头。开发者仪表板上的横幅。两封提醒邮件。然后你关闭了 v1 —— 但结果并非指南所承诺的安静切换,你的错误率直线飙升并维持在高位。流量没有迁移。它只是不断涌入、失败并重试,且容量比以前更高,因为每一次失败都触发了另一次尝试。
指南之所以失败,并不是因为你执行得不好。它的失败是因为它假设另一端是一个人类 —— 一个会阅读邮件、浏览变更日志并在截止日期前提交 Jira 任务进行迁移的人。你很大一部分流量背后已经没有这样的人了。它来自智能体 (Agent),它们对你 API 的认知被冻结在系统提示词、工具 schema 以及散布在成千上万个你看不见也永远无法触达的代码库中的模型训练数据里。你的停用通知是写给读者看的。而你的最大客户端是一个 Prompt。
弃用指南假设有人在听
标准 API 生命周期的每一步都依赖于在正确时刻出现的人眼。如果有人阅读收件箱,弃用邮件就起作用。如果开发者打开迁移指南,它就起作用。如果有人登录仪表板,横幅就起作用。甚至 Sunset 响应头 —— 工具箱中最具机器可读性的工具 —— 之所以奏效,也主要是因为监控库将其暴露给人类,然后由人类安排迁移。
这个假设已经悄然失效。到 2026 年中,Web 上的自动化请求首次超过了人类流量 —— Cloudflare 的雷达数据显示机器人流量占 HTML 流量的 57% 以上 —— 而智能体部分是增长最快的部分,仅在 2025 年,AI 智能体流量就增长了几千个百分点。API 本身就已经占据了 Web 流量的大部分;现在,这些 API 调用中越来越多的一部分不再是由开发者根据你当前的文档编写的代码组成的,而是由模型在推理时决定你的 API 可能长什么样。
这种区别比原始流量更重要。手写的 SDK 集成虽然陈旧但清晰:在某人编写它时它是正确的,并且有一个代码库可以让开发者去更新。而智能体的集成在三层维度上同时过时,且其中两层根本没有代码库。
智能体对你 API 的认知究竟存在于何处
当智能体调用你的 API 时,它对你端点的认知来自于三种来源的混合,且每种来源的衰减周期都不同:
模型训练数据。 模型在训练时记住了存在于博客文章、Stack Overflow 答案和开源代码中的 API —— 这个快照在模型进入广泛生产使用时通常已经过时一年或更久。更糟糕的是,训练数据是权重偏向热度的:如果旧端点出现在一万个代码库中,而新端点只出现在两百个中,模型会自信地输出旧的那个。这与模型倾向于使用已弃用库的机制相同 —— 已弃用的模式在权重中具有更大的引力。
系统提示词和工具 schema。 某人在某处将你的端点文档粘贴到了系统提示词中,或者编写了一个封装你 API 的 MCP 工具定义。这些文本现在存在于他们的代码库、智能体平台或向量数据库中。它永远不会收到你的弃用邮件。只有当它坏到一定程度以至于需要人类介入调查时,它才会更新 —— 而这恰恰是弃用流程本该防止的故障模式。
检索库中缓存的文档。 那些确实将智能体建立在你文档基础上的团队,通常是通过爬虫构建的 RAG 索引来实现的。如果爬虫频率是每季度一次,你六个月的弃用窗口期仅相当于两次索引刷新 —— 前提是流水线仍在运行且有人重新嵌入了更改后的页面。
注意这三点中缺少了什么:你的变更日志。一份从未进入上下文窗口的弃用通知等同于不存在。模型不知道它没有检索到的信息,而所有的标准弃用渠道 —— 邮件、博客文章、仪表板 —— 都不会向任何地方的上下文窗口提供输入。
关闭 v1 不会引发迁移 —— 它会引发重试风暴
这是打破旧思维模式的行为差异。当手写代码集成命中一个已失效的端点时,它会抛出异常,触发报警,然后由人类修复。失败是响亮的、归因明确的且终结性的。当智能体命中一个已失效的端点时,它会做智能体天生擅长的事:应对。
它会重试。它会重新组织请求。它会幻觉出一个看起来合理的备用端点并尝试。它可能会认为错误是暂时的并退避,然后再次尝试原始请求。将这种循环放大到每一个持有你 API 过时认知的智能体实例上,关闭 v1 并不会减少 v1 流量 —— 而是放大了它,将每一次本该发生的请求转化成一连串的失败、格式错误的猜测和重试。你的基础设施为这场风暴买单,智能体的运营商为浪费的 token 买单,而最终用户得到的是一个被静默降级的结果,且没有人会将其记录为“供应商弃用了 API”。
MCP 生态系统已经给这种故障模式起了一个名字:静默损坏 (silent breakage)。重命名的参数或删除的工具不会像损坏的 SDK 构建那样产生清晰的验证错误 —— 它会产生一个误解指令并以错误方式绕过问题的智能体,且没有人会注意到。协议本身的版本控制很清晰,但单个工具仍然没有标准化的版本控制层,因此 schema 漂移会演变成行为漂移,而不是构建失败。开放 Web 上的弃用在更大规模上也面临同样的问题:消费者不会崩溃,它会虚构 (confabulates)。
你的错误响应是唯一会被阅读的迁移指南 如果弃用通知必须进入上下文窗口(context window)才有意义,请自问你的 API 在何处能确保触达到智能体(agent)的上下文。不是你的文档网站,也不是你的变更日志(changelog)。只有一个地方:失败请求的响应体。智能体会阅读错误——这往往是它们唯一能看到的关于你的文档。
这使得错误设计成为了你主要的弃用沟通渠道,而且标准比仅仅返回一个状态码要高得多:
让错误信息承载迁移逻辑。 一个带有 "error": "endpoint deprecated" 的 410 Gone 响应对智能体毫无教益。一个结构化的错误信息,如果能指明替代端点,展示旧字段到新字段的映射,并包含一个有效的示例请求,就能为能力强大的模型提供在对话中进行自我迁移所需的一切。实际上,你是在编写一段提示词(prompt)——所以要像写提示词那样去写它:明确、完整且自成一体。
在弃用窗口期内发出机器可读的标头(headers)。 RFC 9745 的 Deprecation 标头信号表示资源已经或即将弃用;RFC 8594 的 Sunset 标头说明它何时停止响应;而 Link 关系可以指向迁移文档。如今几乎没有客户端中间件会将这些信息呈现给模型——但这正是需要在响应体中放入相同信息的理由,而不是省略标头的理由。智能体框架修复其中间件的速度,比全世界系统提示词被重写的速度要快。
在截止日期之前返回信号,而不仅仅是之后。 仅通过最终的 410 错误才了解到弃用的智能体是在故障发生时才学习。在窗口期内,成功的 v1 响应应携带智能体可以处理的弃用通知——即负载(payload)中的警告字段,智能体可能会将其引用到自己的日志中,这也是操作人员最终发现问题的方式。
一个令人不安的推论:在日落日期之后,你不能直接消失。一个返回连接重置(connection reset)的死路由无法教给智能体任何东西,反而会助长重试风暴(retry storm)。一个返回精确、具指导意义错误的墓碑路由(tombstone route)维护成本很低,却能将失败转化为迁移——一次一个上下文窗口地完成。
将旧路由作为适配器保留,并针对两类受众进行版本管理 更深层的适应是承认,对于智能体消费者来说,成本最低的弃用就是你从未执行过的弃用。Stripe 在智能体让这件事变得紧迫的几年前就展示了这种架构:将每个消费者固定(pin)在他们首次集成的 API 版本上,核心逻辑仅保留在最新版本,并维护一个兼容层,将现代响应向后转换为每个固定版本消费者预期的形式。内部工程师从不接触版本条件判断;旧版本的成本只是一个转换函数,而不是业务逻辑的分支(fork)。
这种模式最初是为那些不想迁移的人类开发者设计的。它恰好是拥有“冻结记忆”的客户端群体所需要的。一个接受 v1 请求并将其转换为 v3 语义的适配器,可以服务于每一个过时的系统提示词,以及每一个记住了你 2024 年文档的模型——无限期地,且成本仅仅是一些映射代码。与另一种选择(成为一个智能体总是在其上失败的 API)相比,维护负担微乎其微。
将智能体视为一个独立的消费者群体,还会引出另外两个提供商端的举措:
检测智能体流量并细分你的生命周期指标。 User-agent 字符串、鉴权令牌来源以及请求形状启发式方法,可以很好地将智能体调用与人类编写的集成区分开,从而回答那个现在应该决定每次弃用的问题:剩余的 v1 流量中,有多少实际上能接收到迁移通知?属于人类的部分可以通过电子邮件通知。属于智能体的部分只能通过适配器和错误设计来迁移。
将你的工具模式(tool schemas)与人类文档分开进行版本管理。 如果你发布了一个用于智能体消费的 MCP 服务器或 OpenAPI 规范,该工件就是与缓存它的消费者之间的接口契约,它需要有自己的兼容性准则:仅允许增量更改,不重命名,不缩小类型范围,不改变参数含义。即使是重新措辞的工具描述也可能改变智能体的行为,因此请将描述文本视为契约的一部分,并在发布更改前评估关键路径。你的人类文档可以自由重写;而你的模式则以一种文字描述从未有过的方式承载着负荷。
生命周期长度刚刚成为了核心竞争力 二十年来,API 提供商将向后兼容视为成本中心,将弃用速度视为工程卫生。智能体逆转了这一经济逻辑。当决定调用哪个 API 的消费者是一个从其记忆和上下文中进行选择的模型时,那个仍然按照模型记忆中的方式工作的 API 就会赢得调用。那些 2024 年的端点仍能正确响应的提供商默认捕获了智能体流量;而那些自那时起发布了三个破坏性版本的提供商,在模型看来,就是一个会随机失败的 API。
这使得兼容性寿命成为了值得宣传的亮点,而不是需要道歉的缺点——这便是智能体网络时代的“永不破坏用户空间(never break userspace)”。它会像正常运行时间 SLA 那样出现在供应商评估中:你让版本存活多久,你的错误是否携带迁移指令,你的工具模式是否仅限增量更新。构建智能体的团队应该已经开始为此给供应商打分了,因为供应商发布的每一次破坏性变更都会变成某人智能体循环中的一次调试任务。
给提供商的实际总结:假设变更日志无法传达到任何人手中。将固定版本和保留适配器作为默认选项,而不是例外。让每一个错误响应都成为一个自成一体的迁移提示词,无论如何都要发出 Deprecation 和 Sunset 标头,并且永远不要让退役的路由完全消失。在任何日落之前,衡量剩余流量中有多少是与人类关联的——因为不属于人类的那部分流量不会按你的计划进行迁移。它会在其上下文窗口告知时才迁移,而你对该窗口的控制渠道只有一个:你发回的字节。
会员专享
余下内容仅对会员开放。 会员可读完整内容 —— 每一个公开发布的观点背后,那些框架、决策与推理的全貌。
— 完整文章,包含未公开存档的部分 — 可落地的工作框架,附带权衡与决策依据 — 新文章抢先看,先于公开发布 登录以继续阅读→ 随时取消 · 一次订阅,畅读全部