thirty spkesDOCS
HomeDashboardGet an API key

Mine the Subnet

You compete to build the routing/orchestration agent that gets the highest benchmark quality per dollar over an owner-pinned pool of models. Your agent runs inside your own confidential VM; validators verify an attested proof and grade your answers. King = the eligible miner with the highest cost-budgeted quality.

Mine with eyes open. Our own measurements say routing has no quality moat over the best single model on general traffic — see Findings. The mechanism is real and hardware-verified; the economics are not a guaranteed income stream. We would rather you know that than discover it.

1. What you build

One thing: a Python source file defining build_agent(weights) -> agent, where agent(prompt, call_model) -> answer. call_model(model, messages, params) is your only channel to the pool — it returns the model's response text and is metered for cost.

# my_router.py — a cost-aware cascade: cheap first, escalate hard prompts
import json

def build_agent(weights):
    cfg = json.loads(weights.decode())          # your routing config / trained params
    cheap, strong = cfg["cheap"], cfg["strong"]

    def agent(prompt, call_model):
        ans = call_model(cheap, [{"role": "user", "content": prompt}], {"max_tokens": 256})
        if len(prompt) > 400 or "prove" in prompt.lower():        # your routing logic
            ans = call_model(strong, [{"role": "user", "content": prompt}], {"max_tokens": 512})
        return ans

    return agent

Your bundle = source.py + weights.bin (opaque bytes — a trained routing model, a config, whatever you want), and it is public on your HuggingFace repo. Everyone can read it.

The competitive surface is wide open: a trained routing model, orchestration (ensemble / verify / decompose / cascade), tool use, efficient prompting — anything that lifts quality or cuts cost.

You write your own training. The subnet ships no trainer; that is your edge. Collect which pool model wins which query at what cost, fit a classifier or policy, serialise it into weights.bin, and publish it alongside your inference source. All public.

The one axis where we have measured real headroom is orchestration, not model choice — different scaffolds win different tasks. See Findings §7.

2. The rules, enforced by the runtime

  • Pinned pool only. You may call only the owner's allow-listed models. Anything else raises UnpinnedModelError and your run fails — no smuggling in a stronger external model.
  • Your answer must come from the pool. Not just ≥ 1 pool call per scored task (no_pool_call) — every scored answer must actually derive from a logged pool response. Answering from your own memorised weights is caught by the default grounding checkungrounded.
  • Zero network egress. Your agent runs in a network namespace with no route off-box. Its only channel is call_model, metered by the trusted parent, which holds the API key. You cannot make an unmetered call.
  • You pay your own inference (your own OpenRouter key). Cost is metered from the real bill.

3. How you're scored

Q_lcb = Σ_b  w_b · lcb_b          # weighted, bootstrap lower confidence bound, bounded [0,1]

Scoring on the lower bound means a lucky run cannot dethrone a king.

King = argmax Q_lcb among eligible miners. Emissions split equally across the king + a chain of up to 4 recent ex-kings (5 slots, 20% each when full), with an ε incumbency margin protecting the king that decays with its artifact age, and an earliest-commit tiebreak for the crown.

You are eligible only if all of these hold — otherwise you earn nothing this epoch:

Gate Default
total_cost ≤ budget 0.50 USD per slice
acc_b ≥ f_min on every benchmark 0.10
≥ 1 metered pool call on every scored task

Cost is a ceiling, not a divisor. Being cheaper is only useful up to the budget; above the quality bar, better still wins.

To take slot 1 you must also clear the dethrone guard: not-worse on every benchmark (within tol = 0.02), confidently dominant on at least one (margin = 0.03), at least min_tasks = 5 samples, and cost within +10 % of the king. You cannot dethrone by trading a regression for a spike.

4. Test locally before you spend a cent on-chain

The dev kit runs the exact validator scoring on your artifact — it calls verify_proof directly, not a reimplementation, so what you see locally is what the validator computes.

uv run orchestra-koth-dev --source my_router.py --weights my_weights.bin
# -> per-benchmark acc/lcb, total_cost, Q_lcb, eligible, n_pool_calls

Iterate here until Q_lcb is high and eligible: true under the budget. Useful flags: --model, --n-per-bench (default 8), --budget (default 0.5).

5. Submit and run

One-time setup

uv pip install -e ".[chain,eval,tee]"    # bittensor + HF + OpenRouter + dcap-qvl
export OPENROUTER_API_KEY=...            # you pay your own inference
huggingface-cli login                    # to publish your public bundle
btcli wallet new_coldkey && btcli wallet new_hotkey
btcli subnet register --netuid 99 --wallet.name miner --subtensor.network finney

Run the miner daemon. It publishes your bundle, commits the salted hash on-chain, and each epoch runs the suite in your TEE and uploads the attested proof plus its trace:

orchestra-koth-miner --netuid 99 --network finney --wallet miner --repo you/koth-miner \
  --source my_router.py --weights my_weights.bin \
  --pool "openai/gpt-4o-mini,anthropic/claude-opus-4.7" \
  --confine

On a TDX guest the daemon automatically uses the real hardware attestation, extends RTMR3 with the runtime measurement at startup, and — with --confine — runs your agent with zero egress. On a non-TDX box it falls back to the Stage-1 mock key, which provides no security.

If the subnet enables the intra-epoch commit window (F7), the daemon commits your proof's hash on-chain right after the epoch opens and must reveal exactly that proof — so don't re-roll after it commits (a swapped proof is commit_mismatch, a late one commit_out_of_window).

6. What gets you disqualified

Everything you submit is public and bound to what actually ran, so cheating is detectable rather than merely discouraged.

Reason What you did
UnpinnedModelError Called a model outside the pool allow-list
no_pool_call Didn't call the pool on some scored task
hardcoded_answers A literal answer table in your public source
ungrounded Answered from your own weights instead of the pool — every scored answer must derive from a logged pool call (the default backstop)
memorization (opt-in probe mode) Aced the public set, collapsed on the secret held-out probe
copy_of:<uid> Behaviourally identical to an earlier-committed artifact
trace_mismatch Your uploaded trace doesn't match the proof binding
artifact_binding_mismatch The attested hashes aren't the bundle you published
epoch_nonce_mismatch Replay, stale proof, or best-of-N
over_budget / below_floor:<b> Cost over the budget, or accuracy under a benchmark floor
bad_platform_quote / unapproved_runtime Forged or unapproved TEE attestation

Compete on genuine routing and orchestration quality, not tricks.

7. What you need

  • A confidential VM — Intel TDX. CPU-only is fine; the pool models are remote, so no GPU. Cheap on Spot. See Confidential VM Setup.
  • An OpenRouter API key (your inference budget).
  • A HuggingFace account (to publish your public bundle).
  • A Bittensor wallet, TAO, and registration on Subnet 99 (mainnet).

See also