Prime Intellect's verifiers, on plimsoll

Prime's own task ran unchanged on plimsoll, and every call left a record you can recheck

verifiers (EXTERNAL · source repo ↗) is Prime Intellect's Python library for the environments AI models are trained and tested in. Its runtime is the place a task's commands run and its files live. plimsoll's runtime plugin makes that place a plimsoll session (INTERNAL · glossary →), one sandbox (INTERNAL · glossary →) kept open for the whole attempt, so every command runs behind plimsoll's walls and comes back with a run record (INTERNAL · glossary →), plimsoll's statement of what was sent, what came back and where it ran. On this page Prime's own task uuid_ctf, a puzzle solved with shell commands, ran through it unchanged. The model in these runs is a script, not an AI, as the box below the picture explains.

How a verifiers attempt runs on plimsoll On the evaluator, vf-eval runs the bash harness loop and a scripted model. Each tool call goes to plimsolld, which runs it in a session sandbox under runc or gVisor and answers with the output and a run record. Every record is appended to a log on the evaluator that is rechecked afterwards. The evaluator the machine running verifiers vf-eval verifiers' command, task, grader plimsoll-bash verifiers' own bash loop scripted model fixed moves, not an AI one call output + run record plimsolld the plimsoll server session sandbox runc or gVisor, no network bash -c "…" /work: task files records.jsonl a line per call rechecked with only the file
The loop that talks to the model stays on the evaluator. Only the commands go into the sandbox, one call at a time.
The “model” on this page is a script, not an AI. A small server on the evaluator, the machine running verifiers, answers each of verifiers' model requests from a fixed list of moves (the server (EXTERNAL · source repo ↗), the moves (EXTERNAL · source repo ↗)): it reads the last tool result and makes the next planned call. That keeps the run free and repeatable while it drives verifiers' real loop, real model-call plumbing and real runtime calls. So every number here measures the plumbing: verifiers, plimsoll and the task. None of them says anything about how well an AI model would do the task.

The headline numbers. A reward is verifiers' score for one attempt, from 0.0 (failed) to 1.0 (solved). runc (INTERNAL · glossary →) is docker's usual container runtime, and gVisor (INTERNAL · glossary →) is Google's stand-in kernel, which answers the code's requests to the operating system itself: the two walls the sandbox ran behind.

1.0Prime's uuid_ctf on plimsoll, runc
1.0the same under gVisor
0.0a scripted wrong answer: the grader can say no
1.0verifiers' own docker runtime, the baseline
318 of 318records in 8 logs, rechecked by two checkers
283 msa command on plimsoll (runc), against 30 ms on verifiers' docker runtime

Run on 2026-10-29 with verifiers 0.4.1.dev97 (the version the repository's lock pins: verifiers==0.4.1.dev97) and Python 3.12.3, on one development machine.

The 30-second version

1

verifiers' command vf-eval runs a task for a model. Whenever the model wants a command run or a file read (a tool call), verifiers asks its runtime.

2

With plimsoll as the runtime, each of those is one call to plimsolld, the plimsoll server, which runs it in the session's sandbox and answers with the output and a run record.

3

The client checks each record as it arrives and appends it to a log. Later, anyone can recheck the whole log with nothing but the file.

The taskPrime's uuid_ctf, from their own environments repository (EXTERNAL · source repo ↗), unmodified: find a recovery token in a synthetic incident archive with shell commands and write it to /workspace/answer.json.
The harnessIn verifiers, the harness is the agent program: the loop that sends the conversation to the model and carries out its tool calls. Here it is plimsoll-bash, verifiers' own bash harness with its loop on the evaluator (why, below).
The runtimeplimsoll's plugin, plimsoll_client.verifiers_runtime: each command, read and write is one call of one plimsoll session.
The graderThe task's own scoring code, which reads the answer back from the sandbox after the attempt.
The record logA file of one JSON line per call: each record's digests (INTERNAL · glossary →), SHA-256 fingerprints of the request and the result, and the isolation tier (INTERNAL · glossary →) the call ran behind. Never the command text.

What ran

Every configuration below ran fresh, in one go, from one command (at the end of this page). On plimsoll every attempt asked for a floor (INTERNAL · glossary →), the weakest tier it accepts: container under runc and kernel under gVisor. vf-validate is verifiers' own check of an environment, run here on plimsoll-sum, a tiny test environment of plimsoll's: the gold (known correct) answer must pass, and the task left untouched must score 0.0 when graded in a fresh sandbox that received only its output files. A run where a script deliberately writes a wrong answer has to score 0.0 too, or a 1.0 means nothing.

WhatHarnessRuntimeTier of each recordRewardRecordsNote
plimsoll-sum through vf-validate: the gold answer, then the untouched tasknoneplimsoll, runccontainer (21)gold passes, untouched 0.021 in 3 sessionsthe untouched task graded in a fresh sandbox
plimsoll-sum through vf-validate: the gold answer, then the untouched tasknoneplimsoll, gVisor (runsc)kernel (21)gold passes, untouched 0.021 in 3 sessionsthe untouched task graded in a fresh sandbox
uuid_ctf, the solving scriptplimsoll-bashplimsoll, runccontainer (14)1.014 in 1 session
uuid_ctf, a wrong answerplimsoll-bashplimsoll, runccontainer (10)0.010 in 1 sessionthe grader can say no
uuid_ctf, the solving scriptplimsoll-bashplimsoll, gVisor (runsc)kernel (14)1.014 in 1 session
uuid_ctf, verifiers' shipped harnessbash, as verifiers ships itplimsoll, runccontainer (8)no attempt8 in 1 sessionstopped in its own setup: wget: bad address 'astral.sh'
uuid_ctf, the solving scriptbash, as verifiers ships itverifiers' docker runtimenot stated1.0none (this runtime keeps no records)the baseline

One attempt, call by call

The uuid_ctf attempt under runc made 14 calls in one session, each with its own record. Each record names the one before it (the arrows), so a record removed from the middle, or two swapped, breaks the chain. The colors are verifiers' phases of an attempt, read from its own timing.

boot: the runtime startssetup: the task writes its filesagent: the script's tool callsscoring: the grader reads the answer
1rootff53715b
2run5d981738
3rune67121d7
4write192fc596
5run2150f310
6runba14180e
7runbb4ddf29
8run3695e10d
9run306f872d
10run88160f1a
11run4e3e2c4a
12run2f4eec00
13runf97e9bcf
14rune55617df

Each square: the call's number in the session, what kind of call it was (root finds the work directory, run runs a command, write writes a file), and the first characters of the record's own digest. Session fingerprint 6a3cc0377978: verifiers copies it into its trace, the record it saves of the attempt, so the trace and the log point at each other.

The scripted moves, and the record each one left

  1. bash: ls /workspace; cat /workspace/corpus/ops/recovery_index.json
    → corpus (and 51 more lines)
    record 3695e10dbb60
  2. bash: python3 /workspace/corpus/ops/extract_recovery_sources.py
    → "case": "INC-3575", (and 18 more lines)
    record 306f872d2b98
  3. bash
    python3 - <<'PY'
    import hashlib, json, uuid
    r = json.load(open('/workspace/recovered_sources.json'))
    payload = r['domain_separator'].encode('utf-8') + b''.join(uuid.UUID(u).bytes for u in r['source_uuids'])
    derived = str(uuid.UUID(bytes=hashlib.sha256(payload).digest()[:16]))
    answer = {'result_uuid': 'PENDING', 'source_uuids': r['source_uuids'], 'evidence_paths': r['evidence_paths']}
    open('/workspace/answer.json', 'w').write(json.dumps(answer, indent=2) + '\n')
    print(derived)
    PY
    → 078fbbe4-adec-65a0-3629-496c56239d16
    record 88160f1a510a
  4. edit: in /workspace/answer.json, replace "PENDING" with "078fbbe4-adec-65a0-3629-496c56239d16"
    → Edited /workspace/answer.json
    record 4e3e2c4afcd6
  5. bash: cat /workspace/answer.json
    → "result_uuid": "078fbbe4-adec-65a0-3629-496c56239d16", (and 16 more lines)
    record 2f4eec0035bb

The same conversation as verifiers' own harness

Driven by the same script, plimsoll-bash on plimsoll and verifiers' shipped bash harness on verifiers' own docker runtime held the same conversation: 12 of 13 messages identical, character for character (the tool calls' random ids aside), with the same tool definitions. The one that differs:

verifiers itself adds that line to the system prompt when the runtime has no network.

Why plimsoll-bash, and not the shipped harness

verifiers' shipped bash harness, on plimsoll, never reached the task: it stopped in its own setup with wget: bad address 'astral.sh'. Every harness verifiers ships installs itself inside the runtime from the internet and then calls the model from inside it, and a plimsoll sandbox has no network at all. plimsoll-bash runs the same loop on the evaluator instead: verifiers' own chat loop from the shipped bash program, loaded unedited, with each bash or edit call sent to the sandbox as one session call. verifiers' harness contract allows a loop to run outside the runtime as long as every model call goes through verifiers' own endpoint, and this one does. For an environment's author it is one line of configuration, --env.agent.harness.id plimsoll-bash, not a change to the environment.

What each call costs

Each call through verifiers' own runtime API, timed on the evaluator with no model and no harness: 5 fresh runtimes per configuration, 20 commands each (the command is true, which does nothing), then a 1 KiB write and read. Bars are medians; the numbers in brackets are the fastest and slowest.

start (provision)
verifiers' docker runtime678 ms [609 to 769, n=5]
plimsoll, runc806 ms [592 to 867, n=5]
plimsoll, gVisor956 ms [622 to 987, n=5]
run a command (true)
verifiers' docker runtime30 ms [27 to 80, n=100]
plimsoll, runc283 ms [252 to 451, n=100]
plimsoll, gVisor402 ms [366 to 492, n=100]
write 1 KiB
verifiers' docker runtime30 ms [29 to 49, n=5]
plimsoll, runc283 ms [260 to 292, n=5]
plimsoll, gVisor402 ms [393 to 417, n=5]
read 1 KiB
verifiers' docker runtime64 ms [28 to 98, n=5]
plimsoll, runc274 ms [266 to 316, n=5]
plimsoll, gVisor398 ms [370 to 403, n=5]
teardown
verifiers' docker runtime367 ms [366 to 469, n=5]
plimsoll, runc118 ms [112 to 139, n=5]
plimsoll, gVisor125 ms [115 to 162, n=5]

Read it plainly: a plimsoll call is slower than a docker exec. Each one is a full plimsoll project call: the server runs plimsoll's runner in the sandbox, reads the files back and sweeps away anything the command left running, and the client checks the record. The uuid_ctf attempt above made 14 calls, so at these medians plimsoll added about 3.5 s to it under runc (the difference per command times 14, simple arithmetic); a task that runs more commands pays proportionally more. Provisioning a runtime took longer on plimsoll (806 ms under runc, against 678 ms); tearing one down took less time on plimsoll (118 ms under runc, against 367 ms).

Whole attempts, phase by phase (seconds, one attempt each)

Phaseplimsoll, runcplimsoll, gVisorverifiers' docker runtime
boot (the runtime starts)0.720.980.59
setup (the task's files, and the harness's own install)1.402.018.90
agent (the scripted moves)1.712.620.86
scoring (the grader)0.540.770.08
whole attempt4.46.410.4

One attempt per configuration, so these are single readings, not averages. On verifiers' docker runtime the setup phase includes the shipped harness installing itself (its package installer and its program's packages) into each fresh container; that is why the whole attempt can come out longer there even though every single call is faster.

The limits, stated plainly

These come from the plugin's own documentation (linked at the end of this page). This run met two of them head on: the network, in the shipped harness's setup, and the work directory, in uuid_ctf's /workspace.

How much of Terminal-Bench 2 runs today: 0 of 89 tasks

Terminal-Bench 2 is a widely used benchmark of command-line tasks for AI agents, and verifiers can load it. This run read every task's files as data, nothing in them executed, at commit 2fd12b88aafd (EXTERNAL · source repo ↗):

What a task's files sayTasksWhy it matters here
names a prebuilt image of its own (docker_image)89 of 89one image per server
allows the internet (allow_internet = true)89 of 89no network
grading script installs or downloads software (apt-get, pip, npm, curl, wget, uv)89 of 89no network at grading
grading script writes /logs/verifier89 of 89read-only root file system
grading script reads /tests89 of 89read-only root file system
Dockerfile works in /app88 of 89one work directory
names no image of its own and fetches nothing at grading0 of 89the two walls nothing else gets around today

The rules are plain text matches over each task's task.toml, tests/test.sh and environment/Dockerfile, written out in the program (census.go). Running Terminal-Bench needs plimsoll to serve a task's own image and either the network at grading or images with the test tools already inside.

What this proves, and what it doesn't

Proves
  • An outside verifiers task, unmodified, ran its setup, every tool call and its grading in plimsoll sessions, and scored what verifiers' own docker runtime scored (1.0).
  • The grader still says no: the scripted wrong answer scored 0.0.
  • Every call left a run record, and every log rechecks offline: each record's digest recomputed from its fields, each session's chain unbroken, each closed session's call count matching the server's. Two separate checkers agree on every count: the Python client's check_record_log and this program's Go checker.
  • The tier plimsolld reported for every call, each at or above its attempt's floor (the Go checker refuses a log otherwise): container under runc, kernel under gVisor.
Doesn't prove
  • Anything about an AI model. The moves were scripted. A run with a real model is the next step, and it is not on this page.
  • Who wrote the log. A record log is not signed: rechecking shows the records agree with each other and nothing was changed or dropped without it showing, not who produced the file. The Nemotron example (INTERNAL · example page →) signs every call.
  • Conformance. verifiers' runtime conformance suite (tests/unit/test_runtimes.py in their repository, not in the installed package) was not run. Reading it suggests the background-process, task-image and network-policy cases would fail by design; that is a reading, not a result.
  • That the hardware is honest: the tier is the server's configuration, the provider's evidence and its startup checks, not a hardware attestation.
  • That other verifiers environments run on plimsoll. One that names an image of its own is refused, and this run measured only Terminal-Bench 2's (above).

Run it yourself

From a clone of the repository (EXTERNAL · source repo ↗), with docker, gVisor installed as docker's runsc runtime, and Python 3.12:

make docker-images                         # plimsoll's sandbox images
make py-frameworks PY_FRAMEWORKS=verifiers # the hash-locked verifiers environment
go run ./examples/verifiers                # every configuration above, fresh; rewrites this page
go run ./examples/verifiers -verify        # recheck the files beside this page; starts nothing

The program fetches the two outside repositories at their pinned commits and refuses any other: prime-envs at e221a6514f2e, whose task files it also checks by SHA-256 because the task's own scoring code runs on the evaluator (as verifiers runs every task), and Terminal-Bench 2, which it only reads. It spends nothing: no model, no paid sandbox. Everything on this page comes from evidence.json and the record logs beside it:

Recheck one with the Python client alone: check_record_log("records/uuid-gold-runc.jsonl") from plimsoll_client.verifiers_runtime. The runtime plugin, its limits and its configuration: the Python client's guide (EXTERNAL · official docs ↗). verifiers' runtime plugins: verifiers' runtimes guide (EXTERNAL · official docs ↗).