LLM request timed out 这个报错,接第三方 API 的朋友应该不陌生。OpenClaw 本身是个开源智能体框架,跑起来很轻,但一旦把模型源切到第三方兼容接口,超时就像定时炸弹一样时不时爆一下。这篇文章把我自己调通的全过程写出来,包括怎么定位、怎么调参数、怎么防复发,给同样在坑里的朋友一个完整参考。
先说结论:这个报错绝大多数时候不是 OpenClaw 坏了,而是整个请求链路里某个环节的响应速度超过了客户端等待上限。你可以把它理解成点外卖,你下单之后商家迟迟不接单,或者骑手迟迟不取货,平台等得不耐烦了就告诉你“超时”。但具体是商家漏单、骑手堵车、还是平台自己网络不好,得一层层看。下面我就按排查顺序,把每个环节拆开讲。
1. 先说清楚:这个超时到底卡在哪一环
想解决问题,第一步不是改配置,而是搞清楚 OpenClaw 从发起一次 LLM 请求到拿到结果,中间到底经过哪些环节。很多人上来就调超时时间,结果调了还是超时,就是因为没定位准卡点。
1.1 OpenClaw 调用第三方 API 的完整链路
OpenClaw 作为一个开源智能体运行时,核心工作是把用户的指令转换成对大模型 API 的调用。当模型源指向第三方兼容接口时,一次请求大致经过以下几个环节:
- OpenClaw 内部配置解析与模型客户端初始化
- 模型 SDK 组装 HTTP 请求,包括 headers、body、认证信息
- 建立 TCP 连接,完成 TLS 握手
- 发送请求体,等待第三方 API 网关响应
- 第三方 API 网关转发请求到上游模型推理服务
- 上游模型完成推理,把结果逐段或一次性返回
- OpenClaw 收到响应,解析并交给上层逻辑
这里的任何一个环节拖延,都可能表现为 LLM request timed out。我见过最离谱的情况是上游模型服务要排队,第三方网关没设置合理的排队上限,结果请求挂在网关内部十几秒才返回错误,OpenClaw 这边早就超时放弃了。
从超时类型上分,客户端通常要区分两个阶段:连接超时和读取超时。连接超时指的是 TCP 建连和 TLS 握手阶段,如果第三方服务 IP 不通、端口被墙、TLS 握手慢,这一阶段就会触发。读取超时则是指请求已经发出去,但迟迟等不到响应数据,常见于上游模型推理慢、网关排队、或者返回的数据量过大。
用生活化类比就是:连接超时是“你拨电话对方一直不接”,读取超时是“电话接通了但对方半天不说话”。两种超时的排查方向完全不同,前者偏向网络层面,后者偏向服务处理能力。
1.2 超时出现的三类典型场景
我实际接触过的案例里,出现超时的场景基本可以归成三类,你先对号入座,能省掉大量无用排查:
第一类是 OpenClaw 直连第三方聚合接口。这是最普遍的场景,用户配置了某个第三方兼容服务作为模型源,日常对话偶尔正常,但请求一长或者并发一高就超时。这种问题多半出在第三方网关的稳定性或者配的模型名称对应的上游服务负载过高。
第二类是第三方系统通过 API 调用 OpenClaw,OpenClaw 内部再去请求 LLM。这种情况下,外部调用方可能设置了自己的超时阈值,比如 30 秒,而 OpenClaw 内部请求 LLM 就要花 40 秒,外部系统先炸了。表面看是 OpenClaw 的问题,实际上是整体调用链路的超时阈值没有对齐。
第三类是批处理或者自动化任务场景。OpenClaw 在无人值守状态下跑批量任务,多个请求几乎同时发出,第三方网关的限流策略触发了排队,部分请求等待时间超过阈值。这种往往是间歇性的,问题复现全靠运气,排查难度最大。
区分这三类场景的意义在于:第一类重点调 OpenClaw 到第三方之间的参数,第二类要协调第三方系统那边的超时配置,第三类要处理并发和限流。后面讲的排查步骤,我会反复提到这个区分。
2. 动手排查:三步定位超时的真正原因
定位问题讲究先易后难。我习惯的顺序是:先查配置,再做网络基准测试,最后看日志。这三步走完,90% 的超时问题都能锁到具体环节。
2.1 先从最容易混淆的配置开始检查
很多超时其实是配置错误导致的连锁反应。比如 Base URL 填错了,请求打到了不存在的路径上,第三方网关可能返回一个 404,但 SDK 却在那里反复重试,最终表现为超时。再比如模型名称填了一个第三方平台没有接入的模型,网关内部查询模型路由表超时,也会直接拖垮响应。
我整理了几个高频配置错误,你在排查时先对着过一遍:
| 配置项 | 典型错误 | 后果 |
|---|---|---|
| Base URL | 末尾多了/v1后又拼接了/v1 | 请求路径 404,反复重试直至超时 |
| API Key | 复制时带了空格或换行 | 认证失败,某些网关延迟返回 401 |
| 模型名称 | 大小写不对或版本号不匹配 | 网关内部路由查询超时 |
| 超时参数 | 设了 10 秒但接口 P95 就要 15 秒 | 正常请求也频繁超时 |
| Stream 参数 | 请求未开启流式但期待快速首包 | 等待完整响应时间过长 |
这里要注意一个细节:OpenClaw 的配置通常是 YAML 文件配合环境变量一起生效。如果你同时设置了环境变量和配置文件里的字段,环境变量优先级更高。我遇到过一位开发者,配置文件里超时设置得很合理,但环境变量里残留了一个旧的超时值,导致每次请求都在同一时间点被掐断。排查时要把两处都看一遍,别只盯着配置文件。
2.2 用 curl 直连第三方 API 做基准测试
配置确认无误后,下一步是把 OpenClaw 隔离掉,直接用 curl 请求第三方 API,看它的真实响应能力。这一步能快速判断问题到底在 OpenClaw 侧还是第三方服务侧。
我常用的命令是这样的:
curl -v -X POST "https://your-api-gateway.example.com/v1/chat/completions" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer sk-xxx" \ -d '{ "model": "your-model-name", "messages": [{"role": "user", "content": "ping"}], "max_tokens": 16, "stream": false }' \ -w "\n时间分解:\n" -w "DNS解析: %{time_namelookup}s\n" -w "TCP连接: %{time_connect}s\n" -w "TLS握手: %{time_appconnect}s\n" -w "首字节: %{time_starttransfer}s\n" -w "总耗时: %{time_total}s\n"关键要看三组数据:TCP 连接时间、首字节时间(TTFB)、总耗时。如果 TCP 连接时间本身就超过 1 秒,说明网络链路有问题;如果 TCP 很快但 TTFB 很长,说明第三方网关或上游模型推理慢;如果总耗时比 TTFB 长很多,说明响应体下载慢,可能是返回内容太多或者网络带宽受限。
光测一次不够。第三方 API 的响应时间是有波动的,我建议至少测 10 到 20 次,记录每次的耗时分布,重点观察两个指标:平均耗时和 P95 耗时。P95 的意思是最慢的 5% 请求的耗时临界值,如果 P95 是 20 秒,那你的超时时间至少要设到 25 秒以上,否则 20 个请求里就有一个会挂。
2.3 看 OpenClaw 日志里的关键时间戳
curl 测试能确认第三方服务的基准能力,但没法看到 OpenClaw 内部的调度逻辑。这个时候日志就是你最好的朋友。
先把 OpenClaw 的日志级别调到 debug 或者 trace。不同版本的 OpenClaw 日志配置方式略有差异,但一般都在配置文件里有个 log_level 字段。调完之后,发起一次会超时的请求,然后重点看日志里的几个时间点:
- 请求发起时间:OpenClaw 开始组装请求的时刻
- HTTP 调用开始时间:SDK 真正发出请求的时刻
- 第三方响应时间:第一批响应数据到达的时刻
- OpenClaw 抛错时间:LLM request timed out 出现的时刻
用这四个时间点做减法,就能算出各阶段的耗时。如果从请求发起到 HTTP 调用开始就隔了好几秒,说明问题出在 OpenClaw 内部,可能是前置处理逻辑、插件机制或者上下文压缩占用了太多时间。如果 HTTP 调用开始到抛错之间正好等于你配置的超时时间,那说明是第三方响应太慢,OpenClaw 等不起。
还有一种容易被忽略的情况:系统时间不同步。如果 OpenClaw 所在机器的时间和第三方网关的时间偏差过大,某些基于时间戳校验的 API 可能直接拒绝请求,而表现就是请求被挂起直到超时。排查时顺手执行一下时间同步命令,成本很低但收益明显。
3. 核心解决手段:参数调整与重试机制
定位到问题之后,接下来就是动手改参数了。这一部分我重点讲两个东西:超时时间怎么调才科学,以及重试机制怎么设计才不容易把问题放大。
3.1 超时参数怎么调才不算乱调
大多数 OpenClaw 部署在调用第三方 API 时,超时配置会涉及两个字段:连接超时和读取超时。连接超时对应的是建连阶段,读取超时对应的是发出请求后等待响应的阶段。
连接超时不建议设得太大,5 到 10 秒足够。因为正常网络环境下,TCP 建连加 TLS 握手通常在 1 到 2 秒内完成,超过 10 秒还连不上,说明网络链路大概率有问题,继续等没有意义。
读取超时则要看基准测试的结果。我的经验公式是:读取超时 = P95 响应耗时 × 1.5,再往上取整到 10 的倍数。比如 curl 测试显示 P95 是 18 秒,那读取超时就设为 30 秒;如果 P95 是 7 秒,就设为 15 秒。这个系数的意义在于给波动留出缓冲,又不至于让单次请求占住线程太久。
这里要特别提醒:超时时间不是越长越好。很多人的第一个反应是把超时调到 300 秒,觉得这样总不会超了。但超时时间过长会带来两个新问题:一是 OpenClaw 内部线程被长时间占住,并发能力下降;二是第三方接口如果真的挂了,你要等满 5 分钟才能感知到,严重拖慢故障恢复速度。合理的做法是留足缓冲但不放纵。
在 OpenClaw 的配置里,常见的写法是:
model: provider: openai_compatible model_name: your-model-name api_base: https://your-api-gateway.example.com/v1 api_key: ${OPENCLAW_API_KEY} timeout: connect: 10s read: 30s如果你的 OpenClaw 版本采用的是环境变量方式,那就是类似OPENCLAW_TIMEOUT_CONNECT=10和OPENCLAW_TIMEOUT_READ=30这种命名。具体字段名以你实际使用的版本文档为准,但思路是一样的:连接超时管建连,读取超时管响应等待。
3.2 流式响应是解决首包超时的关键
很多第三方 API 默认非流式返回,也就是说要等完整响应生成完才一次性返回。对于长文本场景,整个生成过程可能要几十秒甚至几分钟,客户端只能干等着,超时几乎无法避免。
流式响应(Streaming)能从根本上改变这个局面。开启流式后,第三方 API 每生成一段 token 就立刻推送出来,客户端第一时间就能收到数据,不需要等完整响应。对 OpenClaw 来说,收到第一批数据就代表请求活着,读取超时也就不会那么容易被触发。
流式响应的原理是 SSE,也就是服务端推送事件。HTTP 连接会保持打开,服务端不断往同一个连接里写数据块,每个数据块以data: {"choices": [...]}的形式出现。OpenClaw 收到后逐渐拼装出完整回复。
但开了流式不等于万事大吉。这里有一个坑:流式模式下,服务端生成 token 的速度可能很不均匀,有时候两批 token 之间的间隔会超过你设置的读超时。比如你设了 30 秒读超时,但模型思考了 40 秒才输出第一个 token,照样超时。所以流式模式下读取超时应该以“相邻数据块之间的最大间隔”为基准来设置,而不是以完整响应的总耗时。
如果你发现第三方 API 的流式输出经常出现长间隔,可以考虑在 OpenClaw 侧开启“流式超时保护”机制。有些版本支持配置空闲超时(idle timeout),专门控制相邻数据块的最大间隔,这个值可以比整体读取超时小很多,比如 15 秒。
3.3 重试与退避策略的合理设计
超时之后再重试是很多人下意识的做法,但盲目重试会让情况更糟。如果第三方服务已经过载,你的重试请求等于又在排队末尾追加任务,可能越试越慢,最终把 OpenClaw 的请求队列全部堵死。
正确的重试策略要看错误类型。HTTP 状态码 429 表示限流,503 表示服务不可用,超时类错误通常对应网关响应超时或连接被断开。这些属于可重试的错误。而 400、401、403 这类错误代表请求本身有问题,重试 100 次也是同样的结果,不要重试。
重试间隔要用指数退避加抖动。指数退避的意思是每次重试的等待时间按指数增长,比如第一次等 1 秒、第二次等 2 秒、第三次等 4 秒、第四次等 8 秒。抖动是在这个基础上加一个随机偏移,避免多个客户端同时重试形成惊群效应。公式可以写成:
import random def backoff_delay(attempt: int, base: float = 1.0, cap: float = 30.0) -> float: delay = min(cap, base * (2 ** attempt)) jitter = random.uniform(0, delay * 0.3) return delay + jitter在 OpenClaw 中,如果要实现重试,优先看框架本身有没有内置的重试配置。有些第三方 SDK 自带自动重试,但默认重试次数可能过多或过少。我建议把重试次数控制在 2 到 3 次,超过这个数字之后再重试的成功率很低,反而白白消耗资源。
另一个值得注意的点:重试时要不要重新构造请求体?对于 LLM 调用,如果上下文里带有时间戳或者随机采样参数,重新构造请求可能导致生成结果不一致。OpenClaw 内部一般会保存原始请求的不可变快照,重试时直接复用,这个设计是合理的,不需要你自己处理。
4. 针对第三方 API 的专项优化
前面讲的都是 OpenClaw 侧的参数调整。但第三方 API 本身的不稳定性才是超时的根本来源,这一节专门讲怎么应对第三方服务的各种异常表现。
4.1 第三方 API 网关响应的不稳定因素
第三方兼容接口本质上是一个或多或少的聚合网关,它自身的稳定性取决于上游模型服务的负载、网关的队列设计、以及限流策略。我实测过一家聚合服务的耗时数据:同样一个请求,凌晨 2 点的 P95 是 6 秒,下午 3 点的 P95 直接飙到 25 秒。这说明单纯调大超时并不能根治问题,高峰期还是会触发超时。
网关的不稳定主要来自几个方面:上游模型推理服务的排队时间、网关自身的 CPU 和内存瓶颈、限流策略触发的排队等待、以及跨地域网络链路的抖动。你可以通过长期监控来掌握它的规律,比如每天固定时间跑一次 curl 基准测试,积累一周数据,基本就能看出高峰期分布。
如果第三方网关的 P95 和 P99 差距特别大,说明它的服务质量很不稳定。这种情况下我会考虑两个方向:一是寻找备用的第三方服务,二是降低对它的依赖,比如把一些固定模式的请求改成本地规则处理。
4.2 请求体瘦身与上下文管理
请求体大小是影响超时的一个隐蔽因素。LLM 请求的耗时和总 token 数呈正相关,上下文越长,模型处理的时间越长,第三方网关转发的数据量也越大。如果你发给第三方 API 的请求动辄几万 token,超时几乎是必然的。
我处理过一个案例:某开发者给 OpenClaw 配置了很长的 system prompt,又开了长期记忆功能,每次请求都把历史消息完整带上,token 数经常到两万以上。第三方 API 处理这样的请求需要将近 30 秒,远超默认超时时间。
解决方案是上下文瘦身。OpenClaw 通常支持上下文压缩机制,把历史消息做摘要,只保留最近几轮完整消息,再往前的用摘要代替。你也可以手动调小单次请求携带的最大 token 数,或者对 system prompt 做精简。瘦身之后,请求耗时能下降 50% 以上。
另外一个参数是max_tokens,它决定了模型最多生成多少 token。如果这个值设得很大,模型生成时间就长。在需要快速响应的场景下,适当限制输出长度能显著降低总耗时。比如客服机器人,回复一般不会超过 200 字,max_tokens设 300 就够,没必要给 2000。
4.3 多路回退与本地兜底方案
单点依赖第三方 API 永远是风险最大的方案,因为它一挂,你的整个 OpenClaw 服务都跟着挂。我的建议是至少配置两个可用的模型来源,做好故障切换。
OpenClaw 支持配置多个 provider,某些版本还支持自动故障切换。配置思路是:主 provider 指向稳定的第三方服务,备用 provider 可以指向另一家服务或者本地部署的模型。当主 provider 连续超时达到阈值时,自动把请求切换到备用 provider。这样即便第三方 API 高峰期不稳定,你的服务也能兜底。
还有一种更轻量的兜底方案,适用于一些固定场景的问答。比如你跑的是智能客服,常见问题的高频回复完全可以做成模板或者本地规则。OpenClaw 收到请求后先走本地匹配,匹配不到再走 LLM。这虽然不是 AI 优先的做法,但能大幅降低对第三方 API 的依赖,减少被超时影响的概率。
5. 实操记录:一次完整的排障过程
理论讲再多也不如一次实操来得直观。这个案例是我帮一位开发者处理的,症状就是间歇性 LLM request timed out,非常典型。
5.1 问题复现
那位开发者的环境是 OpenClaw 部署在一台云服务器上,模型源指向某第三方兼容 API。现象是:对话偶尔正常,有时候连续几次请求都报 LLM request timed out,过一会儿又自己恢复。出错频率大约每 10 次请求出现 1 到 2 次,完全没有规律可循。
我让他做了一件事:把报错前后 10 分钟的 OpenClaw 日志完整保留下来,同时用 curl 手动测同一个第三方 API 的响应时间。结果很说明问题:手动 curl 测试偶尔也会超时,但比 OpenClaw 的频率低很多。
这一步基本确认了:第三方 API 本身就不稳定,但 OpenClaw 的某些配置放大了这种不稳定性。
5.2 逐步验证
我让他按步骤验证了几个点:
第一步,检查配置文件里的超时设置。发现他设置的是 20 秒读取超时,但 curl 测试显示第三方 API 的 P95 响应时间是 22 秒。也就是说,每 20 个请求至少有 1 个的响应时间超过他的超时阈值,超时当然会发生。
第二步,查看日志里每次超时前的请求特征。发现超时的请求全部集中在上下文长度超过 8000 token 的场景。而短对话请求很少超时。这说明问题不仅和第三方 API 的负载有关,还和请求体大小有关。
第三步,检查并发情况。日志显示他的 OpenClaw 配置了多个会话同时运行,高峰期会有 5 个请求同时打到第三方 API。第三方网关在并发请求到来时出现了明显的排队,个别请求的响应时间被拉长到 30 秒以上。
三个因素叠加在一起:第三方 API 本身 P95 偏高、请求体过大、并发触发排队。任何一个单独拿出来都不是致命问题,但合在一起就把 20 秒超时时间打穿了。
5.3 最终配置
针对这个案例,我们做的调整如下:
- 读取超时从 20 秒调到 45 秒,缓冲区间按 P95 乘以 1.5 再加余量
- 开启上下文压缩,把超长历史会话的消息进行摘要,控制单次请求在 6000 token 以内
- 最大并发数限制到 3,避免同时太多请求打向第三方 API
- 重试次数设为 2 次,采用指数退避,第一次等 1 秒、第二次等 2 秒
- 增加了一个备用 provider,主 provider 连续超时 3 次后自动切换
调整之后稳定跑了两周,没有再出现过一次 LLM request timed out。配置大概长这样:
model: provider: openai_compatible model_name: your-model-name api_base: https://your-api-gateway.example.com/v1 api_key: ${OPENCLAW_API_KEY} max_tokens: 1024 stream: true timeout: connect: 10s read: 45s advanced: max_concurrency: 3 context_compression: true context_target_tokens: 6000 retry: max_attempts: 2 backoff_base: 1s backoff_multiplier: 2 retry_on_http: [429, 503]这个配置不是标准答案,但它反映了真实世界里解决超时问题需要的几个必要动作:给足缓冲、降低负载、控制并发、设置兜底。
6. 常见问题速查表与避坑心得
最后整理一个速查表,方便你遇到问题时快速对照。同时分享几个写文档的人通常不会写进文档里的经验。
6.1 快速对照表
| 现象 | 可能原因 | 解决方向 |
|---|---|---|
| 每次都在相同时间点超时 | 环境变量覆盖了配置文件的超时值 | 检查环境变量和配置文件优先级 |
| 请求偶尔超时,手动 curl 正常 | 并发请求触发第三方网关限流 | 降低 OpenClaw 最大并发数 |
| 长对话必超时,短对话正常 | 上下文 token 过多导致处理变慢 | 开启上下文压缩或裁剪历史消息 |
| 流式模式下仍超时 | 相邻 token 间隔超过读超时 | 配置独立的空闲超时参数 |
| 切换模型后开始超时 | 模型名称不匹配或模型负载过高 | 核对模型名,或更换备用模型 |
| 重启后超时消失,运行几小时后复发 | 第三方网关或本机连接被逐步耗尽 | 检查连接复用配置和资源泄漏 |
| 使用第三方聚合服务超时 | 聚合网关排队机制不合理 | 更换服务、配置备用 provider 或本地兜底 |
6.2 几个写文档的人不会告诉你的坑
第一个坑:健康检查比超时调优更重要。很多人只盯着超时参数改来改去,却忘了给第三方 API 加健康检查。我建议在 OpenClaw 侧配置定期探测,比如每 30 秒发一次极简请求,连续失败就标记服务不可用并切换。这样能把故障发现时间从几分钟缩短到几十秒。
第二个坑:不要把重试做成放大器。如果你的重试间隔很短,比如 100 毫秒,第三方服务还在过载中,你的重试请求会加剧排队,形成恶性循环。我见过一个案例,OpenClaw 默认重试 3 次且间隔很短,结果每次超时后第三方服务的负载反而更高。重试间隔一定要按指数退避来设,必要时加随机抖动。
第三个坑:流式响应不是万能的。有些第三方 API 对流式支持得并不好,或者流式模式下 TTFB 反而更长。开启流式之前,先用 curl 对比流式和非流式的首包时间。如果流式的 TTFB 更长,说明网关对流式处理有额外开销,这时候流式并不能解决超时问题。
第四个坑:版本升级要慎重。OpenClaw 本身迭代很快,新版本可能改动了超时字段名、重试逻辑或者线程模型。升级前先看 changelog,重点看有没有涉及网络层和请求调度的改动。我曾经在升级后遇到超时行为完全变化的情况,最后发现是新版本重写了连接池的复用逻辑,导致部分请求排队等待空闲连接,而旧版本没有这个问题。
第五个坑:不要忽略时区问题。如果你的日志和第三方 API 的响应头里都有时间戳,而两边时区不一致,排查超时时对不上时间线会非常痛苦。统一使用 UTC 记录日志,能省去大量对时间的精力。
我个人在实际操作中的体会是:LLM request timed out 这种问题,八成都不是代码 bug,而是资源和使用方式的错配。只要你能接受“第三方 API 就是会慢”这个现实,然后从超时阈值、请求体大小、并发数三个维度去做合理设计,绝大部分超时都能在配置层面解决。剩下那部分解决不了的,多半是第三方服务本身的稳定性问题,那就不是调参能解决的了,该换服务就换服务,该做兜底就做兜底。希望这篇排障记录能帮你少走几天弯路。