Agent contract
Everything your agent can rely on at evaluation time, and every constraint it must respect.
Runtime
- Node.js 22, running
node index.jsfrom your archive. - Your directory is mounted read-only at
/agent. - mineflayer (
^4.20.0) and mineflayer-pathfinder (^2.4.5) are pre-installed and resolvable — you do not (and cannot) runnpm install.require('vec3')also works; it ships with mineflayer. - The target server is PaperMC 1.21.11, survival mode, offline-mode, no spawn protection.
The runtime image bakes the dependency set, and your code is read-only with no network — so only the packages above resolve. Design your agent around them.
Environment
Your agent is given these environment variables:
| Variable | Meaning |
|---|---|
NPABENCH_HOST | Minecraft server host to connect to |
NPABENCH_PORT | Minecraft server port |
NPABENCH_AGENT_USERNAME | Username your agent must join with |
NPABENCH_AGENT_PROMPT | The mission prompt for this run |
NPABENCH_TIMEOUT_SECONDS | Wall-clock budget for the run |
LLM access (optional)
Your agent has no internet access, so it can't reach an LLM provider directly. Instead the validator runs a small proxy inside its own network and gives your agent an address and a temporary token for it — send your LLM requests there.
The validator's real provider accounts stay locked inside that proxy, so your agent never sees a real API key and can't spend past the budget set for your run.
| Variable | What it holds |
|---|---|
OPENROUTER_BASE_URL | the proxy's address, inside the validator's network |
OPENROUTER_API_KEY | a temporary token for your run — not a real provider key |
Behind the proxy, the validator uses its own OpenRouter and Chutes accounts to reach the actual models — you can use either.
Which models you can use
Only models on a pinned allowlist work; anything else returns 403 model_not_allowed. Each model
is listed with its id on both providers, and the id you send decides which provider serves
the request:
| Model | OpenRouter id | Chutes id |
|---|---|---|
| DeepSeek V3 (0324) | deepseek/deepseek-chat-v3-0324 | deepseek-ai/DeepSeek-V3-0324 |
| DeepSeek R1 | deepseek/deepseek-r1 | deepseek-ai/DeepSeek-R1 |
| Qwen3 32B | qwen/qwen3-32b | Qwen/Qwen3-32B |
| GPT-OSS 120B | openai/gpt-oss-120b | openai/gpt-oss-120b |
Spend is metered at that provider's price, and the two differ — Chutes is cheaper for most of these. Because each task has a fixed USD cap, choosing the cheaper id buys you more calls.
The allowlist is pinned in the subnet repo (docker/proxy/model_pairs.json) so every validator
enforces the same set — check there for the current list.
Other notes:
- Each task has a hard USD spend cap (small by default) — budget your calls.
- Streaming is not supported; only
/chat/completionsand/responsesare proxied.
Sandbox constraints
- No internet. The only reachable services are the Minecraft server and the LLM proxy.
- Read-only filesystem except
/tmp(64 MB). - 1 GB memory, 256-process limit, all Linux capabilities dropped.
- Wall-clock budget = the mission's duration (600 s for the current missions).
Movement limits (anti-cheat)
A movement monitor watches your bot's motion. Exceeding either cap zeros your score
(status: movement_violation):
| Motion | Cap |
|---|---|
| Horizontal speed | 9.0 blocks/s |
| Upward speed | 6.0 blocks/s |
Move like a legitimate survival player — walking, sprinting, jumping, and pathfinder navigation are fine; teleport-like motion is not.
Packaging rules
Enforced when you submit:
.tar.gz, ≤ 1,000,000 bytes.package.jsonandindex.jsat the archive root.- No absolute paths,
.., symlinks, hardlinks, or device entries. - Submissions are scanned for cheats; a hit bans the hotkey.
- A hotkey may be used at most 3 times; each round accepts up to 40 entries.