Skip to content

ACP client 未归还连接池导致每次发送冷启动,acp.runtime.ttlMinutes 配置失效

问题

使用 claude-agent-acpgemini --acp adapter 时,即使配置了 acp.runtime.ttlMinutes,每次 agent 发送消息仍然都要经历冷启动(重新初始化 ACP 进程),导致响应极慢。

版本:openclaw 2026.4.15(npm global install)

根本原因分析(社区深度排查):

经代码审计发现三个死亡点必须同时修复:

  1. runTurn 缺少 finally 块:ACP client 执行完后未归还连接池,导致连接泄漏
  2. createInitialRecord 不存储 mode 字段(L3909):初始化时丢失 mode 信息
  3. ensureSession 的 reuse 分支不回填 mode(L3959):复用已有 session 时 mode 永远是 undefined

三个问题共同导致:每次 runTurn 都认为需要新建 session,即使连接池里有可用 client 也无法复用。

解决方案

方案一:等待官方修复

该问题已报告并提交了修复方案,关注官方 release notes。

方案二:临时降低冷启动影响

agents.defaults 中适当增大超时配置,减少因冷启动导致的请求失败:

yaml
agents:
  defaults:
    acp:
      runtime:
        ttlMinutes: 30      # 即使无法复用,也减少启动频率
        startupTimeoutMs: 15000  # 给冷启动更多时间

方案三:本地 patch(高级用户)

runTurn 的核心执行逻辑中添加 finally 块:

js
// 伪代码示意,具体路径需根据安装版本确认
async function runTurn(session, input) {
  const client = await pool.acquire(session.acpxRecordId);
  try {
    return await client.turn(input);
  } finally {
    pool.release(client);  // 确保归还
  }
}

同时在 createInitialRecord 返回值中补充 mode 字段,并在 ensureSession 的复用分支中回填。

常见问题

Q: 如何判断是否命中此 bug?

A: 查看 gateway 日志,若每次消息处理都出现 ACP cold startinitializing adapter 日志,而不是 reusing session,则说明连接池复用失败,属于此 bug 范围。

Q: acp.runtime.ttlMinutes: 0 是否可以禁用连接池?

A: 设为 0 表示每次都新建(无 TTL 限制),实际上是将"冷启动"变为预期行为,可以作为临时绕过手段,代价是放弃性能优化。