agentscope-ai / agentscope-ai/agentscope-java

[Bug]: SessionSandboxStateStore 与 MysqlAgentStateStore 组合使用时,内部 sandbox session ID 含路径分隔符导致持久化失败

未關閉
#2,645 1 則留言 0 個 reaction 已指派 0 人 在 GitHub 檢視
area/core/memory area/extensions area/harness bug
主要語言
Java
星號
5.6k
分支
1.3k
平均合併
4 天 12 小時
30 天內合併 PR
77

描述

## 问题描述

在 `HarnessAgent` 同时使用以下能力时:

- `MysqlAgentStateStore`
- sandbox filesystem
- `IsolationScope.SESSION`
- 外部 sandbox provider(本项目里是 `AgentLoopFilesystemSpec`)

一轮对话结束后,sandbox 状态持久化会失败。

这里并不是业务侧传入的 `sessionId` 有问题。业务侧传入的是正常值,例如:

```text
session-030127f5-e0bd-4207-af2d-d14f9f89d820
```

异常发生在 AgentScope 内部通过 `SessionSandboxStateStore` 保存 sandbox 状态时,最终传给 `MysqlAgentStateStore` 的内部 ID 含有路径分隔符。

## 异常堆栈

```text
[sandbox] Failed to persist sandbox state: Failed to save sandbox state for SandboxIsolationKey{scope=SESSION, value='session-030127f5-e0bd-4207-af2d-d14f9f89d820'}
java.io.IOException: Failed to save sandbox state for SandboxIsolationKey{scope=SESSION, value='session-030127f5-e0bd-4207-af2d-d14f9f89d820'}
at io.agentscope.harness.agent.sandbox.SessionSandboxStateStore.asIo(SessionSandboxStateStore.java:95)
at io.agentscope.harness.agent.sandbox.SessionSandboxStateStore.save(SessionSandboxStateStore.java:63)
at io.agentscope.harness.agent.sandbox.SandboxManager.persistState(SandboxManager.java:208)
at io.agentscope.harness.agent.middleware.SandboxLifecycleMiddleware.releaseForCall(SandboxLifecycleMiddleware.java:148)
Caused by: java.lang.IllegalArgumentException: AgentStateStore ID cannot contain path separators
at io.agentscope.extensions.mysql.state.MysqlAgentStateStore.validateSessionId(MysqlAgentStateStore.java:816)
at io.agentscope.extensions.mysql.state.MysqlAgentStateStore.save(MysqlAgentStateStore.java:328)
at io.agentscope.harness.agent.sandbox.SessionSandboxStateStore.save(SessionSandboxStateStore.java:60)
```

## 最小复现

### 运行时接入方式

```java
HarnessAgent.Builder builder = HarnessAgent.builder()
.name("test-agent")
.model(model)
.stateStore(new MysqlAgentStateStore(dataSource, false));

builder.filesystem(new AgentLoopFilesystemSpec(sandboxClient, "./workspace")
.isolationScope(IsolationScope.SESSION));
```

### RuntimeContext

```java
RuntimeContext runtimeContext = RuntimeContext.builder()
.userId("1000000026668240")
.sessionId("session-030127f5-e0bd-4207-af2d-d14f9f89d820")
.build();
```

执行一次正常对话,等 sandbox 生命周期在结束阶段落库,即可复现该问题。

## 期望行为

使用 `MysqlAgentStateStore` 时,sandbox 状态可以正常持久化。

## 实际行为

sandbox 状态持久化失败。原因是内部生成的 sandbox state ID 含有 `/`,而 `MysqlAgentStateStore` 明确拒绝带路径分隔符的 session ID。

从本地排查看,内部 ID 形态类似:

```text
sandbox/session/
sandbox/user//
sandbox/agent/
sandbox/global
```

这些值作为框架内部 namespace 风格 ID 是合理的,但与 `MysqlAgentStateStore.validateSessionId(...)` 的约束不兼容。

## 根因分析

这看起来是以下两个官方组件之间的兼容性问题:

- `io.agentscope.harness.agent.sandbox.SessionSandboxStateStore`
- `io.agentscope.extensions.mysql.state.MysqlAgentStateStore`

`SessionSandboxStateStore` 使用带 `/` 的内部 ID 对 sandbox state 做 namespacing,
而 `MysqlAgentStateStore` 又要求传入的 session ID 不能包含路径分隔符。

因此下面这组能力组合当前会失败:

- 开启 sandbox state persistence
- 任意 sandbox isolation scope
- 底层使用 `MysqlAgentStateStore`

把隔离级别从 `SESSION` 改成 `USER` 也不能解决,因为内部 ID 依然带 `/`。

## 建议修复方向

建议不要把带 `/` 的内部 sandbox namespace ID 直接作为 `sessionId` 传给 `AgentStateStore`。

例如可以考虑以下几种方式之一:

1. 在 sandbox persistence 层对内部 ID 做编码后再传给 `AgentStateStore`
2. 将 sandbox namespace 与业务 `sessionId` 拆成不同字段,而不是复用同一个 `sessionId`
3. 对框架内部生成的 sandbox ID 放宽 `MysqlAgentStateStore` 的校验规则

## 运行环境

- Java: 17
- Spring Boot: 3.1.12
- AgentScope Java: 2.0.0
- State store: `agentscope-extensions-mysql`
- Database: MySQL 8.0
- Sandbox provider: external provider via `AgentLoopFilesystemSpec`

## 说明

这里的复现代码和结论是基于:

- 当前项目实际依赖的 AgentScope Java `2.0.0`
- 本地运行时异常堆栈
- 本地对相关类调用链的排查

我没有在此 issue 中声称它对应 GitHub `main` 分支的最新源码行为;如果该问题已经在后续未发布代码中修复,请忽略。

貢獻指南

開啟貢獻指南

評估

這個 Issue 還沒有評估資料。

把新 issue 寄到你的電子郵件信箱

精選適合新手參與的 GitHub issue 摘要。