agentscope-ai / agentscope-ai/agentscope-java

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

Đang mở
#2,645 1 bình luận 0 reaction 0 người được giao Xem trên GitHub
area/core/memory area/extensions area/harness bug
Ngôn ngữ chính
Java
Star
5.6k
Fork
1.3k
Merge trung bình
4 ngày 12 giờ
Pull request đã merge (30 ngày)
77

Mô tả

## 问题描述

在 `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` 分支的最新源码行为;如果该问题已经在后续未发布代码中修复,请忽略。

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Đánh giá

Issue này chưa được đánh giá.

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.