Skip to content

Claude Agent SDK session 上下文在长线程中持续膨胀,导致上游 API 408 流式超时 #43

Description

@ethuh

环境

  • Kagura 版本: v0.2.1 (commit 0a7289c,源码构建)
  • 部署方式: macOS,PM2 双实例 (codex-001 + cc-001)
  • cc-001 provider: claude-code
  • cc-001 后端: third-party Anthropic-compatible API (base URL + auth token)
  • cc-001 模型: opus[1m](实际代为解析为 gpt-5.5[1m],具备 1M 上下文上限)

问题描述

在同一个 Slack thread 中连续使用 cc-001(Claude Code provider)多轮对话后(约 10+ 轮),后续请求稳定出现 HTTP 408,Claude SDK 自动重试 10 次全部失败,最终 execution 状态变为 failed

错误日志关键片段:

[bootstrap:claude:session] ⚠ Claude API retry 1/10 after 556ms (http=408 error=server_error)
...
[bootstrap:claude:session] ⚠ Claude API retry 10/10 after 38624ms (http=408 error=server_error)

[bootstrap:claude:session] ERROR Claude Agent SDK execution failed:
Claude Code returned an error result: API Error: 408
{"error":{"message":"stream error: stream disconnected before completion:
stream closed before response.completed","type":"invalid_request_error"}}

而在新开 thread 中发送相同请求,一切正常。

根因分析(阅读源码后)

我阅读了以下关键代码后,确认问题来自于 Kagura 没有对 Claude Agent SDK 的 session 做任何上下文压缩或自动释放

  1. Slack 端: thread-context-loader.ts 硬编码 limit: 200,每轮拉取最多 200 条 Slack 消息并全部塞入 prompt(processors.ts:237-268
  2. SDK 端: 每次在同一 thread 里的后续消息都带 resumeHandle(即 claude_session_id),传给 agent-sdkquery({ resume: sessionId })adapter.ts:291
  3. 无 compact 机制: SDK 内部 session 历史持续累积——包括每次的工具调用、读文件、对话历史——且 Kagura 自身也没有任何截断/压缩/compact 的逻辑

实际观测到的单次请求规模:

Thread context loaded for ... (103 messages)
Token usage [gpt-5.5[1m]]: input=247,909 output=37,688 cache_read=713,728

这个请求规模加上 streaming 连接,上游/api 代理非常容易在任意环节(idle timeout/proxy/NLB/模型节点)触发 408 "stream disconnected before completion"。

一旦失败,SDK 的重试用的是同一个巨大的请求,必定持续失败,形成死循环。 只有重启 Kagura + 标记 execution 为 stopped 才能打破。

成功场景对比

  • 新开 thread: 一切正常(Slack 历史为空,无 SDK session resume)
  • /model reset: 能清掉 session handle,新请求不带 resume,从零开始
  • 切换 workspace: 文档提到会 "start a fresh session"

现有缓解手段(及其不足)

手段 是否有效 副作用
新开 thread 丢弃 Slack 内上下文的连续性
/model reset 未文档化为"上下文重置"工具
switch workspace 需要来回切,不自然
改小 CLAUDE_MAX_TURNS ⚠️ 部分缓解 只限制工具调用轮数,不管 session history 累积

建议

  1. 文档化: 在 README 或 architecture docs 中说明这个限制,推荐用户在长任务中定期使用 /model resetsave_memory + 新 thread 的工作流。
  2. 考虑自动机制: 例如在 SDK 层面提供 session compaction(类似 Claude CLI 的 /compact),或者在 Kagura 层面检测到 thread 过长后自动 reset session handle。
  3. 让 Slack 线程历史量可配置: thread-context-loader.ts 中的 limit: 200 写死了,建议做成环境变量(如 SLACK_THREAD_HISTORY_LIMIT)。

补充

这个问题用相同的 gpt-5.5 模型在 Codex CLI provider(codex-001) 上表现不同——Codex 走的是 CLI stdin 的 --resume 线程机制,出问题时 CLI 会报 "thread/resume failed" 并自动 fallback 到无 resume 的新 session。Claude agent SDK 没有这个兜底。


感谢佬的这个项目,它非常棒!但是目前尚不清楚是模型的问题,还是其他的问题,因为我没有换别的模型试过,也没有用codex试过在一个thread里长对话,目前对话轮数稍微多一些,就会408,不知道佬有没有什么好办法呢?另外,我也装了你的handoff那个skill,或许在slack这里面能用上?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions