Rensei docs

Capacity Pools

Pools, substrate resolution, and runtime_provides override.

Capacity pools are the link between the Rensei scheduler and your execution infrastructure. Each pool binds a provider class (e.g. docker, e2b) to a set of configuration values and declares what substrate requirements that pool can satisfy. When the platform dispatches an agent session it selects a pool - not a provider directly.

Substrate resolution order

The scheduler resolves substrate capabilities in this order for every pool it evaluates:

flowchart TD
    A([Scheduler evaluates pool]) --> B{runtime_provides\ncolumn is non-null?}
    B -- yes --> C[Use operator override\nfull replacement, not merge]
    B -- no --> D{providerId in\nPROVIDER_CLASS_DEFAULT_CAPABILITIES?}
    D -- yes --> E[Use class default\nfor that provider]
    D -- no --> F[Return empty declaration\nno capabilities advertised]
    C --> G[Match against agent card\nsubstrate requirements]
    E --> G
    F --> G
    G --> H{All required\nkinds satisfied?}
    H -- yes --> I([Pool is eligible])
    H -- no --> J([Pool filtered out])

The key invariant: runtime_provides is a full replacement. If you set it, list every capability the pool provides - omitting a kind silently removes it from the pool's advertised surface, even if the class default would include it.

What a pool is

A pool record in execution_provider_pools stores:

ColumnPurpose
idUUID primary key
orgIdOrg that owns this pool
providerIdProvider class: local, docker, kubernetes, e2b, daytona, modal, vercel
nameHuman-readable label shown in the capacity settings UI
configJSONB - provider-specific config (image, namespace, kubeconfig, etc.)
runtime_providesJSONB - operator substrate override, or null to use class defaults
isActiveWhether this pool accepts new sessions

A single provider class can have multiple pools. This is useful when you have heterogeneous infrastructure - for example, a Kubernetes cluster with GPU nodes and CPU-only nodes can be modelled as two separate kubernetes pools with different runtime_provides declarations.

Creating and managing pools

Navigate to Settings → Execution → Capacity to create, edit, and deactivate pools. You can also manage pools via the CLI:

# List all pools for the current org
rensei capacity pools list

# Create a pool (interactive)
rensei capacity pools create

# Show a pool's config and substrate declaration
rensei capacity pools show <poolId>

For API access, pools are managed at GET/POST /api/org/execution-pools and PATCH/DELETE /api/org/execution-pools/[poolId].

Substrate resolution

The scheduler uses substrate capabilities to match a session's requirements against available pools. Resolution has two layers.

Provider-class defaults

When runtime_provides is null, the platform falls back to PROVIDER_CLASS_DEFAULT_CAPABILITIES[providerId]. These defaults reflect what the base provider class guarantees out of the box:

ProviderRuntime kinds (default)Requirement kinds (default)
localnative, npm, python-pip, http, mcp-server, a2a-protocol, host-binary, workareapersistent-storage, long-running, workarea, host-binary, network-egress, git, full-history-clone, toolchain:go, toolchain:node
dockernative, npm, python-pip, http, mcp-server, a2a-protocol, workareapersistent-storage, long-running, workarea, network-egress, git, full-history-clone, toolchain:go, toolchain:node
kubernetesnative, npm, python-pip, http, mcp-server, a2a-protocol, workareapersistent-storage, long-running, workarea, network-egress, git, full-history-clone, toolchain:go, toolchain:node
e2bnpm, python-pip, http, mcp-server, a2a-protocollong-running, network-egress, git, full-history-clone
daytonanpm, python-pip, http, mcp-server, a2a-protocollong-running, network-egress, git, full-history-clone
modalnpm, python-pip, http, mcp-server, a2a-protocollong-running, network-egress, git, full-history-clone
vercelnpm, http, mcp-server, a2a-protocolnetwork-egress, git, full-history-clone, toolchain:node

Operator overrides via runtime_provides

Setting runtime_provides on a pool replaces the class default entirely. Use this when the pool's actual image or template provides more (or fewer) capabilities than the class default:

{
  "runtimeKinds": ["npm", "python-pip", "http", "mcp-server", "a2a-protocol"],
  "requirementKinds": [
    "long-running",
    "network-egress",
    "git",
    "full-history-clone",
    "toolchain:go",
    "toolchain:node"
  ]
}

The schema for runtime_provides is SubstrateCapabilityDeclaration:

interface SubstrateCapabilityDeclaration {
  runtimeKinds: RuntimeKind[]
  requirementKinds: SubstrateRequirementKind[]
}

runtime_provides is a full replacement, not a merge. If you set it, list every capability the pool provides - omitting a kind removes it from the pool's advertised surface even if the class default would include it.

When to use an override

ScenarioAction
E2B pool with a custom template that bakes Go and Node toolchainsAdd toolchain:go and toolchain:node to requirementKinds
Kubernetes pool on GPU nodesAdd gpu to requirementKinds
Daytona pool with a template that bakes NodeAdd toolchain:node to requirementKinds
Modal pool for Go workloadsAdd toolchain:go to requirementKinds once your Modal image bakes the Go toolchain

Auth-mode pool pinning

Sessions using host-session or local auth modes are pinned to providerId='local' pools exclusively. If no active local pool exists for the project, dispatch fails at the profile-validation step with a clear error.

This is enforced by authModeRequiresLocalCapacity('host-session' | 'local') in src/lib/providers/sandbox/providers.ts and validated at dispatch time. Cloud provider pools (docker, kubernetes, e2b, etc.) will never receive these session types regardless of how they are configured.

Pool configuration per provider

Each provider reads specific keys from the pool's config JSONB. Any unrecognised key is silently ignored.

Docker pool config

{
  "dockerHost": "tcp://192.168.1.10:2375",
  "image": "ghcr.io/renseiai/donmai-worker:latest",
  "memoryMB": 2048,
  "cpu": "1.0"
}

dockerHost defaults to the DOCKER_HOST environment variable or /var/run/docker.sock. If omitted, the platform uses the default Unix socket on the host running the platform service.

Kubernetes pool config

{
  "kubeconfig": "apiVersion: v1\nkind: Config\n...",
  "kubeconfigPath": "/etc/rensei/kubeconfig.yaml",
  "namespace": "rensei-workers",
  "image": "ghcr.io/renseiai/donmai-worker:latest",
  "serviceAccountName": "rensei-worker-sa",
  "memoryMB": 2048,
  "cpu": "1.0"
}

Provide either kubeconfig (inline YAML string) or kubeconfigPath (file path on the platform host). If neither is set, the provider calls KubeConfig.loadFromDefault(), which handles in-cluster ServiceAccount and ~/.kube/config.

Default namespace: rensei-workers. Create this namespace before activating a Kubernetes pool.

Daytona pool config

{
  "daytonaApiUrl": "https://app.daytona.io/api",
  "image": "ghcr.io/renseiai/donmai-worker:latest",
  "diskGB": 20
}

daytonaApiUrl defaults to DAYTONA_API_URL environment variable, then https://app.daytona.io/api.

E2B pool config

{
  "templateId": "my-donmai-worker-template",
  "launchRunnerInline": false
}

templateId is the E2B template ID of your custom donmai worker template. The bare base template does not contain the donmai binary and cannot host sessions. Set launchRunnerInline: true only for templates whose start command cannot be customised - this uses execCommand to launch donmai agent run after provision.

{
  "image": "ghcr.io/renseiai/donmai-worker:latest",
  "gpu": "a10g",
  "entrypoint": ["donmai", "agent", "run"]
}

gpu accepts any Modal GPU type string (e.g. a10g, a100, h100). Omit it for CPU-only sessions.

Vercel Sandbox pool config

{
  "vercelScope": "my-team-slug",
  "runtime": "node24",
  "networkPolicy": "allow-all",
  "snapshotId": "snp_xxxxxxxx"
}

vercelScope is your Vercel team slug. Required if your Vercel account belongs to multiple teams. snapshotId lets you warm-start sandboxes from a pre-built filesystem snapshot (p75 restore under 1 second per Vercel SLA).

Code survival scan and substrate requirements

The code survival feature (analytics/factory/code-survival) runs static analysis batches that require specific substrate capabilities. Pools for code survival must declare:

RequirementWhy
gitRunning git client in the sandbox
full-history-cloneDeep clone to reach arbitrary merge SHAs (not --depth 1)
toolchain:goGo/callgraph reachability analysis
toolchain:nodets-morph TypeScript/JavaScript reachability analysis

local, docker, and kubernetes satisfy all four by class default. For e2b, daytona, and modal, the operator must bake the toolchains into the pool template and add them to runtime_provides. For vercel, toolchain:go is not available - Go repositories degrade to survival-plus-TS-only analysis on Vercel Sandbox pools.

  • Add a Provider - SandboxProvider interface and registration
  • Local - daemon workers, local pool setup
  • Docker - Docker pool configuration
  • Kubernetes - Kubernetes pool configuration
  • E2B - E2B template requirements
  • Daytona - Daytona workspace configuration
  • Modal - Modal GPU pool configuration
  • Vercel Sandbox - Vercel team scope and runtime

On this page