agentscope-ai / agentscope-ai/agentscope-java

[Bug]:abstractFilesystem() with user-registered SandboxLifecycleMiddleware should participate in wrappedCall lifecycle

Open
#1,605 0 comments 0 reactions 0 assignees View on GitHub
area/harness bug
Dominant language
Java
Stars
5.6k
Forks
1.3k
Avg merge
4d 12h
Merged PRs (30d)
77

Description

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

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.