BASIS
Documentation

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.

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.

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.

bash
# 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"]
  }'
Request body fields
  • 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.

bash
# 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"}'

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.

Worker 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.
bash
# 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.

bash
# 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)

live

Run 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)

soon

Serving 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.

text
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.

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.

Reward settlement — derived from configuration
  • Reward distributor

    Pending deployment / configuration

    pending
  • Worker rewards

    Dry-run — rewardSettlementEnabled() is false until configured

    Dry-run

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.