Skip to content

Rename VM executor limit to guest-execution cap with env override - #1913

Draft
jog1t wants to merge 1 commit into
mainfrom
claude/maxactivevms-exposure-analysis-nd6qqa
Draft

Rename VM executor limit to guest-execution cap with env override#1913
jog1t wants to merge 1 commit into
mainfrom
claude/maxactivevms-exposure-analysis-nd6qqa

Conversation

@jog1t

@jog1t jog1t commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator

Rename the process-wide concurrency limit from max_active_vm_executors to max_active_guest_executions to better reflect that it bounds all guest processes (JavaScript, TypeScript, Python, WASM) rather than just V8 isolates. Add operator-configurable override via AGENTOS_MAX_ACTIVE_GUEST_EXECUTIONS environment variable with validation and improved error messaging.

Key changes

  • Renamed configuration field: RuntimeConfig.max_active_vm_executorsmax_active_guest_executions throughout the codebase
  • New constants:
    • DEFAULT_MAX_ACTIVE_GUEST_EXECUTIONS = 64 (fixed default, no longer derived from CPU count)
    • MAX_ACTIVE_GUEST_EXECUTIONS_CEILING = 1024 (hard upper bound)
    • MAX_ACTIVE_GUEST_EXECUTIONS_ENV (environment variable name)
  • Environment override: Added RuntimeConfig::apply_env_overrides() and apply_env_overrides_from() methods that parse and validate the environment variable before any VM is created
  • Validation: Invalid overrides (non-numeric, zero, negative, or above ceiling) fail with typed errors naming the variable and bounds rather than silently clamping
  • Error messages: Updated all guest-execution limit errors to reference the environment variable and explain that every live guest process holds one slot for its whole lifetime
  • Documentation: Added comprehensive resource-limits guide explaining the cap, sizing guidance, and debugging section for limit-exceeded errors
  • Logging: Sidecar now logs the effective admission ceiling at startup for observability
  • Tests: Added comprehensive test coverage for environment override parsing, validation, and error cases

Implementation details

The default is now a fixed constant (64) rather than derived from available_parallelism(), ensuring identical admission ceilings across hosts. This prevents silent rejection of ordinary workloads on small hosts (e.g., a shell plus the command it waits on already needs two slots).

The override is read once at process startup via apply_env_overrides() before SidecarRuntime::process() fixes topology, ensuring the ceiling is process-wide and shared by all VMs. A present-but-invalid value is a hard error, never silently clamped or fallen back to default — an operator who explicitly requests a specific ceiling must get exactly that or a clear error.

Limit-exceeded errors now name AGENTOS_MAX_ACTIVE_GUEST_EXECUTIONS so operators know exactly which knob to turn, and explain the lifetime semantics (parent and child each hold one slot).

https://claude.ai/code/session_0182QmdSp9xAUey53LViPA8B

@railway-app

railway-app Bot commented Aug 24, 2026

Copy link
Copy Markdown

🚅 Environment agentos-pr-1913 in rivet-frontend has no services deployed.

…nable

The process-wide V8 executor slot cap was derived from available_parallelism()
and had no override path in any shipped build: every runtime.* config value came
from RuntimeConfig::default(). Its own limit error told operators to "raise
runtime.executor.maxActiveVms", a knob nothing could set.

The cap admits concurrently running guest executions, not VMs. Every live guest
process holds one slot for its whole lifetime, so a shell and the command it
waits on need two, and a fleet of parallel agents exhausts it well before any
per-VM cap. CPU count is the wrong unit: the slot costs one OS thread and one
thread-affine V8 isolate, and an agent parked on a network read burns no CPU
while holding one.

- Read AGENTOS_MAX_ACTIVE_GUEST_EXECUTIONS at sidecar startup, before the
  process topology is fixed. Missing, non-numeric, zero, or above-ceiling
  values fail startup with a typed error instead of being clamped.
- Default to a fixed 64 rather than the host core count, so admitted
  concurrency no longer varies per machine, with a hard ceiling of 1024.
- Rename the knob, config field, and limit error to say guest executions, and
  point the error at a variable an operator can actually set.
- Log the effective ceiling at startup so the admitted value is observable
  before an execution is rejected for exceeding it.

Kept process-scoped rather than exposed as a client wire field: one sidecar
process is shared by every VM and connection it hosts, so no single tenant may
rewrite the ceiling for its neighbours.
@jog1t
jog1t force-pushed the claude/maxactivevms-exposure-analysis-nd6qqa branch from 418ac77 to 70c8b83 Compare August 24, 2026 22:31
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.

1 participant