你整套技术栈里的每一个超时设置,都假设客户端最终会放弃:浏览器标签页会被关掉,CI 任务会撞上自己的墙钟上限,人会走开。你从负载均衡器、网关和 HTTP 库那里继承来的默认值,都是为一个耐心以秒计的调用方调好的。
Anthropic 称 Claude Opus 5.5 能持续执行任务 18 小时以上。
这并不是在说某一个超长的 HTTP 请求,而是在说连贯性:模型会跨越一个远长于你的 API 服务过的任何会话,去推进同一个目标。当这类会话指向你的接口时,它的寿命会超过你的访问令牌、你的幂等窗口、你的部署周期,以及你的大部分重试预算。而且与人不同,它不会意识到自己该停下来。
这是 API 设计问题,不是模型问题。下面是哪些地方会坏,以及该改什么。
AI Coding 交流群
如果你也在用 AI 写代码,或者正在研究 Cursor、Claude Code 这些工具,欢迎加入以下交流群。群里平时会聊一些 AI 编程的实际用法、开发工作流,还有各种新工具和新玩法。
Anthropic 实际公布了什么
新模型的厂商数字,这样我们讨论的是同一张表:
| 属性 | Claude Opus 5.5 |
|---|---|
| API 模型 id | claude-opus-5-5 |
| 输入 / 输出 | $4 / $20 每百万 token |
| 缓存输入读取 | $0.20 / 百万(缓存写入 $5) |
| 上下文窗口 | 1M |
| 最大输出 | 128k |
| 快速模式 | $8 / $40 每百万 |
| 运行成本对比 Opus 5 | 低 40% |
| 输出速度对比 Opus 5 | 快 30% |
| 持续在任务上的时长 | 18+ 小时 |
| 可用平台 | Claude Platform、AWS、GCP、Azure |
同一份公告里的基准测试成绩:Terminal-Bench 4.0 为 66.4%、OSWorld 2.0 为 81.8%、AutomationBench 为 40.0%、FrontierCode v1.1 为 54.4%、CursorBench 4.0 为 57.8%、Humanity’s Last Exam 带工具为 67.7%、Chartography 为 89.0%、GDPval-AA v2.1 达到 1846 Elo,以及成功的 boundary-circumvention 尝试减少 85%。
18-hour 这个数字才是落到你基础设施上的那一个。基准测试分数改变的是你选哪个模型,持续时长改变的是你的 API 必须扛住什么。
六个不再成立的假设
| 假设 | 过去为什么成立 | 一个 18-hour 的 agent 会把它变成什么样 |
|---|---|---|
| 一次调用会在一个超时内完成或失败 | 调用方是交互式的 | 任务时长超过你能安全设置的任何空闲超时 |
| 窗口很短,所以重试很便宜 | 重复请求相隔几秒到达 | 重复请求相隔数小时才到达,那时你的去重窗口早已关闭 |
| 开始时的凭据在结束时仍然有效 | 会话比 token TTL 短 | 一个任务里 token 会轮换两到三次 |
| 流就是一个连接 | 流的寿命就是一个响应 | 连接会断,而任务并没有结束 |
| 客户端记得自己在做什么 | 状态只存在于一个进程里 | agent 会压缩上下文、重启,然后需要你来提醒它 |
| 客户端能判断自己正在推进 | 有真人在盯着转圈动画 | 没有进度信息,agent 要么重头开始,要么永远等下去 |
每一条都有一个无聊、早已被吃透、而且通常被跳过的修法,因为过去没有东西逼着你做。现在有东西在逼了。
返回句柄,而不是返回干活的过程
价值最高的改动:任何可能超过几秒的操作,都立即返回一个 job 资源,而不是一直占着连接。
POST /v1/reports HTTP/1.1
Host: api.example.com
Idempotency-Key: 01J9Z4KCQ7M3XN2YB8V6H0
Content-Type: application/json
{"dataset": "orders_2026_q3", "format": "parquet"}
HTTP/1.1 202 Accepted
Location: /v1/jobs/job_01J9Z4KD
Retry-After: 5
Content-Type: application/json
{
"id": "job_01J9Z4KD",
"status": "queued",
"created_at": "2026-09-23T04:12:09Z",
"api_version": "2026-08-01"
}
然后让状态资源承载 agent 决定下一步所需的一切:
{
"id": "job_01J9Z4KD",
"status": "running",
"progress": { "completed": 41200, "total": 180000, "unit": "rows" },
"started_at": "2026-09-23T04:12:11Z",
"updated_at": "2026-09-23T05:47:02Z",
"expires_at": "2026-09-24T04:12:09Z",
"retry_after_seconds": 15,
"result_url": null,
"error": null
}
真正起作用的是四个字段。progress 带一个显式 unit,让模型可以推断等待是否理性,而不是靠已过时间猜。retry_after_seconds 把轮询节奏交给服务端控制,这在调用方毫无礼貌意识时很重要。expires_at 告诉 agent 这个句柄的有效期,好让它在失效前做检查点。api_version 把 job 钉在它创建时的那份契约上,这是挡在你 3pm 那次部署和一次黎明就开始的运行之间唯一的东西。
能提供 webhook 时,它是更好的完成信号;当 agent 没有可回调的地址时,轮询就是兜底方案。我们关于 长时 agent 调用中轮询与 webhook 取舍的实操文章讨论了这一权衡。在 18-hour 的时间尺度上变化的是:两者你都需要,因为一个在第三个小时投递的 webhook,送到的是一个此后已经压缩过上下文的 agent,接到的调用方已经不记得自己发过请求了。
让幂等性的寿命超过任务本身
大多数幂等实现把 key 只存一天甚至更短,这在过去一直够用。一个在长任务后段重试某次失败的 provisioning 调用的 agent,会落在原来的去重窗口之外,这时你的 API 就会欢快地干两遍活。
三个代价很小的改动:
- Publish the window. 在响应里返回过期时间,让调用方可以据此推理,而不是在文档里写一次然后指望它。
- Say when you replayed. 一个
Idempotency-Replayed: trueheader 能把无声的空操作 变成 agent 可以据以行动的信息。 - Reject mismatches loudly. 同一个 key、不同的 body,意味着调用方已经搞不清自己的状态。这时应该返回带原始请求指纹的
409,而不是继续返回过期结果。
HTTP/1.1 200 OK
Idempotency-Replayed: true
Idempotency-Expires: 2026-09-24T04:12:09Z
在操作确实危险的地方,优先使用 客户端提供的自然键,而不是不透明键。从业务事实推导出的 transfer_id 能挺过 agent 的记忆压缩,而它在十一个小时前生成的随机 UUID 做不到。我们关于 agent 幂等性的入门文章列出了各种失效模式。
假设凭据会在任务中途过期
一次 18-hour 运行会活过几乎所有的短期访问令牌。这是正确的安全姿态——但前提是你的 API 把这个区别做得足够清晰。
当 token 已过期时,返回 401 加一个 WWW-Authenticate: Bearer error="invalid_token" 质询;把 403 留给没有权限的主体。agent 对这两者的处理截然不同:一个意味着刷新后继续,另一个意味着停下并报告。把它们混成一种笼统的失败,就会得到一个花四小时重试某件它永远不会被允许去做的事情的 agent。
把 job 绑定到主体,而不是绑定到令牌实例。一个在某个令牌下启动、而该令牌此后已轮换的 job,必须仍然能被同一身份读取,否则每次凭据刷新都会让在途工作变成孤儿。
把流当作可续传的,而不是当作一个连接
长时间运行的流会断开。接受这一点,然后去设计重连,而不是设计连接。
对 server-sent events 来说,这意味着给每个事件一个单调递增的 id,在重连时尊重 Last-Event-ID 请求 header,并以一个短于你和客户端之间最紧的空闲超时的间隔发送 keepalive 注释。在你自己的文档里点出这些配置项的名字,因为读者得去改它们:AWS 负载均衡器上的 idle_timeout.timeout_seconds、nginx 里的 proxy_read_timeout、Cloud Run 服务上的 timeout。重点不是一个具体数值,而是这个数值确实存在、比任务时长短,并且从服务创建以来没人看过它一眼。我们的 SSE 流式传输指南讲了线格式;agent 特有的那部分是续传。
限流 header 也比平时更重要。RateLimit-Limit、RateLimit-Remaining 和 RateLimit-Reset 让模型能在一次长任务中自己调节节奏,而 Retry-After 出现在每一个 429 上则免去了猜测。给 agent 一个数字,它会尊重这个数字;什么都不给,它就会自己发明一套退避策略,而它的发明不会比你的更好。
成本那一侧是一个设计决策
再看一眼价格那一行。输入每百万 token $4,缓存读取 $0.20,在 agent 最常重发的部分上差了二十倍;而在 1M 上下文窗口下,绝对数字会迅速变大。缓存写入 $5 意味着第一遍比普通读取略贵,所以只有当前缀确实被复用时缓存才划算。放到十八个小时里,它是划算的。
这正是你的 API 形态变成别人账单上成本项的地方。如果你的 OpenAPI 规范、工具定义或错误目录位于 agent 上下文的开头,那么字节稳定性就是一项功能。确定性地序列化,保持 key 顺序稳定,给工具定义加版本而不是原地修改。对你的规范做一次纯外观上的重排序,就会让缓存前缀失效,并以完整的输入价格对整个前缀重新计费,而为它付钱的客户永远不会知道是你干的。
这个规模不是假设。OpenAI 披露过,其研究员的编码 agent 日均花费中位数超过 $600,第 90 百分位超过 $7,000。这就是没人做优化时持续 agent 工作的成本,也是两天内三次模型发布全都以单任务成本而不是每 token 成本打头的原因之一。缓存何时回本的算术在我们的 Opus 5.5 缓存成本拆解里。
在 agent 找到那条长路径之前先测它
这些都不是点一次发送、看一眼 200 就能验证的。故障都发生在第九个小时。
在 Apifox 里,把整个生命周期建模成一个测试场景,而不是单个请求:断言创建调用返回 202,其中带 Location 和一个 Retry-After;循环调用状态接口直到到达终态;并断言 progress.completed 从不倒退。最后那条断言抓到的真实 bug 比任何状态码检查都多,因为非单调的进度正是让 agent 决定重头再来的原因。
然后用 mock 服务端故意把它弄坏。提供一个连续二十次轮询都停在 running 然后失败的 job;提供一个 429 但不带 Retry-After,看你的客户端会怎么反应;在任务进行到一半时提供一个 401,确认在 job 在途时刷新路径确实能用。Apifox 的 SSE 测试能保持一个流式连接打开并对单个事件做断言,这是验证 Last-Event-ID 续传是否返回了正确游标、而不是从零重放的唯一实用办法。把这个场景接进 CI,这样将来某次超时改动会表现为一个失败的测试,而不是某个客户整夜运行的任务失败。Apifox 可以免费开始使用,而你构建一次的场景能覆盖你所有长时运行的接口。
简短清单
- 长时间操作返回带 job 句柄的
202,绝不占着连接 - 状态响应带上进度、单位、服务端选定的轮询间隔和过期时间
- job 钉住它创建时所用的 API 版本
- 幂等窗口被公开,重放有标记,key 复用而 body 改变时返回
409 - token 过期时的
401与权限被拒的403可以区分 - job 属于某个主体,而不是某个令牌实例
- 流携带事件 id、尊重
Last-Event-ID、并在路径上最短的空闲超时内发送 keepalive - 每个
429都带上Retry-After,限流 header 始终存在 - 规范和工具定义序列化后字节稳定,让客户端缓存保持热态
这些要求没有一项是 Opus 5.5 发明的。它只是拿掉了跳过它们的最后一个借口,因为那个过去会在发现裂缝之前就放弃的客户端,现在会径直穿过这些裂缝干上十八个小时。
开发必备:API 全流程管理神器 Apifox
介绍完上文的内容,我想额外介绍一个对开发者同样重要的效率工具 —— Apifox。作为一个集 API 文档、调试、设计、测试、Mock、自动化测试于一体的工具,Apifox 是目前提升研发效率的首选。
如果你正在开发项目,不妨试试其极其友好的界面设计,它完全兼容 Postman 和 Swagger 数据格式,导入数据非常方便,,即使是新手也能很快上手,点击这里即可注册使用。

值得一提的是,除了个人和常规团队使用,针对有高安全合规要求、或需要在内网环境协作的企业,Apifox 还提供了深度定制的私有化部署方案。
获取专属报价与部署方案
详细的私有化部署系统架构与安全白皮书
针对您公司规模的专属报价单
免费的 1v1 专属产品演示 (Demo) 机会