OpenClaw Node Hosting Gets Real Capacity Control: CPU-Based Default and nodeHost.workerRuns.capacity Override
A merged PR deletes the hardcoded two-session cap per paired node. Capacity now defaults to one worker session per available CPU core (clamped to 1024) with an explicit config override — a significant change for anyone distributing session load across machines.
Two merged changes reshape how OpenClaw distributes session work across paired machines, and together they remove the two biggest frictions in fleet-style deployments: a hardcoded concurrency ceiling and hand-picked node targeting.
From hardcoded two to hardware-honest defaults
Node session hosting capped every paired node at exactly 2 concurrent worker sessions. The constant lived in src/node-host/node-worker-capacity.ts, and although a capacity option existed in the plumbing, the only production construction site never passed it — so a 32-core Mac Studio hosted precisely two sessions and there was no knob to change that.
PR #128352 deletes the hardcap rather than preserving a compatibility path:
- default capacity is now
os.availableParallelism()(falling back toos.cpus().length), clamped to[1, 1024]; nodeHost.workerRuns.capacity(strict integer, 1–1024) is the explicit override, wired from config; enforcement stays node-local — the Gateway cannot set it remotely;- slot journaling,
{total, available}inventory publication, and the 10-second admission wait are untouched. Only the ceiling moved.
Regression tests prove the override publishes {total: N} in the runner inventory and that mocked parallelism values of 0/7/1025 yield capacities of 1/7/1024.
Any available node: automatic placement
sessions.dispatch previously required an explicit {profileId} or {deviceId}, so multi-node operators hand-picked a target for every session. PR #128421 adds autoDevice: true, mutually exclusive with explicit targets:
- the gateway ranks eligible session-host runtimes by most available worker slots with a deterministic tie-break, reports the chosen
deviceId, and fails over through at most three candidates when a selected node churns at the pre-provisioning fence (authorization and provisioning errors never rotate); - with no eligible host, dispatch fails fast stating why — none paired, all disconnected, at capacity, or update required; and
- the Control UI’s new-session picker gains an “Any available node” option, disabled with a reason when no session hosts exist.
Live two-node proof in the merge record covers ranking by free slots, end-to-end dispatch onto a real node worker, reselection after killing the preferred node, and the exact mutual-exclusion error.
Operator guidance
- Treat the new capacity default as a load-model change: after updating a node, its concurrent-session ceiling jumps from 2 to core count. Size memory and model backends accordingly, or set
nodeHost.workerRuns.capacityexplicitly before restarting nodes into production. - Update nodes on your schedule — the default changes at update + node restart, not silently mid-run.
- If you automate dispatches,
autoDevice: trueplus reported placement gives you fleet balancing without a scheduler; keep explicit targets where affinity matters, since autoDevice and explicit IDs are mutually exclusive by schema.
THE RECEIPTS
Claims should survive the click.
Primary links used for this article are listed openly. If the evidence changes, the verification date changes with it.THE OPERATOR BRIEF