Skip to content

fix(dataplane): make the self-hosted environment worker path usable - #2818

Open
vipzj wants to merge 2 commits into
agentscope-ai:mainfrom
vipzj:fix/self-hosted-worker-path
Open

fix(dataplane): make the self-hosted environment worker path usable#2818
vipzj wants to merge 2 commits into
agentscope-ai:mainfrom
vipzj:fix/self-hosted-worker-path

Conversation

@vipzj

@vipzj vipzj commented Aug 23, 2026

Copy link
Copy Markdown

Problem

The self-hosted environment (type self_hosted) hands execution to an external HandsWorkerMain worker, but on current main the whole worker path is broken — every worker API call fails before doing any work:

  1. 401 on every worker request. EnvironmentKeyAuthFilter calls ControlPlaneClient.verifyEnvironmentKey from the reactive security filter chain (a reactor-http-epoll thread). The WebClient call inside ends with .block(), which Reactor rejects on NonBlocking threads:
verifyEnvironmentKey failed for env_xxx: block()/blockFirst()/blockLast()
are blocking, which is not supported in thread reactor-http-epoll-4

Verification therefore always returns false and the filter never sets the env:<id> authentication, so pending-tools / tool-results / work/poll all answer 401.

  1. 502 / intermittent failures on the worker controllers. SelfHostedWorkerController and WorkerEnvironmentController wrap blocking work (session resolve through ControlPlaneClient, work-queue ops) in Mono.fromCallable without subscribeOn, so the callable runs on the subscribing parallel-* thread:
resolveSession failed for sess_xxx: block()/blockFirst()/blockLast()
are blocking, which is not supported in thread parallel-1

GET /api/environments/{id}/sessions/{sid}/pending-tools returns 502 and work/poll fails intermittently.

Fix

  • ControlPlaneClient: run the blocking key verification on a small dedicated daemon thread pool instead of the event-loop thread.
  • Both worker controllers: add .subscribeOn(Schedulers.boundedElastic()), matching what the other data-plane controllers (DataSessionApiController) already do — the class javadoc of ControlPlaneClient explicitly requires callers to schedule off the event loop.

Verification

Deployed the data plane with these patches and verified the full flow end to end with a real HandsWorkerMain worker:

  • pending-tools / tool-results / work/poll return 200 with valid environment keys (X-Builder-Environment-Key);
  • a session on a self_hosted environment suspends with session.requires_action (tool_suspended) as designed;
  • the external worker polls the work queue, executes execute + write_file locally, posts results, and the suspended turn resumes and produces the final agent.message.

mvn spotless:check and mvn -pl agentscope-service/service-dataplane package pass.

vipzj added 2 commits August 23, 2026 23:55
EnvironmentKeyAuthFilter calls ControlPlaneClient.verifyEnvironmentKey from
the reactive security filter chain (reactor-http-epoll thread). The WebClient
chain inside ends with .block(), which Reactor rejects on NonBlocking threads,
so verification always failed and every self-hosted environment worker request
was rejected with 401:

    verifyEnvironmentKey failed for env_xxx: block()/blockFirst()/blockLast()
    are blocking, which is not supported in thread reactor-http-epoll-4

Run the blocking verification on a small dedicated thread pool instead.
SelfHostedWorkerController and WorkerEnvironmentController wrap blocking work
(session resolve via ControlPlaneClient, work queue ops) in Mono.fromCallable
without subscribeOn, so the callable runs on the subscribing parallel/event-loop
thread and fails with:

    resolveSession failed for sess_xxx: block()/blockFirst()/blockLast()
    are blocking, which is not supported in thread parallel-1

The pending-tools endpoint returned 502 and work/poll failed intermittently,
which made the self-hosted hands worker unusable. Add
.subscribeOn(Schedulers.boundedElastic()) like the other data-plane
controllers (DataSessionApiController) already do.
@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@codecov

codecov Bot commented Aug 23, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 0% with 43 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...pe/builder/web/api/SelfHostedWorkerController.java 0.00% 26 Missing ⚠️
...e/builder/web/api/WorkerEnvironmentController.java 0.00% 17 Missing ⚠️

📢 Thoughts on this report? Let us know!

@oss-maintainer

Copy link
Copy Markdown
Collaborator

CLA Not Signed

The Contributor License Agreement (CLA) check is currently pending on this PR (license/cla: Contributor License Agreement is not signed yet.). This PR cannot be merged until the CLA is signed.

@vipzj please sign the CLA via the CLA assistant badge in the comment above, or visit https://cla-assistant.io/agentscope-ai/agentscope-java. Once signed, the license/cla status will turn green.


Automated check by github-manager-bot

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants