agentscope-ai / agentscope-ai/agentscope-java
[Bug]:abstractFilesystem() with user-registered SandboxLifecycleMiddleware should participate in wrappedCall lifecycle
- Linguagem predominante
- Java
- Estrelas
- 5.6k
- Forks
- 1.3k
- Merge médio
- 4d 12h
- PRs com merge (30d)
- 77
Descrição
When using builder.abstractFilesystem(sandboxFs) combined with builder.middleware(new SandboxLifecycleMiddleware(sandboxManager, sandboxFs)), the sandbox lifecycle is never triggered.
Root cause: HarnessAgent.wrappedCall() / wrappedStreamEvents() only invokes the private field sandboxLifecycleMw, which is exclusively populated through the
builder.filesystem(SandboxFilesystemSpec) path. SandboxLifecycleMiddleware does not override any MiddlewareBase methods, so adding it to the middleware chain via builder.middleware() is
a no-op.
Use Case
Custom tools (e.g., an OSS upload tool) need a reference to the SandboxBackedFilesystem instance at construction time to call execute() / downloadFiles(). These tools are registered via
builder.toolkit() before build().
With builder.filesystem(SandboxFilesystemSpec), the SandboxBackedFilesystem is created internally during build() — there's no way for user-provided tools to obtain a reference to it.
This forces users to use abstractFilesystem(), but that path has no lifecycle management, requiring manual acquireForCall / releaseForCall invocation from the application layer —
reimplementing the Mono.using() pattern that wrappedCall already provides.
┌───────────────────────────────────┬───────────────────┬───────────────────────────────────┐
│ Path │ Lifecycle managed │ Custom tool can access sandbox FS │
├───────────────────────────────────┼───────────────────┼───────────────────────────────────┤
│ filesystem(SandboxFilesystemSpec) │ ✅ │ ❌ │
├───────────────────────────────────┼───────────────────┼───────────────────────────────────┤
│ abstractFilesystem(fs) │ ❌ │ ✅ │
└───────────────────────────────────┴───────────────────┴───────────────────────────────────┘
Proposed Solution
In HarnessAgent.Builder.build(), if sandboxLifecycleMw is still null after the sandboxFilesystemSpec block, scan the registered middlewares for a user-provided
SandboxLifecycleMiddleware and promote it to the sandboxLifecycleMw field:
if (sandboxLifecycleMw == null) {
for (MiddlewareBase mw : allMiddlewares) {
if (mw instanceof SandboxLifecycleMiddleware slm) {
sandboxLifecycleMw = slm;
break;
}
}
}
This makes the existing abstractFilesystem() + middleware(SandboxLifecycleMiddleware) combination work as expected — the framework's wrappedCall() handles acquire/release automatically.
Alternatives Considered
1. Allow SandboxFilesystemSpec to accept a pre-created SandboxBackedFilesystem — more invasive API change.
2. Post-build tool registration — e.g., builder.afterSandboxReady(fs -> {...}) callback — new API surface.
3. Application-layer workaround (current) — call acquireForCall / releaseForCall from the service layer, bypassing framework lifecycle.
Environment
- agentscope-harness: 2.0.0-RC1 / 2.0.0-SNAPSHOT (main branch)
- Affected classes: HarnessAgent, SandboxLifecycleMiddleware
Guia de contribuição
Avaliação
Esta issue ainda não foi avaliada.