OpenClaw Agent Session 空闲超时后可能卡死:为什么 `sessions_send` 会持续 timeout,直到重启 Gateway
OpenClaw News Editorial
最新一条 OpenClaw bug 报告,指向了一个对自动化链路很伤的故障模式:当 agent session 因空闲而超时,进入 ended 状态 后,后续再调用 sessions_send,系统可能不会把这条 session 重新唤起,而是持续返回 timeout。
对运维来说,关键不只是“超时”本身,而是超时之后,系统不再像一个可恢复的消息驱动会话,而更像一个只有 重启 Gateway 才能恢复的失效端点。
当前被报告的现象是什么
按照 issue 描述,故障链路大致是这样:
- 一条 agent session 先正常运行
- 随后因长时间空闲而命中 timeout
- session 状态进入
ended - 之后再调用
sessions_send(sessionId, message)会返回timeout - 自动化无法自行恢复,只能手动重启 Gateway
这点很要命,因为很多运维会把 sessions_send 当作一个稳定的“重新唤起既有 session”的入口,用在定时 checkpoint、周期性任务派发或已有会话的后续编排里。
为什么这不是一个小超时问题
这不是单纯“报错难看”或者“偶发失败”这么简单。
它直接打到了一批常见的生产型用法:
- 定时 checkpoint 消息
- 周期性向既有 agent session 投递新任务
- 由 cron 或调度器触发的 follow-up 流程
- 默认假设“会话闲置后仍可复用”的后台工作流
一旦 ended session 不能被稳定拉回,团队通常会掉进三种坏结果:
- 自动化静默漂移:任务不再推进,但系统没有明确告诉你模型已经变了
- 人工保姆化:为了让流程恢复,只能靠人手动重启 Gateway
- 危险重试:在不知道旧状态是否还残留的情况下重复发任务,带来副作用重复风险
所以真正的伤害,不是“一次 timeout”,而是 大家不再相信 session reuse 这套自动化模式本身。
它和“正常 timeout”有什么不同
正常 timeout,本质上是生命周期策略事件。
你可能不喜欢,但它至少是清晰的:会话因规则而结束,系统行为仍然自洽。
这次报告的问题不同。用户抱怨的重点是:timeout 已经发生之后,恢复路径本身又坏了,或者根本不存在。
这就把问题边界推到了三者之间:
- session 生命周期状态
- 消息驱动的重新激活机制
- runtime / session 重新附着逻辑
如果 sessions_send 本来就应该是一个合法的再进入入口,那么 ended 之后持续 timeout,说明系统已经无法把“仍然可定位的 session 标识”重新映射回一条真正可执行的处理路径。
更像是哪一层出了问题
只根据当前 issue 信息看,这件事 不像只是 timeout 策略设得太短。
它更像是下面这类更深层的问题之一:
- session 记录还在,但已经不能真正 resume
- ended 在实现上等于终止态,但对外部调用者没有表达清楚
sessions_send命中的 session handle,已经无法干净地映射到 live worker / runtime 路径- Gateway 重启后,内部路由或状态附着被重建,因此发送能力暂时恢复
最后这一点很关键。如果重启 Gateway 能恢复行为,问题通常更接近恢复链路或 runtime 附着,而不是用户 prompt 或 cron 本身。
怎么确认你撞到的是同一个故障模式
如果下面几条同时成立,就很像是这次报告的同类问题:
- 这条 session 之前曾经能正常接收
sessions_send - 后来它因空闲进入
ended - 之后的 send 持续 timeout
- 不是换个普通消息或外部动作就能把旧 session 路径拉回来
- 只有 Gateway 重启后,链路才恢复可用
这组条件能把它和一些更简单的情况区分开,例如:
- session id 写错
- timeout 发生在 agent 内部某个工具调用,而不是会话入口
- cron 本身没触发
- 某个远程依赖暂时网络异常
- 原本设计上就是一次性 session,并不承诺复用
上游修复前,运维该怎么止血
在上游行为被明确或修复前,比较稳妥的做法是:把 idle timeout 之后的 ended agent session,视为“可能不可恢复”的对象。
更安全的操作方式包括:
1)不要默认 sessions_send 一定能拉活 ended session
如果这条流程是关键链路,设计上就要接受一种可能:ended 之后,不是 resume,而是需要 replace。
2)在投递关键 follow-up 前,加一道 session 健康检查
在发送下一条定时任务前,先确认目标 session 仍然处于预期状态,或者至少仍应接受新工作。
3)高价值任务优先设计成“可重建”,而不是“强依赖复用”
如果这条链路关系到收入、发布、审核或部署,优先采用可以干净起新 session 的工作流,而不是把稳定性压在一条长期复用的旧 session 上。
4)明确记录“超时”与“人工恢复”之间的边界
如果现在只能靠重启止血,就把 session 进入失败态的时间点、恢复后重放了什么动作记录下来,避免重复副作用,也方便后面排障。
接下来真正该关注什么
后续就算上游修了,也不只是“有没有 patch”这么简单。
更关键的问题其实是:sessions_send 面对 ended session 的契约到底是什么?
运维需要一个明确答案,至少三种模型里得占一种:
- ended session 应该被自动重新激活
- ended session 应该快速失败,并返回明确终止态错误
- ended session 应该透明地创建替代 session
这三种都可以接受,只要文档和行为一致。现在最伤的是中间态:外部看起来还能投递,实际却像死路,直到整台 Gateway 重启。
结论
这条 bug 值得关注,因为它命中的不是边缘场景,而是 可复用 agent automation 这类高意图生产用法。
如果你的工作流依赖 sessions_send 在空闲间隔之后继续驱动既有 session,不要把 timeout 当成一个无害状态变化。按当前报告,它可能会进一步演化成持续性的恢复失败,并让自动化链路卡死到必须重启 Gateway 为止。
如果你已经确认是 ended session 恢复失败,下一步最值得补哪层判断
如果你已经确认问题不只是一次 timeout,而是 ended 之后整条 session reuse 路径都不再可靠,下一步最值得补的判断通常有两层:
- 先看 OpenClaw Agents 排障指南:任务卡住、工具不回、结果异常时先查什么,确认是不是同时还叠加了 provider、工具调用或消息链路异常;
- 如果你的故障起点其实是 crash 或 restart,而不是 idle timeout,本页就不该单独看,应该回到 Gateway crash/restart 后 orphaned sessions 不会真正恢复 去区分是 session reuse 语义坏了,还是 restart recovery 本身没接回执行路径。
这层补充很重要,因为很多人会把“重启后恢复不了”和“ended 后 send 不起作用”混成同一个问题,结果越查越散。
自动化恢复前的高意图分流清单
在你把 Gateway restart 当成唯一修复动作前,先把这三类流量分开,否则后续数据会很难判断到底是哪条路径在失效:
- idle timeout 后发送失败:继续留在本页,重点看
sessions_send对 ended session 的契约。 - crash/restart 后任务丢失:转到 orphaned sessions 恢复问题,不要把它误记成普通 timeout。
- 工具或 provider 本身报错:先走 agents troubleshooting 总表,把 provider、工具调用和消息通道分层排掉。
这份分流清单能把中文高意图读者从“重启试试看”推进到可复现、可归因、可链接的故障入口。
如果你是从 setup 或 troubleshooting 进来,先分清 idle 恢复和启动失败
这篇现在和 setup 指南、troubleshooting 总表、ACP transcript-history 事故页处在同一组流量线索里。也就是说,很多读者不是单纯搜索 timeout,而是在判断 sessions_send 卡死到底是 agent 没启动、API 视图过旧,还是本文说的 idle session 恢复失败。
重启 Gateway 前,先按三类分流:
- session 从第一条消息就没接住:回到 setup 验证、认证、sandbox 和 runtime 启动日志,这篇大概率还不是主修复路径。
- run 有 transcript 证据,但 history 看起来为空:先对照 ACP transcript-history 文章,因为工作可能已经发生,只是 session API 投影过旧。
- session 曾经正常,空闲后所有后续
sessions_send都 timeout:再把它当作 ended-session recovery 边界,保留时间戳,并安排受控 Gateway 重启。
这能让从泛排障路径进来的高意图用户,先选最小扰动的恢复步骤,而不是直接重启生产链路。
重启 Gateway 前的恢复检查清单
如果事故正在发生,你需要快速判断是 resume、replace,还是 restart,可以按这份清单把 issue 报告变成可执行的恢复路径:
- 记录最后一次成功
sessions_send的时间,以及第一次 timeout 的时间。 - 确认目标 session 只是 idle、已经明确
ended,还是已经不在 session index 里。 - 只发送一条低风险诊断消息,不要立刻重放真正的业务任务。
- 如果诊断消息也 timeout,就给新工作创建替代 session,并把旧 session 标记为不可安全复用。
- 只有在保留 failed session id、相关日志和原本要投递的 follow-up 消息之后,再安排 Gateway restart,这样上游排查才能区分是路由被修好,还是状态已经丢失。
这里的关键不是“能不能靠重启恢复”,而是不要一上来就重启。重启太早会抹掉最有价值的证据,让你很难判断真实问题到底是 ended-session reactivation、orphaned runtime attachment,还是调用方自己的 retry loop。
sessions_send 超时时,先确认任务是不是还活着
sessions_send 超时不一定等于 agent 已经失败。更常见的情况是目标 session 仍在执行长任务,只是调用方等待窗口太短,或者结果事件没有及时回到当前通道。排查时先把它拆成“任务存活、结果回传、调用方超时”三层:
- 先查目标 session 的最近活动时间和最后一条输出,确认它是不是仍在推进;
- 如果 session 还活着,不要立刻重复发送同一指令,先延长等待或改用状态查询;
- 如果 session 已经无输出,再看是否卡在工具调用、模型响应、部署环境或通道回传。
这段适合承接“OpenClaw sessions_send timeout”“agent session still running but no reply”“跨 session 调用超时”这类搜索,把读者从盲目重试引到更稳的状态判定路径。
相关阅读
搜索入口分流:sessions_send 超时先看哪一层
如果你是从 “sessions_send timeout”、“agent session timeout” 或 “OpenClaw 子代理不返回” 搜到这里,先别把问题归因到模型慢。按下面顺序拆:
- 先确认目标 session 是否仍活着:如果目标会话已经退出或被清理,继续重试只会制造更多等待。
- 再看工具调用边界:区分是
sessions_send发不出去、子任务执行太久,还是回包在路由层丢失。 - 检查 timeout 设置是否匹配任务形态:长任务应该拆成后台任务或明确等待点,而不是用一个同步调用硬等到底。
- 保留 target session id 和时间戳:后续查日志时,session id、调用时间、超时秒数比“它卡住了”更有用。
这类故障最有效的处理方式,是把“模型没回”拆成“会话存活、工具投递、任务执行、结果回传”四段逐段验证。
相关阅读
- OpenClaw Agents 排障指南:任务卡住、工具不回、结果异常时先查什么
- Gateway 崩溃重启后没有恢复孤儿会话时,先查什么
- OpenClaw 记忆系统指南:什么该记、什么不该记、记住后怎么补验
- 如何使用 OpenClaw 构建自愈基础设施
可复用 session 自动化的告警模式
对高意图自动化来说,真正有价值的告警不只是“某次 send timeout”。更应该记录能证明旧 session 复用路径已经不安全的序列:
- 同一个目标 session 之前能正常接住
sessions_send; - 之后该 session 进入 idle 或 ended 状态;
- 在重放业务任务前,低风险诊断 follow-up 已经 timeout;
- 新建 session 可以工作,但旧目标仍然失败。
这四段组合能把 ended-session recovery bug 和慢模型、长工具调用、调用方 timeout 设置过短区分开。
如果这个模式出现在定时发布、审核、收件箱分流或部署流程里,先把新工作路由到替代 session。旧 session 应该作为排查证据保留,而不是继续把关键任务往里面重试。
从值班视角给 sessions_send 失败分级
如果这篇是你从中文搜索结果点进来的,建议先把 sessions_send 失败分成三个等级,避免一上来就重启 Gateway:
- 可重试级:只有一次 send 超时,目标 session 仍有后续输出,先降低并发或延长等待,不要立即判定为 ended-session bug。
- 需替换级:同一个 ended session 连续 timeout,但新建 session 可以正常工作,先把新任务切到替代 session,并保留旧 session id 做证据。
- 需重启级:替代 session 也无法接管,或 Gateway 内部路由已经无法定位运行路径,再把受控 restart 当成恢复动作。
这层分级能把搜索流量里的“偶发慢”“旧 session 不可复用”和“Gateway 路由坏掉”拆开,也能让读者先选择最小扰动的恢复方案。
给自动化编排加一条替代 session 路由
如果这类 timeout 已经出现在定时任务或后台编排里,不要只把告警写成“旧 session 失败”。更可执行的做法,是在编排层预留一条替代 session 路由:当旧 session 连续两次诊断发送失败时,新业务任务自动切到 fresh session,旧 session 只保留给证据采集和上游复现。
这条路由尤其适合发布、审核、数据同步这类不能长时间卡住的流程。它能把用户搜索里的“sessions_send timeout 怎么办”转成一个明确操作:先隔离旧会话,再让新任务继续推进,最后再决定是否需要 Gateway restart。为了让上游能复现,还要保留 failed session id、首次 timeout 时间、诊断消息和重启前 Gateway 日志,避免 restart 太早抹掉关键证据。
FAQ:idle 后 sessions_send timeout 怎么判断
还要继续重试同一个 ended session 吗?
不建议把它当作第一恢复动作。如果同一个 ended session 连续两次低风险诊断发送都 timeout,先把新业务任务切到替代 session,并保留旧 session 做日志证据。继续把生产任务打进旧目标,可能只会制造重复副作用,却不能证明恢复链路正常。
什么时候才该重启 Gateway?
把 restart 当成受控恢复步骤,而不是第一排障动作。只有在证据已经保存、fresh session 也无法接住新工作,或者日志显示 Gateway 已经无法把消息投递附着到任何 live runtime 路径时,重启才更像合理恢复动作。
给上游报 bug 时最该留下什么?
至少保留 target session id、最后一次成功发送时间、第一次 timeout 时间、session 当时是 idle 还是明确 ended,以及 fresh replacement session 是否可用。这些信息能把生命周期语义问题和路由恢复问题拆开。
定时任务和后台作业的恢复 playbook
如果 timeout 出现在周期性作业里,不要只把它当成聊天界面问题,而要按“工作流连续性”处理。更实用的 runbook 是:
- 同一个旧 session 连续两次诊断
sessions_sendtimeout 后,标记为不安全; - 在重放任何带写入副作用的任务前,先创建或选择替代 session;
- 只复制继续作业所需的最小上下文,不要整段搬运失败 transcript;
- 记录替代 session 是否完成了同一个业务步骤;
- 等新路径保护住用户可见工作流后,再回头检查 Gateway 日志。
这段流程更适合“OpenClaw cron sessions_send timeout”这类搜索意图:先保证发布、部署、分流作业继续推进,同时保留足够证据给上游复现。
来源
- Bug 报告: openclaw/openclaw#60948
