Join our community of builders on Discord!

Dispatcher-free Mode

Lightchain AI is moving job assignment from a central dispatcher service to the chain itself. In dispatcher-free mode a worker watches SessionManager for session requests it is eligible for, claims one with a single transaction (sortition — a weighted random draw among eligible workers), and then serves that session's jobs from JobRegistry exactly as before. No service picks the worker; the contract does.
CodeTEXT
Two things hold in every mode: the encrypted result settles on-chain as a blob (that is the authoritative response), and live token streaming to the consumer is best-effort.

Where it is live

NetworkAssignment todayWhat a worker should run
Testnet (8200)Dispatcher-free. AIConfig.getSortitionEnabled() returns true, and the testnet worker-gateway no longer delivers dispatcher jobs.The external profile below — the flow in Run a Worker on Testnet.
Mainnet (9200)Dispatcher-routed. getSortitionEnabled() returns false.The gateway profile in Run a Worker on Mainnet today. The switch is planned for the week of 2026-09-14. The mainnet image already supports the external profile, and a gateway that accepts it runs at worker-gateway-v2.mainnet.lightchain.ai; the operators channel announces when to move — see Prepare for dispatcher-free mode.
Check either network yourself:
CodeBASH

Run profiles

One image, three profiles, selected by two environment variables:
ProfileSORTITION_ENABLEDWORKER_GATEWAY_URLWho assigns jobsRedis
External — for independent operatorstruesetThe chain: the worker self-claimsNot needed. Responses, heartbeat and drain go through the gateway
Gateway (legacy)unsetsetThe dispatcher, delivered over the gateway WebSocketNot needed
Direct — Lightchain-operated nodes onlyeitherunsetDispatcher via Redis/Asynq, or self-claimRequired
SORTITION_ENABLED=true also requires SESSION_MANAGER_ADDRESS; the worker refuses to start without it. When both SORTITION_ENABLED and WORKER_GATEWAY_URL are set, the startup log carries the line external worker profile: sortition assignment with gateway egress (responses, heartbeat, drain via worker-gateway).
Run the external profile only against a gateway that accepts it: worker-gateway.testnet.lightchain.ai or worker-gateway-v2.mainnet.lightchain.ai. Against worker-gateway.mainnet.lightchain.ai (the current mainnet gateway) the worker would still claim and settle jobs on-chain, but its streamed responses would be rejected, so users would see no answer.

Environment reference

Everything below is read by the sidecar; the CLI reads the chain and identity variables too.
VariableDefaultPurpose
SORTITION_ENABLEDfalseWatch SessionManager and self-claim eligible sessions instead of waiting for the dispatcher.
SESSION_MANAGER_ADDRESSRequired when sortition is on. Resolve it with getSessionManagerAddress() above.
SORTITION_STATE_DIRdata/sortition-stateBlock cursors the watchers resume from. Put it on a mounted volume (/data/sortition-state); with an empty directory a restarted worker rescans the last 2,000 blocks of session history.
SORTITION_POLL_INTERVAL4sHow often the watchers poll the chain.
WORKER_GATEWAY_URLGateway used for response streaming, heartbeat and drain.
MAX_CONCURRENT_JOBS2Jobs served at once; the watcher stops claiming while the worker is at capacity.
RELEASE_STATE_PATH./release_state.jsonLedger of the release scheduler that settles your earnings. Set /data/release_state.json so it survives docker rm.
SHUTDOWN_TIMEOUT30sHow long in-flight jobs get to finish after SIGTERM.
SEARCH_ENABLED, TAVILY_API_KEY, …See Web search.
Chain, identity, model and inference variables (CHAIN_ID, RPC_URL, the *_ADDRESS set, WORKER_KEYSTORE_*, ENCRYPTION_KEYSTORE_PATH, SUPPORTED_MODELS, OLLAMA_URL, BEACON_API_URL, BLOB_MODE) are unchanged from the install guides.

Verify it is claiming

A healthy external-profile start:
CodeTEXT
There is no "job received" line until a session is won — a quiet log is normal while other workers win the draws. When your worker wins you see claimed session request, then the usual stage 1: broadcasting ack txjob completed sequence for each job in that session:
CodeBASH
lightchain-worker preflight (shown in the install guides) checks everything a claim depends on — registration, stake against the live minimum, each model's whitelist / enabled / added state, gateway login, Ollama tags — and exits 1 on any failure. Run it first whenever a registered worker never claims. Workers can augment a prompt with a live web search when the user turns on Web search in the chat. The worker runs one Tavily query with the prompt, folds the top results into the prompt it sends to the model, and publishes the sources after the answer so the chat renders them beneath it. Search is fail-open: on any error or timeout the job proceeds with the original prompt and no sources. Enable it with your own Tavily API key:
CodeBASH
TAVILY_API_KEY is required when SEARCH_ENABLED=true; the worker refuses to start without it. What the flag changes on the network side:
  • The worker advertises the search capability in its heartbeat, and in dispatcher-free mode declares it on-chain at startup (WorkerRegistry.setCapabilities, one transaction from the worker key, sent only when the mask changes). Sessions that require search are claimable only by workers whose mask includes it; the worker skips requests it cannot satisfy.
  • Capabilities are an owner-managed namespace: a worker can only declare names the network has registered (WorkerRegistry.getCapabilityCount()). Both testnet and mainnet have search registered (mainnet since 2026-09-13). A worker started before its network registered a capability logs capability not registered on-chain; skipping declaration and declares it on its next start.
  • Both published images (registry.lightchain.ai/testnet/worker:latest and mainnet/worker:latest, build f24e37e) support web search; a mainnet image pulled before 2026-09-13 does not.

Stopping a dispatcher-free worker

lightchain-worker drain sets a marker that the dispatcher honours. In dispatcher-free mode nothing consults it before a claim, so a running worker keeps claiming sessions until the process stops. To take a worker out of rotation:
  1. Stop it with SIGTERM and a grace period longer than SHUTDOWN_TIMEOUT:
    CodeBASH
    On SIGTERM the worker sets the drain marker through the gateway, stops both watchers, gives in-flight jobs up to SHUTDOWN_TIMEOUT (default 30 s) to finish, then exits. Docker's default 10 s grace would kill it mid-job.
  2. Jobs submitted later in sessions you already claimed still target your worker. While it is offline they time out, and every timeout is recorded as an offence even while slash rates are 0 — see Slashing & Rehabilitation.
  3. Continue with the release and deregister steps in Drain & Graceful Exit; they are unchanged.