Reference
Scope. The interfaces that exist today are the command-line tools, the conductor's action grammar, the on-chain record formats and the published reveal — all documented below and all runnable from the repository. The HTTP API is design-stage and is described only in Using the Gateway.
Command-line tools
All five ship as console scripts of the thirtyspokes package (uv pip install -e ".[dev]").
thirtyspokes-miner — the miner's steps
thirtyspokes-miner --netuid N [--network finney] --wallet NAME [--hotkey NAME] <command>
hotkey verify the local hotkey is ed25519 and readable BEFORE paying to register it
identity the registration facts to send the owner; reads only the chain
check --model DIR --reference DIR
the validator's admission gate on a local tree
register-key [--key-file FILE] --cap-usd X [--mailbox-url URL] [--generation K] [--key-credential]
seal your own OpenRouter key to the owner and put it beside the
submission — your arm runs on it (§4); re-run to rotate
submit --model DIR --reference DIR [--mailbox-url URL] [--generation K]
check, upload, commit — SPENDS the hotkey's one shot
submit refuses a sr25519 hotkey by name (the envelope is sealed to an ed25519 key), runs the admission gate before opening the mailbox or uploading a byte, uploads against a credential scoped to the miner's own prefix, and commits the ready signal last. --generation opens a later credential after a rotation. The owner's mailbox key is pinned in the tools (config.OWNER_MAILBOX_KEY), so there is nothing to obtain and no flag to pass; --owner-key HEX remains as an override for a rehearsal against a different owner, and an envelope signed by anything else is refused.
thirtyspokes-dev — the local dev kit
thirtyspokes-dev [--model-tree DIR --reference DIR] [--conductor module:attr]
[--world module:attr] [--budget-usd 1.0] [--concurrency 16] [--nonce dev]
Calls the validator's own admit, scaffold and arm scorer. Reports the parse-failure rate and the endings breakdown before the score, then the decisions themselves. Touches no bucket, chain or network. --concurrency 1 to read one episode's trace at a time.
thirtyspokes-sim — one offline window
thirtyspokes-sim [--root DIR]
The whole mechanism against the archetype cast, nothing re-expressed. The suite pins the order the cast must come out in.
thirtyspokes-owner — credentials, balances, the schedule
thirtyspokes-owner --state DIR <command>
issue --hotkey SS58 --netuid N --wallet NAME [--owner-hotkey NAME] --r2-endpoint URL
--r2-bucket NAME --r2-private-model-bucket NAME [--ttl-seconds 86400] [--key-only]
mint and publish a credential sealed to one hotkey
credit --hotkey SS58|owner --usd X [--ref TEXT]
append a credit: the owner account, or a grant to a hotkey on top
of its own key (picked up at the next window)
balances every balance and cap the gateway would run a window against
status who holds credentials, and which must now be revoked
key the owner public key the tools pin; printed to check it
commit-schedule --netuid N --wallet NAME [--owner-hotkey NAME] --world module:attr
--windows N --per-benchmark N --minimum N [--replace-governance-record]
publish the chained-manifest root for the whole schedule
--state must be the validator daemon's own --state: the one-shot ledger is <state>/mailbox.json, and two ledgers would be two one-shots. commit-schedule refuses to overwrite a slot holding anything but a schedule root unless --replace-governance-record says the record there is a retired mechanism's.
thirtyspokes-validator — the daemon
thirtyspokes-validator --state DIR --netuid N [--network finney] --wallet NAME [--hotkey NAME]
--genesis-block B --window-blocks N --windows N --immunity-blocks N
--world module:attr --reference-tree DIR
--serve-url URL | --serve-host HOST --serve-cards 0:8002,1:8003 --serve-trees DIR
--sandbox-host ENDPOINT [--grade-dir DIR]
--r2-endpoint URL --r2-bucket NAME
--r2-private-model-bucket NAME --r2-public-model-bucket NAME --public-model-base-url URL
--per-benchmark N --minimum N [--king-zero-uid N] [--poll-seconds 60] [--check]
Every seam is a required argument or a required environment variable (OPENROUTER_API_KEY, R2_ACCESS_KEY_ID, R2_SECRET_ACCESS_KEY); there is no offline default anywhere in it. --check runs the launch gates against the chain — rate limit, immunity period, the docker daemon behind --sandbox-host — and exits without opening a window or spending a cent.
The conductor's action grammar
One action per step, the last line of the reply:
REASON <free text> optional; capped at 512 tokens; never leaves the conductor
DELEGATE <model_id> the scaffold sends the ORIGINAL task to this model
RETRY <model_id> the same, after observing an outcome
STOP submit the best result so far
MAX_STEPS = 12, MAX_CONDUCTOR_TOKENS = 576. A model_id outside the window's catalog snapshot is a parse failure; three consecutive parse failures force STOP.
On-chain records
| record | format | slot |
|---|---|---|
| schedule root | schedule:v1:<64 hex> |
the owner hotkey's commitment |
| ready signal | r2ready:v1:<86 base64url> — the registration id and the manifest SHA-256, two 32-byte digests packed into one slot |
the miner hotkey's commitment |
| weights | set_weights by uid, resolved from hotkeys at write time |
the owner hotkey |
The registration id is derived from (netuid, uid, hotkey, registration block); the upload prefix is submissions/<registration id>/, and the mailbox key mailbox/v1/<registration id>/<generation, zero-padded to 20>.bin.
The reveal
Published once per window at v3/reveal/<window>.json as { "record": …, "sig": … }, the signature being the owner hotkey's over the canonical record. Fields of the record:
| field | meaning |
|---|---|
v, window, nonce, benchmarks, n_tasks |
the window and its slice |
freshness |
how much of the slice's category mix recurred from earlier windows |
power |
king_zero, contrast, higher, spread, lcb, floor, n_tasks, separates, by_benchmark |
graders_failed |
tasks excluded from every arm because the grader or sandbox failed |
king_hotkey, king |
the reigning hotkey ("" while King₀ reigns) and its arm: quality, final, per_benchmark[{benchmark, n_tasks, quality, spend, final}], excluded |
outcomes[] |
per challenger: hotkey, commit_block, status, detail, shot_spent, won, exhausted, arm, verdict{delta, lcb, eps, loo_min, loo_dropped, median, sign_wins, sign_p, n_tasks, by_benchmark, loo} |
crowned, pensioners |
who took the crown this window, if anyone, and the lineage |
weights, metagraph |
uid → share as set, uid → hotkey as resolved |
metering[] |
per arm: payer, scoreable, reason, metered_usd, recorded_usd, calls, unfunded_calls, exhausted, futile, resumed |
traces |
the full decision traces of the king's and reference arms — per episode, per step: action, model, cost, observations, the rendered-state digest |
The dashboard renders everything but the traces.
Environment variables the world reads
V3_EXCHANGE (the λ table, which also pins the worker pool), V3_KING0 (the best fixed policy by name), V3_BENCHMARKS (default livecodebench,hle), V3_TASKS_PER_BENCHMARK, V3_SEED, OPENROUTER_API_KEY; on the validator, V3_DOCKER_HOST and V3_GRADE_DIR are written from --sandbox-host and --grade-dir.