Documentation
Guides · Worker
Worker guide
Contribute GPU capacity to the Basis inference network. You register a worker with an EVM reward address, send heartbeats, serve OpenAI-compatible jobs the orchestrator routes to you, and accrue rewards for measured work. This guide is practical: register, run, and understand exactly how rewards are computed — and what is still pending before rewards settle for real.
Overview
A worker is a process that connects to the Basis orchestrator, advertises which models it can serve, and runs inference jobs that are dispatched to it. The orchestrator measures the work — quality, uptime, and latency — and the network computes a reward in planned $BASIS base units from the worker pool that remains after the protocol fee. Rewards accrue to a ledger and are batched for settlement on Base.
You can run a worker today, locally or self-hosted. A hosted orchestrator is pending, so for now you point the worker at an orchestrator you run (default ws://localhost:8787). Reward settlement runs in dry-run until the reward distributor is configured — see Pending before live rewards.
Requirements
An EVM reward address
A valid 0x… Ethereum-format address you control. It is required to register and required to earn — a worker with no valid address accrues 0.
A model backend (or echo)
Ollama running locally for real inference, or the echo runtime for GPU-free local testing. WebGPU in the browser is planned.
An orchestrator to connect to
The runtime/orchestrator process (Socket.io, PORT 8787). Run it yourself for now; a hosted orchestrator is pending.
Node ≥20 and pnpm
The worker is a standalone package in this monorepo (runtime/worker), run locally or self-hosted.
Wallet identity
A worker is identified by its worker_id and paid through its worker_wallet. The wallet must be a valid EVM 0x… address; registration validates it and rejects malformed input. The reward address is the only place rewards can land, so set it to an address you control.
Required to earn
A valid EVM reward address is required to accrue any reward. The placeholder 0x0000000000000000000000000000000000000000 registers but earns nothing. Basis never holds your funds or keys — the address is only a settlement destination.
Linked wallet when auth is required
When authentication is required (BASIS_AUTH_REQUIRED=true), the worker_wallet must be a wallet linked to your account — registering a worker for an unlinked wallet is rejected (403 wallet_not_linked). Accrued rewards then map to that linked wallet and your account. Sign in with Privy and link the worker wallet first.
Register a worker
Register with a POST to /api/workers/register. The body carries the worker id, the EVM reward wallet (required and validated), the runtime, and the models the worker serves.
# Register a contributor GPU worker. A valid EVM reward address is required.
# The placeholder 0x000... below registers, but earns nothing — supply a real
# address you control to accrue rewards.
curl -X POST https://basis.watch/api/workers/register \
-H "Content-Type: application/json" \
-d '{
"worker_id": "worker-example",
"worker_wallet": "0x0000000000000000000000000000000000000000",
"runtime": "ollama",
"models": ["basis-default"]
}'- worker_idStable identifier for this worker. Reused on heartbeat and in lookups.
- worker_walletEVM 0x… reward address. Required and validated. Rewards settle here.
- runtimeOne of "ollama", "webgpu", "vllm", or "external".
- modelsModels served, e.g. ["basis-default"].
To see registered workers and a single worker's state, use GET /api/workers and GET /api/workers/{workerId}.
Heartbeat
Keep the worker marked active by sending a heartbeat on a short interval. The body only needs the worker id.
# Keep the worker marked active. Send this on a short interval.
curl -X POST https://basis.watch/api/workers/heartbeat \
-H "Content-Type: application/json" \
-d '{"worker_id":"worker-example"}'Note
Extra fields such as status, models, or tokens_per_second are accepted on the heartbeat body but are currently ignored. Self-reported throughput is not trusted for accounting — the server measures the work it observes.
Run the worker
The worker is the standalone runtime/worker package. Run it locally or self-hosted (a hosted orchestrator is pending) and point it at an orchestrator you run. It is configured entirely with environment variables.
- BASIS_ORCHESTRATOR_URLOrchestrator websocket URL. Default ws://localhost:8787.
- BASIS_WORKER_WALLETEVM 0x… reward address. REQUIRED — no valid address, no reward.
- BASIS_WORKER_RUNTIMEEither "ollama" or "echo". Default echo.
- BASIS_WORKER_MODELSComma-separated list of models the worker serves.
- OLLAMA_URLLocal Ollama endpoint. Default http://127.0.0.1:11434.
# Run the standalone worker package against the orchestrator. # BASIS_WORKER_WALLET is REQUIRED — a worker with no valid EVM address earns 0. BASIS_ORCHESTRATOR_URL=ws://localhost:8787 \ BASIS_WORKER_WALLET=0xYourEvmRewardAddress \ BASIS_WORKER_RUNTIME=ollama \ BASIS_WORKER_MODELS=basis-default \ OLLAMA_URL=http://127.0.0.1:11434 \ pnpm --filter runtime/worker start
For GPU-free local testing, use the echo runtime — it returns a deterministic response with no model backend, so you can exercise registration, heartbeats, and job flow without a GPU.
# GPU-free local testing: the echo runtime needs no model backend. BASIS_ORCHESTRATOR_URL=ws://localhost:8787 \ BASIS_WORKER_WALLET=0xYourEvmRewardAddress \ BASIS_WORKER_RUNTIME=echo \ pnpm --filter runtime/worker start
The orchestrator is the separate runtime/orchestrator process (Socket.io, PORT 8787). See the operator guide for hosting it.
Supported runtimes
Ollama (native)
liveRun a model locally with Ollama and serve real inference. Set BASIS_WORKER_RUNTIME=ollama and point OLLAMA_URL at your endpoint. Live for local and self-hosted workers today.
WebGPU (browser)
soonServing inference from a browser tab over WebGPU is planned. It is listed as a registration runtime but is not yet a way to run a worker.
The standalone worker package today supports ollama and echo. Registration additionally accepts vllm and external as declared runtimes.
Model availability
The network advertises basis-default as the model id. Declare the models you serve in the models field at registration (and in BASIS_WORKER_MODELS) so the orchestrator only routes jobs your worker can handle. The network's advertised model list is available at GET /api/v1/models; a model reads as available only when an inference backend is configured.
Reward formula
Rewards are computed deterministically from a worker pool — the total charge for a job minus the protocol fee — scaled by measured quality, uptime, and latency (each in basis points, divided by 10000), with penalties subtracted.
workerPool = totalCharge − protocolFee
reward = workerPool
× (quality / 10000) # bps
× (uptime / 10000) # bps
× (latency / 10000) # bps
− penalties
# Failed or rejected jobs earn 0.
# A valid EVM reward address is required to earn anything.
# Server-counted output tokens are authoritative; worker-reported counts are advisory.- —
workerPool = totalCharge − protocolFee
The pool that can be paid out to the worker for a job, after the protocol fee is taken from the total charge.
- —
quality × uptime × latency (bps)
Three measured factors in basis points, each divided by 10000, multiply into the pool.
- —
Failed or rejected jobs earn 0
If a job fails or is rejected, it produces no payable reward.
- —
A valid EVM reward address is required
No valid 0x… address means no reward accrues, regardless of work done.
- —
Server-counted tokens are authoritative
The server's output-token count is what the reward is based on; worker-reported counts are advisory only.
Rewards are denominated in $BASIS
Workers earn $BASIS only — the reward is computed and accrued in $BASIS base units, and settled on Base in $BASIS. Any USD figure shown anywhere is a notional snapshot, informational only: it is a convenience conversion at a point in time, never a guaranteed amount and never what a worker is paid in. $BASIS is planned, not live; until the reward distributor is configured, accrual runs in dry-run.
Quality checks / anti-cheat
Because rewards follow measured work, the network guards against low-effort or fabricated output. These checks protect honest workers from being diluted by gamed metrics.
- live
Coherence checks
Output is screened to reject garbage and degenerate repetition. Incoherent responses do not pass as valid work.
- live
Throughput sanity cap
Implausibly high throughput is capped, so a worker cannot inflate its measured output beyond a sane bound.
- pending
Canary probes
Probing workers with known-answer canary jobs is a documented stub today and planned, not yet enforcing.
Settlement batches
Accrued rewards land in a reward ledger and are settled to Base in batches by a keeper. Settlement is idempotent — a batch hash settles once — and the keeper never signs in the application or hot path. Read the full mechanics on the settlement page. Your accrued rewards for a worker are visible at GET /api/workers/{workerId}/rewards.
Pending before live rewards
Reward settlement runs in dry-run until the reward distributor is configured. The ledger accrues and the keeper computes batch hashes, but nothing settles on-chain until the distributor address is set.
- pending
Reward distributor
Pending deployment / configuration
- Dry-run
Worker rewards
Dry-run — rewardSettlementEnabled() is false until configured
When the distributor is configured, rewardSettlementEnabled() becomes true and the keeper settles real batches. Until then, run a worker to test the full flow — your accrued ledger entries are honest and will be settled once the distributor is live.
Troubleshooting
Registration rejected
The worker_wallet is not a valid EVM 0x… address. Supply a well-formed, checksum-safe address you control.
Worker not receiving jobs
Confirm heartbeats are landing and that the orchestrator is reachable at BASIS_ORCHESTRATOR_URL. Check that the models you declared match what the network advertises.
Accruing zero rewards
Jobs may be failing or rejected (those earn 0), the reward address may be missing or invalid, or settlement is in dry-run until the distributor is configured.
Ollama errors
Verify Ollama is running and OLLAMA_URL points at it. To isolate, switch BASIS_WORKER_RUNTIME=echo and re-test without a model backend.
Counts disagree with the receipt
Server-counted output tokens are authoritative. Worker-reported counts and heartbeat throughput fields are advisory and may be ignored.