This is a self-hosting guide. The hosted product at https://www.orcapods.ai needs none of this: sign in and go.
Why Multiple Runners?
Running multiple runners lets you:- Scale horizontally: more runners means more concurrent sessions
- Specialize by runtime: dedicate runners to specific LLM providers
- Isolate workloads: separate runners for different tenants or use cases (future)
- Improve resilience: conductor routes away from unhealthy runners
How Session Routing Works
Each runner has a hash derived from itsRUNNER_BASE_URL:
sess-<hash>-<8hex>
When any conductor receives a request targeting a session, it extracts the hash,
looks it up in its remote.Pool, and routes directly to the owning runner.
Routing is stateless by session ID, but membership changes are currently held
in each conductor process; horizontally replicated conductors must therefore
reconcile their registries independently.
Basic Two-Runner Setup
Capability-Based Routing
Runners advertise their capabilities. The conductor only routes sessions to runners that support the requested runtime: Set capabilities viaRUNNER_CAPABILITIES (comma-separated):
Sidecar Configuration per Runner
Each runner can have different sidecars for different runtimes:
Per-runtime sidecars (recommended for production):
Checking Topology
TheGET /api/topology endpoint shows all runners, their capabilities, health,
membership state, process footprint, session breakdown, and the sidecar worker
instances observed beneath each runner:
process, sessionsByRuntime, and
sidecars can be null when a runner does not answer its topology probe.
sidecars[].observedInstances is a lower bound on worker replicas, not a
count, and cold means an idle or scaled-to-zero sidecar rather than a
fault. There is currently no dashboard view of this data; use the curl
example above, or GET /api/stats/summary for an aggregate healthy/total
runner count.
Runner Health & Failover
The conductor probes each runner at startup and during reconcile, and records a membership state. An individual runner that is unreachable during startup no longer prevents the conductor from booting when at least one runner answers; it remains visible asunreachable and is excluded from new session routing
until a successful reconcile. A runner that is deliberately draining is also
excluded from new sessions, while sessions it already owns remain routed by
their session ID. Boot still fails when no runner answers at all.
Multi-Host Deployment
When runners run on different hosts,RUNNER_BASE_URL must be a routable URL that all conductors can reach:
Never use
localhost for RUNNER_BASE_URL in multi-host setups. It needs to be a URL that resolves from the conductor’s network.Runner-Specific Tool Configuration
Different runners can have different tools available. For example:- Runner A has
TAVILY_API_KEYset, soweb_searchandweb_extractwork - Runner B does not, so those tools return errors