Agent集体卡死原因分析及解决方案

故障时间线

本次故障从触发到恢复历经约8个小时,关键节点如下:

时间 事件 状态
10:00:21 handai/deepseek-v4-flash 模型服务首次返回 400 format 错误 触发点
10:12:42 h0assistant 主会话 context overflow(290条消息),自动压缩超时 加剧
10:15:41 上下文压缩 Compaction timed out, failover 到 qwen3.5-flash 失败
10:46 首次 long-running session 告警 队列积压
13:01~13:12 handai/deepseek-v4-flash 反复出 format 400 恶化
13:21~17:37 h0assistant 卡死 processing 状态 完全卡死
16:17 飞书消息无法响应 影响用户
17:33 手动导出诊断包并重启网关 恢复

根本原因分析

本次故障并非单一故障点,而是链式连锁反应的结果.

触发点: 模型提供商 Tool Schema 兼容性问题

调用链路: OpenClaw -> handai(newapi) -> 火山引擎 deepseek-v4-flash. 日志中出现: FailoverError: provider rejected the request schema or tool payload. status=400, reason=format. 火山引擎 deepseek-v4 在 tool_call 参数校验上与 OpenAI 标准不完全一致,复杂 tool call 触发校验失败.

加剧因素 1: Context Overflow 死循环

290条历史消息触发 context overflow,自动压缩超时,全量摘要也失败,形成死循环.

加剧因素 2: 内存压力过高

网关进程内存达 1.95 GB,加载 59 个插件,大量未使用.

加剧因素 3: 历史会话积压

主 agent 66 个会话, h0assistant 18 个会话.

已采取的解决方案

方案一: 关闭模型 Tool Call 能力

compat.supportsTools = false,规避火山引擎 tool schema 校验问题.

方案二: 插件白名单削减

59 个插件缩减到 24 个必要插件.

方案三: 内存压力立即缓解

重启后内存从 1.95 GB 下降至 432 MB.

防御建议

建议一: 定期清理历史会话

建议二: 控制模型兼容性

建议三: 添加 Context Overflow 告警监控

效果总结

指标 整改前 整改后 变化
网关内存 1,955 MB 432 MB darr;78%
插件数量 59 个 24 个 darr;59%
deepseek-v4-flash tools 开启 关闭 规避 400 format

本次故障揭示了 AI Agent 系统在生产环境中的典型威胁:模型提供商兼容性问题、上下文管理失败、插件臃肿、内存危机之间形成链式反应.


后续复盘:supportsTools: false 是双刃剑(2026-07-01 更新)

在采用 supportsTools: false 作为应急方案一段时间后,我们发现这个配置本身引发了新的问题。

背景补充:DeepSeek 官方 vs 火山引擎

经查证,DeepSeek 官方 API(api.deepseek.com)完全支持 Function Calling</strong,遵循 OpenAI 标准 tools 参数格式。当时的 400 错误来自火山引擎的 deepseek-v4-flash 端点,其 tool_call 参数校验与 OpenAI 标准不完全一致。

调用链路:OpenClaw → handai(newapi) → 火山引擎 deepseek-v4-flash

supportsTools: false 的实际效果

通过 OpenClaw 源码分析,supportsTools: false 的效果是”禁用了一半”:

层面 行为 是否符合预期
API 请求 不传 tools 字段给模型 API ✅ 符合
工具构建 传给 runner 的工具列表为空 ✅ 符合
System Prompt 仍然包含完整的工具描述(”你可以用 exec 工具…”) ❌ 不符合

原因:effectiveToolsAllow(决定 system prompt 中列出哪些工具的参数)不依赖 toolsEnabled,而是来自 params.toolsAllow。因此即使工具被禁用,system prompt 仍然告诉模型”你有 exec、read、write 等工具可用”。

引发的新问题:死循环

在 2026-07-01 的分析中,我们发现 supportsTools: false 配置下的 deepseek-v4-flash 陷入了工具调用死循环(详见 OpenClaw 会话死循环案例分析)。

矛盾点:如果工具确实被禁用了,模型不应该能执行工具调用。但实际观察到模型反复执行 exec 命令 166 次,上下文膨胀到 654K tokens。

可能的解释:

  • 模型收到 system prompt 说有工具可用,但 API 请求里没有 tools 定义,于是在文本输出中”模拟”工具调用格式
  • OpenClaw 的 DSML 过滤器或其他文本解析路径检测到这些工具调用块并执行了它们
  • 或者触发了 fallback 机制,切换到有工具能力的模型执行了工具调用

利弊分析

时间维度
短期(应急) 立即消除 400 错误,恢复服务 模型不能正常调用工具
长期(现状) system prompt 仍诱导工具使用 → 死循环;虚假安全感;模型能力浪费

建议的长期方案

  1. 排查火山引擎 tool schema 兼容性问题:具体是哪个字段不兼容?能否在 handai provider 层做 schema 转换?
  2. 或换用 DeepSeek 官方 APIapi.deepseek.com)代替火山引擎端点,官方 API 完全兼容 OpenAI 格式
  3. 恢复 supportsTools: true,同时确保 loop detection 对 exec 生效(参考 Issue #93917
  4. 如果确实需要禁用工具:应该同时从 system prompt 中移除工具描述,而不是只禁用 API 层面的工具传递

本次复盘的核心教训:supportsTools: false 只禁用了 API 层面的工具传递,但没有同步调整 system prompt,导致”告诉模型有工具但又不给工具”的矛盾状态,反而引发了更严重的死循环问题。

作者: Jack.shang

jack.shang 程序员->项目经理->技术总监->项目总监->部门总监->事业部总经理->子公司总经理->集团产品运营支持