> ## Documentation Index
> Fetch the complete documentation index at: https://docs.phyi.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Validator Guide

> Register on netuid 76, stake for a permit, execute the round's agents, score against ground truth, and set graduated weights.

A validator evaluates **all four tracks** every round. It runs every
participating agent against its track's task set inside the validator's **own**
hardened sandbox image, scores each agent against ground truth behind a
validator observed liveness check, posts signed results to the server, and sets
one graduated weight vector spanning all tracks on chain for consensus to
reconcile.

<Frame caption="The validator's evaluation pipeline for one round: screening, sandboxed execution with the liveness check, ground-truth scoring, results posting, threshold and graduated weight setting, and on-chain consensus.">
  <img src="https://mintcdn.com/phylax/5hx8zY_xj0vZeb37/images/figures/validator-pipeline.webp?fit=max&auto=format&n=5hx8zY_xj0vZeb37&q=85&s=f4690c3a92e30cbdc95807585344a014" alt="Validator evaluation pipeline" width="1600" height="876" data-path="images/figures/validator-pipeline.webp" />
</Frame>

## All four tracks, every round

There is no track to choose. Every validator evaluates every track each round
(skills, mcp\_servers, packages, repositories), so the per track emission shares
are enforced inside each validator's own weight vector and no track can go
uncovered. Miners still commit to a single track; validators cover them all.
See [The Four Tracks](/core/tracks).

## Eligibility

Chain eligibility is permissionless. You need both:

* a validator **permit**, granted by stake weight, and
* positive **vtrust**, which proves you are actively setting weights.

In addition, the Phylax backend admits only registered validators: once you are
registered and staked on chain, contact the Phylax team with your validator's
public IP and hotkey to be added to the allowlist. Until then the backend
declines your round polls with a 403 and the validator keeps retrying; it
recovers on its own the moment you are added.

## Requirements

* A Linux host with Docker and `docker compose`. The validator executes untrusted
  miner agents, so the Docker jail is mandatory: agents run only inside it, and
  if the jail is unavailable execution does not proceed.
* `btcli` installed: `pip install bittensor-cli`.
* A Bittensor wallet with enough stake to hold a permit.
* Capacity for a full four track pass per round. Each sandbox run is pinned at
  2 GB memory and 1 CPU, so N agents in parallel need roughly N × 2 GB RAM. The
  floor specification is **16 vCPU / 32 GB RAM / 100 GB disk**. See
  [The Round Model](/system/rounds).
* Outbound access to `ghcr.io` (the public validator, proxy, and sandbox
  images), to `api.phyi.dev` (round scheduling, agent fetch, results), and to
  the chain endpoint `wss://entrypoint-finney.opentensor.ai:443`.
* An accurate system clock (NTP): every request to the backend is signed with a
  timestamp the server verifies, so a drifting clock fails authentication.
* The four labelled corpora ship inside the validator image; nothing to
  download. A validator abstains from any round where a track's corpus is
  missing rather than submit a partial result.

<Note>
  Authorization is layered: the chain grants the validator permit purely by stake
  (the top hotkeys by stake, recomputed every epoch, about 72 minutes), vtrust
  accrues from actually setting weights, and the backend independently verifies
  your request signature, your permit, and that your IP is registered in the
  operator managed allowlist. Registering your IP and hotkey with the Phylax team
  is a required onboarding step. Until both the permit and the registration land,
  the validator logs a single warning per state and keeps retrying; it recovers on
  its own once authorized.
</Note>

## Step 1: Create your wallet

```bash theme={"system"}
btcli wallet create --wallet.name validator --wallet.hotkey default
```

Back up the mnemonics. Fund the coldkey with enough TAO to cover the recycle cost
and the stake you plan to hold:

```bash theme={"system"}
btcli wallet balance --wallet.name validator --network finney
```

On testnet you can instead fund it from the faucet with `--network test`.

## Step 2: Register on netuid 76

Put your hotkey on the metagraph. Phylax is **live on mainnet as netuid 76**
(`finney`). View the subnet at [taostats.io/subnets/76](https://taostats.io/subnets/76).

```bash theme={"system"}
btcli subnet register \
  --netuid 76 \
  --network finney \
  --wallet.name validator \
  --wallet.hotkey default
```

Use `--netuid 486 --network test` for testnet. Verify you landed on the metagraph:

```bash theme={"system"}
btcli subnet metagraph --netuid 76 --network finney
```

## Step 3: Stake for a permit

A validator permit is granted by stake weight. Add stake to your hotkey:

```bash theme={"system"}
btcli stake add --wallet.name validator --wallet.hotkey default --amount <TAO>
```

Confirm your stake and watch for the permit and vtrust to appear once you start
setting weights:

```bash theme={"system"}
btcli wallet overview --wallet.name validator --network finney
```

## Step 4: Install and configure

```bash theme={"system"}
curl -fsSL https://raw.githubusercontent.com/praxi-labs/phylax-subnet/main/scripts/install.sh | bash -s validator
cd ~/phylax/validator
```

Fill in `.env`. The corpus ships with the subnet and weights go on chain; the
validator polls the server for round scheduling and posts results back to it.
Without a server it falls back to block-derived round timing, so it can still run
end to end for local development.

The installer writes a complete validator only `.env`: the backend identity is
pinned, the proxy token is generated, and the docker group id is detected.
There is nothing to fill in (`PHYLAX_VALIDATOR_LABEL` is optional).

```ini theme={"system"}
PHYLAX_NETUID=76
SUBTENSOR_NETWORK=finney
WALLET_NAME=validator
WALLET_HOTKEY=default
BITTENSOR_DIR=~/.bittensor

PHYLAX_SERVER_URL=https://api.phyi.dev
PHYLAX_SERVER_HOTKEY=<pinned by the installer>
PHYLAX_PROXY_ADMIN_TOKEN=<generated by the installer>
DOCKER_GID=<detected by the installer>
PHYLAX_VALIDATOR_LABEL=
```

Every validator evaluates all four tracks every round; there is no track to
choose. The compose file itself sets the sandbox runtime
(`ghcr.io/praxi-labs/phylax-agent`, the hardened image Phylax publishes; every
miner's untrusted code runs inside it, never inside a miner supplied image) and
the inference proxy address (`http://phylax-proxy:8900`, the sandbox's only
egress, so every agent LLM call is metered). Neither is an env choice.

The three values the installer filled, and what they are:

`PHYLAX_SERVER_HOTKEY` pins the backend's on chain identity so your validator refuses an impostor that tries to feed it fake rounds or agents. It is a fixed public value that every validator uses. The installer pins it; verify it anytime:

```bash theme={"system"}
curl -s https://api.phyi.dev/v1/server-identity
```

`PHYLAX_PROXY_ADMIN_TOKEN` is a secret shared only by your own validator and proxy containers. Your validator uses it to read per task inference metering from the proxy. No one issues it; the installer generates it. Regenerate anytime:

```bash theme={"system"}
openssl rand -hex 24
```

`DOCKER_GID` is your host's docker group id. The validator launches sandbox containers by talking to the docker socket, so it must belong to that group. The installer detects it:

```bash theme={"system"}
getent group docker | cut -d: -f3
```

## Step 5: Run

```bash theme={"system"}
docker compose pull && docker compose up -d
docker compose logs -f
```

This starts the validator neuron, the inference proxy, and Watchtower.

### Confirm it's healthy

The logs should show the validator connect and begin polling:

```text theme={"system"}
starting Phylax validator on netuid=76 hotkey=... corpora={'skills': ...} ...
```

After that, per round phase, you see either a `submission` wait while miners are
still submitting, or task execution once the window closes. Quick checks:

* `docker compose ps` shows the validator, proxy, and watchtower all `Up`.
* `btcli wallet overview --wallet.name validator --network finney` confirms your hotkey is on netuid 76 with a validator permit, and shows your vtrust once you set weights.
* `curl -s https://api.phyi.dev/v1/server-identity` returns the same hotkey you put in `PHYLAX_SERVER_HOTKEY`.

If a run fails with `image pull failed`, the sandbox image is unreachable (see the note above) and the validator abstains rather than evaluate outside the jail. A docker socket permission error means a wrong `DOCKER_GID`.

## Staying current

Auto-updates are part of the validator deploy, not an add-on. **Watchtower** runs
by default and watches the validator and proxy containers; when a new image is
published it pulls it and restarts that container in place, one at a time, so every
validator moves to the same build without manual `docker compose pull`. It polls
hourly by default (`WATCHTOWER_POLL_INTERVAL`, in seconds).

The **sandbox image** (`phylax-agent`) updates on its own, separately from
Watchtower: the executor runs `docker pull` on `PHYLAX_SANDBOX_IMAGE` before every
agent run, so with `PHYLAX_SANDBOX_DIGEST` unset it always resolves the latest
build. Pin the digest only when you want a frozen, reproducible sandbox.

<Note>
  The validator host must be able to pull `phylax-validator`, `phylax-proxy`, and
  `phylax-agent` from `ghcr.io`. These are public, so no login is needed — but if a
  run fails with `image pull failed`, the sandbox image is unreachable and no
  evaluation can proceed.
</Note>

## What the validator does each round

The validator polls the server (`/v1/rounds/next`); when a round is due the server
returns its id and the frozen participant set, and the validator draws its tasks
for that round. Without a server, a block-derived fallback keeps local development
running.

<Steps>
  <Step title="Freeze and derive">
    When the round opens, read the participating agents pinned by hash, and draw
    this round's tasks from the frozen pool. The draw is deterministic and
    reproducible.
  </Step>

  <Step title="Screen">
    Reject agents that are malformed, oversized, missing the entrypoint, or
    showing abuse patterns, before they consume evaluation resources.
  </Step>

  <Step title="Execute">
    Run each pinned agent against every task, `r` times, reduced to one verdict
    by repetition consensus, inside your own hardened sandbox image
    (`cap-drop=ALL`, `no-new-privileges`, non-root, internal network), each run
    bounded by the per-task CPU budget and funded from the miner's inference key
    through the metered proxy.
  </Step>

  <Step title="Score">
    Tally each agent's task verdicts against ground truth over the whole task
    set: clamped MCC on the behavioural tracks, F2 on repositories. A
    behavioural run counts only if the validator observed its liveness probe.
    See [Scoring](/core/scoring).
  </Step>

  <Step title="Publish and set weights">
    Post signed per-agent results and attestations to the server
    (`/v1/rounds/results`); it records them for the leaderboard and marketplace but
    never decides the winner. Then apply the quality threshold, assign graduated
    weights to your top-ranked eligible agents, and submit your vector on chain.
  </Step>
</Steps>

A validator that cannot finish all four tracks abstains for the round and sets
no weights, so a slow or stalled validator never ships a partial vector or holds
up the round.

## Consensus and honesty

Every validator evaluates the same frozen agents against the same labels, so a
divergent validator is readily identified. Weight above the stake-weighted median
is clipped, bonds reward alignment with consensus over time, and the task draw is
deterministic and reproducible so a rigged set is detectable by anyone. See [Weights and Consensus](/core/weights-and-consensus).
