面向智能体的 API 要把失败说清楚
作者结合小型 API 运行经验,说明模糊的500响应会诱发智能体持续重试,结构化错误码有助于调用方正确处理失败。文章还讨论超时重试下的写入去重,以及接口变更的弃用过渡。
AI 深度解读
给 Agent 用的 API,出错时返回什么,可能比文档写得多完整更影响调用结果。作者运行过文档转换、changelog 差异比较、webhook 接收等小型 API,反复遇到同一个问题:调用方会重试,却未必知道什么时候该停。
他的结论是:错误要能被程序识别,重复请求要能去重,接口变化要留迁移时间。这篇经验值得读,因为它把 Agent 接入的难点,从「怎样调用成功」推进到了「失败以后怎样恢复」。
错误响应要告诉 Agent 下一步怎么办
作者早期的转换接口遇到格式不合法的输入,直接返回通用的 500。调用方随后循环重试,直到预算耗尽。
问题出在错误表达上:输入有问题,原样再发多少次都解决不了;但一个笼统的 500,没有给调用方足够信息来区分「修改输入」和「稍后再试」。
作者后来改为返回结构化错误,包含机器可读的错误码,以及一句给人看的说明。他观察到,重试风暴随之消失。
错误响应应该帮助调用方决定下一步,而不只是宣布这次失败了。
不过,原文没有提供响应 JSON、错误码定义,也没说明调用方如何解析这些字段。因此可以借鉴这个方向,不能直接从文章里拿到一套完整协议。作者所说的「Agent 不读文档,只读错误响应」,也更适合理解为经验性强调,而不是所有 Agent 的固定行为。
超时后的重试,为什么需要去重
超时只能证明调用方没等到结果,不能证明服务端没执行。
作者观察到,Agent 会在超时后重新 POST。如果这是一个修改状态的接口,重复请求可能让同一个任务被处理 3 次。因此,他主张每个写入接口都应有去重方案。
这里涉及幂等性(idempotency):同一操作重复提交时,服务端应能识别它,避免重复产生业务效果。
原文没有交代去重标识怎么生成、记录保留多久,也没有讨论任务执行到一半时如何恢复。这些仍然需要接口提供方自己设计。只告诉调用方「可以重试」,没有对应的服务端保障,恢复过程就可能制造新的问题。
版本管理也是同一类可预测性问题。作者看到,调用方会固定能用的版本,并把分页结构、限流响应头写进工作流。接口里的小习惯,也会逐渐变成调用方的依赖。
所以,破坏性变更需要明确的旧版退役与迁移路径。不能因为新接口更合理,就假设已有 Agent 会自动适应。
我的判断
我认同作者把失败处理放到接口设计的前面。对程序员来说,错误分类、幂等和版本兼容都是熟悉的工程问题;Agent 的连续调用,让这些问题更容易表现为预算消耗或重复执行。
但这篇提供的是运行经验,没有对照实验,也没有请求量、错误率、成本变化或观察时长。结构化错误之后「重试风暴消失」,可以支持作者当时的改造有效,尚不足以证明任意 Agent 都能正确理解任意错误格式。
结构化错误也不能替代调用方的重试策略。接口需要表达失败原因,调用方仍需决定是否重试、何时停止。两边约定一致,恢复才可靠。
作者还通过 Moltbook API(https://www.moltbook.com/api/v1/feed)搭建自己的阅读循环,观察到 Agent 会不断重试、重排和重新格式化输入。这补充了他的使用体验,但原文没有展开实现,不能据此推导出该 API 的错误处理能力。
能拿来做什么
- 给 Agent 调用的 Node API 梳理错误响应,先区分输入不合法和临时失败,再提供稳定的机器错误码及一句说明。具体字段需要自行约定,原文没有现成格式。
- 检查创建任务等写入接口,在「服务端已执行、调用方却超时」的情况下再次提交,确认同一任务不会被重复处理。
- 修改分页结构或限流响应头之前,检查已有工作流的依赖,并为破坏性变更安排旧版退役与迁移路径。
- 调试日常 AI 编程里的 API 调用时,除了验证成功响应,也检查错误是否能让调用方修正输入或停止无效重试。