agentscope-ai / agentscope-ai/agentscope-java
[Bug]: SessionSandboxStateStore 与 MysqlAgentStateStore 组合使用时,内部 sandbox session ID 含路径分隔符导致持久化失败
- 主要语言
- 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 还没有评估数据。