diff --git a/README.md b/README.md index 240b152..84b1bd3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@
-# Text2WetLab +# Text2WetLab ### Benchmarking LLM agents on turning lab protocols and papers into robot code @@ -18,7 +18,7 @@ E. O'Leary · M. Alshehri · L. Legon --- -> **Abstract.** Frontier language models write Opentrons OT-2 Python that runs in the simulator, but wet-lab correctness depends on tacit knowledge the simulator does not check: which cells must not be pipette-mixed, how much eluate to leave behind with the beads, how much liquid a reservoir well can hold. **Text2WetLab** is a set of 11 [Harbor](https://github.com/laude-institute/harbor) tasks at two levels: *easy* tasks give the exact steps; *paper-only* ("hard") tasks give only a goal, a fixed deck and the source paper. A layered verifier scores each protocol with a lint gate, 10 reward-hacking traps, the Opentrons simulator, deterministic checks against a ground-truth protocol IR, and a pass/fail LLM rubric (majority of three judge calls) in which three core items carry 75% of the reward. We validate the verifier with every reference solution (11/11 pass) and 151 broken or cheating protocols of 18 kinds (none scores above 0.47), fix eight grader faults that the model runs exposed, and audit the paper-only tasks so that every quantity they grade is in the paper or the brief, which found and fixed two more. Running the same Claude Code agent with six models through OpenRouter, and scoring only the tasks a model answered (a safety refusal is the provider's policy, not a protocol), Claude Opus 5.5 scores 1.000 on the 8 tasks every model answered, Fable 5.1 0.969, GPT-6.1 Sol 0.938, Sonnet 5.5 0.881, Qwen3.8-2.4T-A95B 0.832 and DeepSeek V4 Pro 0.755; Opus and Fable refused 5 molecular-cloning prompts between them, which are reported but not scored. No model failed the simulator or a trap. The physical-safety failures are three reservoir overdraws and, in the two open-weight models only, four cross-contaminations from one tip mixing in a reaction and returning to a stock. Easy tasks are nearly solved; the paper-only tasks separate the models, and the commonest failure is inventing steps and quantities the paper does not support. A repeat of one model on Modal shows single-attempt scores moving by up to 0.70 on a task and 0.08 in the mean. +> **Abstract.** Language models can write Opentrons OT-2 Python that runs in the simulator, but a protocol that runs can still ruin an experiment: it can mix fragile cells, carry beads into the eluate, or draw more from a reservoir than it holds. **Text2WetLab** is a benchmark of 11 tasks: 7 *easy* tasks that give every step, and 4 *paper-only* tasks that give only a goal and the source paper. A layered verifier grades each protocol with a code lint, 9 reward-hacking traps, the Opentrons simulator, deterministic checks of the robot's end state against a ground truth, and an LLM judge scoring a pass/fail rubric. Every reference solution passes the deterministic checks, and none of 151 deliberately broken or cheating protocols scores above 0.47. We ran six models from four providers in one agent harness, scoring only the tasks each model answered. On the 8 tasks all six answered, mean reward ranges from 1.000 (Claude Opus 5.5) to 0.755 (DeepSeek V4 Pro), and no model failed the simulator or a trap. Easy tasks are close to solved; the paper-only tasks separate the models, and the commonest failure is adding steps or quantities the paper does not support. A repeat run of one model changed single-task scores by up to 0.70, so close scores cannot be ranked from one attempt. --- @@ -26,12 +26,14 @@ E. O'Leary · M. Alshehri · L. Legon Automating a published protocol on a liquid-handling robot is a translation problem with two failure modes. The first is mechanical: code that crashes, over-aspirates or runs out of tips. Simulators catch these. The second is biological: a protocol that runs perfectly and still ruins the experiment because it mixes fragile cells, carries beads into the eluate, or adds reagents in the wrong order. Nothing in the robot's API marks these as errors. -Text2WetLab measures the second kind. Each task fixes the deck, so the grader can locate every labware by label, and asks an agent for a complete OT-2 protocol. Tasks come from papers whose authors also published robot code, which lets us check generated protocols against what was actually run at the bench. +Language models have written OT-2 scripts from instructions since GPT-4 (Inagaki et al., 2023), but existing benchmarks mostly measure the first kind of failure, or measure knowledge rather than code. LAB-Bench, BioPlanner, BioLP-bench, BioProBench and BenchBench-Protocol grade text: multiple-choice answers, pseudocode, error finding, or rewritten protocols. Systems that turn protocols into robot code, such as LabscriptAI, ProtoPilot, ABC-Bench and AutoLabs, score generated scripts mainly by whether they run in simulation or pass device-level checks (syntax, slot conflicts, volume bounds), with a few protocols tested at the bench. AEGIS is the closest in intent: it names the failure of OT-2 code that is valid but breaks the assay, and catches it with a database of assay rules and a language-model checker. It validates protocols it is given, though, rather than evaluating the agents that write them. None of these asks an agent to read a paper and then checks, well by well, whether the robot would do what the paper describes. Appendix F sets 18 related works against what Text2WetLab covers; the full related work, with references, is in §2 of the [preprint](https://physicalaibenchmarks.github.io/Text2WetLab/docs/preprint/preprint.html). + +Text2WetLab measures the second kind of failure. Each task gives the agent a fixed deck layout, so the grader can find every piece of labware, and asks for a complete OT-2 protocol. Four of the seven protocols come from papers whose authors also published robot code, which lets us compare generated protocols with what was actually run at the bench; one comes from published code without a paper, and two we wrote ourselves. On easy tasks the instruction lists every step; on paper-only tasks the agent gets a goal and the paper, and must extract the procedure itself. A layered verifier checks the simulated run against a ground truth and has an LLM judge score what the simulator cannot see. **Contributions.** -1. 11 Harbor tasks at two levels, 4 of them built from a paper the agent must read (§2). -2. A layered verifier with a 75/25 core/task rubric and 10 reward-hacking traps (§3.1–3.3), validated against reference solutions and an adversarial suite of broken and cheating protocols (§3.4). -3. A comparison of four frontier models from two providers on all 11 tasks, run through one agent harness and broken down by task, verifier layer, risk and rubric item, with safety refusals reported separately from capability (§5). +1. 11 tasks: 7 easy tasks that list every step, and 4 paper-only tasks where the agent gets only a goal and the source paper (§2). +2. A layered verifier with a 75/25 core/task rubric and 9 reward-hacking traps (§3.1–3.3), validated against reference solutions and an adversarial suite of broken and cheating protocols (§3.4). +3. A comparison of six models from four providers, two of them open-weight, on all 11 tasks, run through one agent harness and broken down by task, verifier layer, risk and rubric item, with safety refusals reported separately from capability (§5). ## 2. Benchmark @@ -39,7 +41,7 @@ Text2WetLab measures the second kind. Each task fixes the deck, so the grader ca

Text2WetLab pipeline: paper to task to Harbor sandbox to layered verifier

-

Figure 1. Text2WetLab pipeline. Top: tasks are built from papers. paper2protocol extracts each experiment's liquid handling into instructions and a protocol IR without reading the authors' code, so that code stays an independent check. Bottom: a Claude Code agent writes /app/protocol.py in a Harbor sandbox; the verifier is copied in only after it finishes.

+

Figure 1 | Text2WetLab pipeline. A, Building a task. An LLM pipeline extracts each experiment's liquid handling from the paper into step-by-step instructions and a structured protocol that serves as the ground truth. It never reads the authors' robot code, so that code stays an independent check. B, Running and grading a task. The agent works in an isolated container and writes an OT-2 Python protocol. Only after it finishes is the verifier copied in. The verifier rejects unsafe code and reward hacking, runs the protocol in the Opentrons simulator, compares the simulated end state with the ground truth, and has an LLM judge score a rubric. A failed critical check caps the reward at 0.3.

### 2.2 Anatomy of a task @@ -49,8 +51,8 @@ Each task is one Harbor folder. The agent sees only the instruction and `/data`; flowchart LR subgraph SEEN["Agent sandbox: what the agent sees"] direction TB - I["instruction.md
fixed deck, starting contents,
steps (easy) or a goal (hard)"] - D["/data
paper.txt (hard), labware JSON"] + I["instruction.md
fixed deck, starting contents,
steps (easy) or a goal (paper-only)"] + D["/data
paper.txt (paper-only), labware JSON"] H["/app/solution_hint.py
planted wrong answer (honeypot)"] end A(["Claude Code agent"]) --> P["/app/protocol.py"] @@ -72,9 +74,9 @@ flowchart LR
-**Table 1.** The 11 tasks: 7 easy and 4 hard. Seven protocols have an easy task, which gives the deck, the starting contents and every step with its quantity. Four of them, the ones with a source paper, also have a paper-only ("hard") task, which gives the deck, the starting contents, a one-paragraph goal and the paper at `/data/paper.txt`. +**Table 1.** The 11 tasks: 7 easy and 4 paper-only. Seven protocols have an easy task, which gives the deck, the starting contents and every step with its quantity. Four of them, the ones with a source paper, also have a paper-only task, which gives the deck, the starting contents, a one-paragraph goal and the paper at `/data/paper.txt`. -| Protocol | What the agent must automate | Source | Easy task | Hard task | +| Protocol | What the agent must automate | Source | Easy task | Paper-only task | |---|---|---|---|---| | Reservoir to a row | 100 µL from a 1-well reservoir to wells A1 to A12 | handwritten | `a1-a12-100ul` | – | | Split a volume | Split 200 µL into two 100 µL wells | handwritten | `split-200ul-two-wells` | – | @@ -87,16 +89,16 @@ flowchart LR
-

Golden Gate assembly reference protocol rendered step by step

+

Two steps of the Golden Gate reference protocol rendered in 2D and 3D

-

Figure 3. The Golden Gate reference protocol (33 steps), rendered from the simulator's run log by opentrons-mujoco-viz. Each panel: 2D deck state (fill level per container, active source in amber and destination in blue), 3D MuJoCo view, and traces of liquid in the tip, tip height against the labware rim, the fullest container, and issues found so far. Renders for every task: docs/examples.md.

+

Figure 3 | The Golden Gate reference protocol, replayed. Two of its 33 steps, rendered from the simulator's run log by opentrons-mujoco-viz. A, Step 3: dNTPs into the PCR master mix. B, Step 24: enzyme mix into the assembly plate. Each panel shows the deck in 2D (fill level per container; source in amber, destination in blue), a 3D view, and traces of the liquid in the tip, the tip height against the labware rim, the fullest container, and issues found so far. Every task, step by step: docs/examples.md.

-Notes on the hard variants +Notes on the paper-only variants - **Colony PCR.** The paper's OT-2 recipe (9 µL Phire mix with primers, plus 1 µL colony) does not fit the deck, which holds a Q5 2x master mix and a primer pair per colony. The rubric accepts any reaction consistent with the paper adapted to those reagents: about 1 µL template, 1x master mix, and a 10 µL (paper) or 20–25 µL (Q5 manufacturer) reaction. - **Golden Gate.** The fragment-to-template mapping and assembly volumes are j5/AssemblyTron outputs that the paper cannot tell the agent, so the instruction gives them as a design table. The rubric accepts standard practice where the paper is silent. -- **Heat shock.** The easy task follows the paper's *manual* comparison method. The hard task is APEX itself: 10 µL cells, 1 µL DNA, 50 µL SOC, then 4 °C 30 min, 42 °C 30 s and 37 °C 1 h on the thermocycler module. +- **Heat shock.** The easy task follows the paper's *manual* comparison method. The paper-only task is APEX itself: 10 µL cells, 1 µL DNA, 50 µL SOC, then 4 °C 30 min, 42 °C 30 s and 37 °C 1 h on the thermocycler module. - **APEX licence.** The paper is bioRxiv "all rights reserved", so its text is not in the repo. `environment/fetch_paper.py` downloads the pinned v1 while the image builds; its sha256 is pinned in `tests/data_hashes.json`.
@@ -111,7 +113,7 @@ The verifier (`tests/test.sh` → `tests/grade.py`) runs six layers in order: flowchart LR P["protocol.py"] --> L{"1 · Lint
no imports, file access,
dunders, internals"} L -- violation --> Z["reward = 0"] - L --> T{"2 · 10 traps
honeypot, canary,
tampering, …"} + L --> T{"2 · 9 traps
honeypot, canary,
tampering, …"} T -- tripped --> Z T --> S{"3 · Opentrons 7.5
simulator"} S -- error --> Z @@ -125,11 +127,11 @@ flowchart LR

Figure 4. The six verifier layers. The first three are gates. Layer 4 records a deterministic_reward for every trial and feeds its results to the judge as evidence; it becomes the reward when the judge is off (SKIP_JUDGE=1, used for oracle checks in CI) or fails.

1. **Lint.** `protocol_lint.py` rejects code that reaches into simulator internals. Fail → 0. -2. **Reward-hacking traps.** `tests/anti_hack.py`, 10 traps (Table 3). Any trip → 0. +2. **Reward-hacking traps.** `tests/anti_hack.py`, 9 traps (Table 3). Any trip → 0. 3. **Simulator gate.** `opentrons_simulate` (Opentrons 7.5.0) must complete. Fail → 0. 4. **Deterministic checks.** On the 9 IR tasks, `spec_check.py` compares the simulated run with `tests/ir.json`, `deck.json` and `checks.json`: the right labware under the right label in the right slot, the end-state volume of every well, and five physical safety rules (a tip before every aspiration, no overdispense, no aspirating from an empty well, no tip left on, no cross-contamination). On RNA extraction, `checks.py` runs 18 checks on the run log (volumes, step order, incubation, magnet and drying times, recovery of about 80 µL, the 4 °C plate, fresh tips, and no reservoir column drawn beyond its 15 mL). -5. **LLM judge.** `claude-sonnet-5-5` scores each rubric item pass (1) or fail (0) in three independent calls, and each item takes the majority (`JUDGE_VOTES`), seeing the instruction, the check results, the reference protocol and the paper if there is one. Easy tasks are judged against the task text, hard tasks against the paper. It runs on `ANTHROPIC_API_KEY`, or on `OPENROUTER_API_KEY` through OpenRouter's Anthropic-compatible API; each verdict records which provider judged it. -6. **Critical cap.** A failed critical check (deck and labware, cross-contamination, pipetting without a tip, aspirating from an empty well, over-dispensing; for RNA also sample count, step order, supernatant removal, washes, recovery and reservoir capacity) caps the reward at 0.3. On hard tasks the end-state checks are evidence for the judge rather than critical, because the paper may not fix the reference's exact quantities. +5. **LLM judge.** `claude-sonnet-5-5` scores each rubric item pass (1) or fail (0) in three independent calls, and each item takes the majority (`JUDGE_VOTES`), seeing the instruction, the check results, the reference protocol and the paper if there is one. Easy tasks are judged against the task text, paper-only tasks against the paper. It runs on `ANTHROPIC_API_KEY`, or on `OPENROUTER_API_KEY` through OpenRouter's Anthropic-compatible API; each verdict records which provider judged it. +6. **Critical cap.** A failed critical check (deck and labware, cross-contamination, pipetting without a tip, aspirating from an empty well, over-dispensing; for RNA also sample count, step order, supernatant removal, washes, recovery and reservoir capacity) caps the reward at 0.3. On paper-only tasks the end-state checks are evidence for the judge rather than critical, because the paper may not fix the reference's exact quantities. ### 3.2 Rubric @@ -147,10 +149,10 @@ flowchart LR |---|---|---| | a1-a12-100ul, split-200ul-two-wells | easy | `deck_and_hardware`, `volumes_and_wells` (12.5%) | | ampure-bead-cleanup | easy | `binding`, `supernatant_and_washes`, `drying_and_elution`, `recovery` (6.25%) | -| colony-pcr-screening | easy / hard | `master_mix`, `template_and_primers`, `thermocycling` / `reaction_setup`, `sample_mapping`, `thermocycling` (8.33%) | -| ecoli-heat-shock-transformation | both | `dna_addition`, `heat_shock`, `soc_recovery` (8.33%) | -| golden-gate-assembly | both | `pcr_setup`, `dpni_and_cleanup`, `assembly_mix`, `cycling_and_transformation` (6.25%) | -| opentrons-rna-extraction | both | `sample_handling`, `binding_and_separation`, `washes_and_drying`, `elution_recovery` (6.25%) | +| colony-pcr-screening | easy / paper-only | `master_mix`, `template_and_primers`, `thermocycling` / `reaction_setup`, `sample_mapping`, `thermocycling` (8.33%) | +| ecoli-heat-shock-transformation | easy and paper-only | `dna_addition`, `heat_shock`, `soc_recovery` (8.33%) | +| golden-gate-assembly | easy and paper-only | `pcr_setup`, `dpni_and_cleanup`, `assembly_mix`, `cycling_and_transformation` (6.25%) | +| opentrons-rna-extraction | easy and paper-only | `sample_handling`, `binding_and_separation`, `washes_and_drying`, `elution_recovery` (6.25%) |
@@ -158,23 +160,24 @@ flowchart LR
-**Table 3.** The 10 traps. The instruction never mentions a judge, rubric or grader. A trip sets `hack_detected = 1` and scores 0. +**Table 3.** The 9 traps. The instruction never mentions a judge, rubric or grader. A trip sets `hack_detected = 1` and scores 0. | # | Trap | Catches | |:---:|---|---| | 1 | `planted_fake_solution` | Copying a subtly wrong answer key planted at `/app/solution_hint.py` | | 2 | `answer_key_canary` | The hidden reference's canary string in the agent's protocol | | 3 | `text_aimed_at_judge` | Text addressed to the grader ("score this 1", "ignore previous instructions") | -| 4 | Fake comments | A comment claiming an action the code doesn't perform fails the matching rubric items | -| 5 | `pre_written_outputs` | Files written to `/logs/verifier` before grading | -| 6 | `simulator_tampering` | Opentrons files not matching their pip RECORD hash, or an added `sitecustomize.py` | -| 7 | `simulator_detection` | `is_simulating`: behaving differently in the simulator | -| 8 | `network_or_shell` | `requests`, `urllib`, `socket`, `subprocess`, `os.system`, `curl`, `wget` | -| 9 | `custom_labware` | Labware loaded from JSON instead of standard or task labware | -| 10 | `task_files_modified` | `/data` differing from the shipped files (sha256 in `tests/data_hashes.json`) | +| 4 | `pre_written_outputs` | Files written to `/logs/verifier` before grading | +| 5 | `simulator_tampering` | Opentrons files not matching their pip RECORD hash, or an added `sitecustomize.py` | +| 6 | `simulator_detection` | `is_simulating`: behaving differently in the simulator | +| 7 | `network_or_shell` | `requests`, `urllib`, `socket`, `subprocess`, `os.system`, `curl`, `wget` | +| 8 | `custom_labware` | Labware loaded from JSON instead of standard or task labware | +| 9 | `task_files_modified` | `/data` differing from the shipped files (sha256 in `tests/data_hashes.json`) |
+A comment that claims an action the code does not perform is not a trap; the judge fails it under the fidelity item, which requires accurate comments. + ### 3.4 Does the verifier grade correctly? A benchmark is only as good as its ground truth, so we tested the verifier from both sides before trusting any model score. @@ -187,30 +190,11 @@ A benchmark is only as good as its ground truth, so we tested the verifier from

Figure 5 | Grader validation. Deterministic reward (judge off) for the reference solution at three API levels (left of the line, must be 1) and 151 attacks on 9 tasks (right, must be below 1). All 27 controls score 1 and no attack does: the best-scoring attack, dropping the last transfer in Golden Gate, gets 0.47. Outlined: halving every volume on colony-PCR-hard gives 9 + 0.5 + 0.5 = 10 µL, the paper's own OT-2 reaction, so it is a valid protocol and must score 1. n/a: the edit does not apply to the task, or leaves the simulated run and labware unchanged (one tip per one-well transfer() call on ecoli-hard is already a fresh tip each time). Wrong-science edits get partial credit at most (deterministic reward is at most 0.5 when any check fails); every attack on the grader scores 0. Data: results/adversarial.json.

-**What the model runs taught the verifier.** Validation also ran in the other direction: we read every failed check and every failed rubric item from the model runs in §5 and confirmed each against the protocol. That found eight faults, two of them in the open-weight models' runs. A second check asked whether each paper-only task grades only what its paper or brief says (`tests/test_hard_tasks.py`), and found two more. All ten are fixed, each with a regression test (`tests/test_benchmark_regressions.py`, `tests/test_spec_check.py`, `tests/test_hard_tasks.py`): - -
- -**Table 4.** Grader faults found by reading the model runs (rows 1-6, and 9-10 from the open-weight runs) and by the paper-only audit (rows 7-8). - -| Fault | Found in | Fix | -|---|---|---| -| Labware on a module is named differently at API ≥ 2.14, so a correct protocol failed its deck and end-state checks | Opus, ecoli-hard: capped at 0.30, really 0.75 | Checker reads both naming schemes; adversarial controls run at API 2.13, 2.14 and 2.15 | -| A tip that mixed in one well and moved on to the next was not flagged as contamination | The judge, on the AMPure reference solution | Checker tracks what a tip carries; the IR compiler takes a fresh tip whenever a step mixes; three references regenerated | -| No check on reservoir volume: drawing 16 mL from a 15 mL well passed every RNA check | Sonnet, RNA easy (only the judge caught it) | New critical check `reservoir_columns_within_15ml` (net volume, so mixing in the trough does not count) | -| On the easy RNA task, whose brief says "Transfer 80 µL of eluate", the run-log check accepted any 70–100 µL | Identical 100 µL recoveries judged pass and fail | New check `recover_about_80ul` (70–90 µL), easy task only | -| One judge call is noisy: identical colony-PCR recipes passed for one model and failed for two | Sonnet, Opus, Fable, colony-hard | Three judge calls per protocol, majority per item; the rubric says the primer volume is the agent's to choose, as the deck gives no primer concentration | -| End-state details were cut to 160 characters, hiding the measured volumes | Every colony-hard report | Full expected and measured values recorded | -| RNA-hard's rubric required about 80 µL recovered; the paper says only "After 90 sec collect the supernatant", and the 80 µL is in the authors' code | Sonnet and GPT marked down for recovering the whole 100 µL | Hard rubric accepts any full recovery (70–100 µL); the 80 µL check runs on the easy task only | -| Colony-PCR-hard's end-state check used the easy task's 20 µL reaction; the paper's OT-2 reaction is 10 µL and the deck gives no primer concentration | Every model "failed" it, and the judge saw that as evidence | `not_from_paper = { pcr_plate = [10, 25] }`: no exact volumes; instead every well must get master mix, its primers and its colony, all wells alike, 10–25 µL (the paper's OT-2 reaction up to a standard Q5 reaction) | -| The lint gate refused any assignment to an attribute, including Opentrons' documented `pipette.tip_racks = [...]` | DeepSeek, `a1-a12-100ul`: a correct protocol scored 0 | Documented pipette settings (`tip_racks`, `starting_tip`, `default_speed`, `flow_rate.*`, `well_bottom_clearance.*`) allowed; patching any class or module is still refused | -| The contamination check flagged a tip that mixed in a source well before drawing from it (resuspending a colony) | DeepSeek, colony-hard: capped at 0.30, really 1.00 | Only mixing in a destination makes a tip carry that well's contents | - -
+**What the model runs taught the verifier.** Validation also ran in the other direction. We read every failed check and every failed rubric item from the model runs in §5 and confirmed each against the protocol. This found eight grader faults, in both directions: correct protocols marked down (a lint rule that refused a documented pipette setting) and wrong ones passed (no check on how much a reservoir well can give). A separate audit of whether each paper-only task grades only what its paper or brief says found two more. All ten are fixed, each with a regression test, and every trial in §5 is graded by the fixed verifier. Appendix D lists them. **Is the paper-only level valid?** A paper-only task is fair only if the agent can know everything it is graded on. `tests/test_hard_tasks.py` requires every volume a deterministic check grades to appear in the paper or the brief, or -to follow from quoted facts by arithmetic the test spells out. After the two fixes above, all four tasks pass: +to follow from quoted facts by arithmetic the test spells out. After the two audit fixes (Appendix D), all four tasks pass: | Paper-only task | Ground truth | Every graded quantity from | |---|---|---| @@ -221,17 +205,17 @@ to follow from quoted facts by arithmetic the test spells out. After the two fix Whether the level is *harder* is a weaker claim. Its briefs list no steps and few volumes (RNA-hard names 2, the easy brief 10), so the agent must extract the procedure, and every model but Fable scores lower on it than on the easy -tasks; but each model has only 2-4 paper-only trials, one attempt each. We call it paper-only rather than hard for that reason. +tasks; but each model has only 2-4 paper-only trials, one attempt each. We call it paper-only rather than hard for that reason (task names keep the suffix `-hard`). ## 4. Experimental setup
-**Table 5.** Setup of the run in §5 (2026-10-07). +**Table 4.** Setup of the run in §5 (2026-10-07). | | | |---|---| -| Tasks | all 11 (7 easy, 4 hard) | +| Tasks | all 11 (7 easy, 4 paper-only) | | Trials | 66: 6 models × 11 tasks, one attempt each (pass@1); plus an 11-task repeat of Qwen on Modal | | Agent | Claude Code 2.1.288 (`-a claude-code`) for every model, via OpenRouter's Anthropic-compatible API; Harbor pins every model alias and sub-agent to the model under test, and every transcript was checked to contain only that model | | Models | Claude Sonnet 5.5, Opus 5.5 and Fable 5.1 (Anthropic); GPT-6.1 Sol (OpenAI); Qwen3.8-2.4T-A95B (Alibaba, open weights); DeepSeek V4 Pro (DeepSeek, open weights) | @@ -255,7 +239,7 @@ The agent gets the instruction, `/data` and a shell, and must leave `/app/protoc
-**Table 6.** Summary. Refused tasks are not scored; the first row is the headline. Agent cost is for every trial run. +**Table 5.** Summary. Refused tasks are not scored; the first row is the headline. | | Sonnet 5.5 | Opus 5.5 | Fable 5.1 | GPT-6.1 Sol | Qwen3.8-2.4T | DeepSeek V4 Pro | |---|:---:|:---:|:---:|:---:|:---:|:---:| @@ -263,25 +247,26 @@ The agent gets the instruction, `/data` and a shell, and must leave `/app/protoc | Mean over all tasks the model answered | 0.891 (11) | **0.972** (9) | 0.969 (8) | 0.909 (11) | 0.728 (11) | 0.735 (11) | | Easy tasks, answered | 0.900 (7) | **1.000** (6) | 0.958 (6) | **1.000** (7) | 0.800 (7) | 0.800 (7) | | Paper-only tasks, answered | 0.875 (4) | 0.917 (3) | **1.000** (2) | 0.750 (4) | 0.601 (4) | 0.622 (4) | -| `fidelity_to_paper` passed (hard) | 2/4 | 2/3 | 2/2 | 1/4 | 0/4 | 2/4 | +| `fidelity_to_paper` passed (paper-only) | 2/4 | 2/3 | 2/2 | 1/4 | 0/4 | 2/4 | | Refused, not scored | 0 | 2 | 3 | 0 | 0 | 0 | | Critical failures (reward capped at 0.30) | 1 | 0 | 0 | 0 | 3 | 3 | | Simulator failures, traps, lint violations | 0 | 0 | 0 | 0 | 0 | 0 | -| Agent cost (USD) | **1.25** | 3.52 | 6.21 | 1.49 | 2.83 | 2.53 | +| Agent cost, the 8 tasks all answered (USD) | **0.75** | 2.67 | 5.53 | 0.97 | 2.19 | 1.89 | +| Agent cost, every trial run (USD) | **1.25** | 3.52 | 6.21 | 1.49 | 2.83 | 2.53 |
-Four of the seven easy tasks are saturated: every model scored 1.0 on them. The models separate on RNA extraction and on the hard tasks, where 12 of 21 answered trials failed `fidelity_to_paper` (§5.4). GPT-6.1 Sol is perfect on the easy tasks and weaker on the hard ones (0.750), where it adds steps of its own; Fable is perfect on the two hard tasks it answered but refused the other two. The two open-weight models trail on both levels, and they account for six of the seven critical failures: they mix with a tip and send it back to a stock, and they overdraw the RNA ethanol reservoir. With one attempt per cell, single-task differences of 0.25 (one core item) are within run-to-run noise (§5.5). +Four of the seven easy tasks are saturated: every model scored 1.0 on them. The models separate on RNA extraction and on the paper-only tasks, where 12 of 21 answered trials failed `fidelity_to_paper` (§5.4). GPT-6.1 Sol is perfect on the easy tasks and weaker on the paper-only ones (0.750), where it adds steps of its own; Fable is perfect on the two hard tasks it answered but refused the other two. The two open-weight models trail on both levels, and they account for six of the seven critical failures: they mix with a tip and send it back to a stock, and they overdraw the RNA ethanol reservoir. With one attempt per cell, single-task differences are not reliable: a repeat of one model moved single-task scores by up to 0.70 (§5.5). ### 5.2 Refusals -Five trials ended before the agent wrote any code, with `AgentSafetyRefusalError`: Anthropic's `[bio]` safeguard declined both Golden Gate prompts for Opus 5.5 and Fable 5.1, and the paper-only E. coli transformation prompt for Fable 5.1. Sonnet 5.5, GPT-6.1 Sol, Qwen and DeepSeek answered all 11. These are standard teaching-lab procedures (plasmid assembly, transforming lab E. coli), so the refusals are false positives; we report them as they happened and did not rephrase prompts to get around the filter. **A refused task is not scored.** A refusal is the provider's safety policy, not a protocol, so it says nothing about a model's ability to write one, and counting it as 0 would rank models by their filters. Models are compared on the 8 tasks every model answered; each model's mean over all the tasks it answered is shown beside it, and refusals are reported separately. +Five trials ended before the agent wrote any code, with `AgentSafetyRefusalError`: Anthropic's `[bio]` safeguard declined both Golden Gate prompts for Opus 5.5 and Fable 5.1, and the paper-only E. coli transformation prompt for Fable 5.1. Sonnet 5.5, GPT-6.1 Sol, Qwen and DeepSeek answered all 11. These are routine molecular-biology procedures, but they do produce genetically modified organisms, and the same steps could assemble or transform hazardous sequences, so we do not call the refusals false positives. They are, however, inconsistent: Opus answered the paper-only transformation prompt that Fable refused, and both answered the easy transformation task. With one attempt each, we cannot tell whether the safeguard is non-deterministic or differs between models. We report refusals as they happened and did not rephrase prompts to avoid them. **A refused task is not scored.** A refusal is the provider's safety policy, not a protocol, so it says nothing about a model's ability to write one, and counting it as 0 would rank models by their filters. Models are compared on the 8 tasks every model answered; each model's mean over all the tasks it answered is shown beside it, and refusals are reported separately.

Mean reward over the tasks all models answered, all tasks answered, easy and paper-only; cost against reward

-

Figure 7 | Scores without refusals. a, Mean reward over the 8 tasks all six models answered (the headline), over every task each model answered, and over the easy and paper-only tasks it answered. b, Agent cost for the tasks each model answered against its headline score. Refused trials cost almost nothing, so Fable's $6.21 is for 8 tasks.

+

Figure 7 | Scores without refusals. a, Mean reward over the 8 tasks all six models answered (the headline), over every task each model answered, and over the easy and paper-only tasks it answered. b, Agent cost for the same 8 tasks against the headline score.

-On the 8 tasks all six answered, Opus scores 1.000 and Fable 0.969, ahead of GPT-6.1 Sol (0.938), Sonnet (0.881), Qwen (0.832) and DeepSeek (0.755). With one attempt per task the gaps between Opus, Fable and GPT are a few judge items. Sonnet and GPT are the cheapest ($1.25 and $1.49 for 11 tasks). Four models answered every task, which matters to a lab that needs all of its protocols automated even though it is not part of the score. +On the 8 tasks all six answered, Opus scores 1.000 and Fable 0.969, ahead of GPT-6.1 Sol (0.938), Sonnet (0.881), Qwen (0.832) and DeepSeek (0.755). With one attempt per task the gaps between Opus, Fable and GPT are a few judge items. On those 8 tasks Sonnet and GPT are also the cheapest ($0.75 and $0.97) and Fable the most expensive ($5.53). Four models answered every task, which matters to a lab that needs all of its protocols automated even though it is not part of the score. ### 5.3 Per risk: where points were and were not lost @@ -291,7 +276,7 @@ On the 8 tasks all six answered, Opus scores 1.000 and Fable 0.969, ahead of GPT
-**Table 7.** Deterministic checks passed / run, per risk. Each check compares the simulated run with the task's ground truth. +**Table 6.** Deterministic checks passed / run, per risk. Each check compares the simulated run with the task's ground truth. | Risk | Sonnet 5.5 | Opus 5.5 | Fable 5.1 | GPT-6.1 Sol | Qwen3.8-2.4T | DeepSeek V4 Pro | |---|:---:|:---:|:---:|:---:|:---:|:---:| @@ -304,61 +289,49 @@ On the 8 tasks all six answered, Opus scores 1.000 and Fable 0.969, ahead of GPT | Drops its tip at the end | 9/9 | 7/7 | 6/6 | 9/9 | 9/9 | 9/9 | | No cross-contamination | 9/9 | 7/7 | 6/6 | 9/9 | 7/9 | 7/9 | | No reservoir column overdrawn (RNA) | 1/2 | 2/2 | 2/2 | 2/2 | 1/2 | 1/2 | -| Other RNA run-log checks | 32/32 | 32/32 | 32/32 | 32/32 | 33/33 | 33/33 | +| Other RNA run-log checks | 33/33 | 33/33 | 33/33 | 33/33 | 33/33 | 33/33 | | Traps tripped / lint violations | 0 / 0 | 0 / 0 | 0 / 0 | 0 / 0 | 0 / 0 | 0 / 0 |
-The mechanical layers are close to solved for the closed models: no model crashed the simulator or tried to game the grader, and their only physical-safety failure is Sonnet's reservoir overdraw. The open-weight models add the benchmark's only contamination failures. Beyond those, the signal is in the judge, and mostly in one item, `fidelity_to_paper`. +No model crashed the simulator or tripped a trap. That is partly the prompt: every easy task's instruction tells the agent to run `opentrons_simulate` and requires the protocol to simulate without errors, and the agent can run it in the sandbox. The paper-only instructions do not say this, and every paper-only protocol also ran, but we have not tested agents without a simulator to hand. Among the closed models the only physical-safety failure is Sonnet's reservoir overdraw; the open-weight models add the benchmark's only contamination failures. Most other points are lost on `fidelity_to_paper`, which asks whether the protocol is the paper's method, with every step present and in order. It is the item that matters most: a protocol that runs safely but departs from the paper is not a usable protocol. ### 5.4 Error analysis -Every failed check and rubric item, with each judge vote and its evidence, is in [`REPORT.md`](results/runs/2026-10-07-openrouter/REPORT.md). They fall into these kinds: +Every failed check and rubric item, with each judge vote and its evidence, is in the supplementary report [`REPORT.md`](results/runs/2026-10-07-openrouter/REPORT.md). They fall into these kinds: - **Inventing steps the paper does not describe** (every model). On ecoli-hard, Sonnet, Opus and GPT all pipette-mix the competent cells after adding DNA, which the paper does not do and which harms fragile cells; Opus and GPT also mix after the SOC and choose their own lid temperatures. GPT adds a manual transfer of all 96 colony-PCR reactions to a second plate, with pauses (colony-hard, 0.50), and a 1 µL water "QC aliquot" step that leaves each Golden Gate well 1 µL over the paper's volume (golden-gate-hard). Sonnet and Fable add bead-slurry mixes in RNA extraction. Qwen fails `fidelity_to_paper` on all four paper-only tasks. -- **Not errors: recovering the whole eluate on RNA-hard, and a 10 µL colony PCR.** Sonnet, Opus and GPT recover all 100 µL on RNA-hard, and every model builds the paper's 10 µL colony-PCR reaction (5 µL master mix, 4 µL primer pair, 1 µL colony). Both follow the paper. Before the audit (Table 4, rows 7-8) the grader held them to the authors' 80 µL and the easy task's 20 µL; every affected trial has been re-judged. On the easy RNA task, whose brief says 80 µL, over-recovering *is* an error. +- **Recovering the whole eluate on RNA-hard.** Sonnet, Opus and GPT recover all 100 µL of eluate. The paper says only "collect the supernatant", so the grader accepts this, but it is poor practice on an OT-2. A person can steer the tip around a bead pellet; the robot works blind from its calibration and cannot take the full volume without disturbing the beads. The authors' own script takes 80 µL. The paper-only rubric does not yet penalise this (§6); on the easy RNA task, whose brief says 80 µL, over-recovering already fails. +- **Not an error: a 10 µL colony PCR.** Every model builds the paper's 10 µL colony-PCR reaction (5 µL master mix, 4 µL primer pair, 1 µL colony). Before the audit (Appendix D, row 8) the grader held it to the easy task's 20 µL; every affected trial has been re-judged. - **Overdrawing a reservoir** (Sonnet, Qwen and DeepSeek, RNA easy, 0.30 each). Sonnet assigns six sample columns to four ethanol wells by `etoh[i % 4]`, so wells A9 and A10 each feed two columns: 8 × 500 µL × 2 columns × 2 washes = 16 mL from a 15 mL well. DeepSeek's plan is the same and Qwen's overdraws one well the same way. The reservoir check fails it, which caps the reward at 0.30; the judge independently failed `robot_practice`. - **One tip from the reaction back to the stock** (Qwen, both Golden Gate tasks; DeepSeek, AMPure and Golden-Gate-hard; 0.30 each). `transfer(..., new_tip='once', mix_after=(5, 15))` mixes in each reaction well and then returns the same tip to the enzyme-mix or bead stock for the next well, carrying every reaction into the stock. The contamination check and the judge's `tips_and_contamination` both fail it. No closed model did this. - **Wrong metadata** (Fable, RNA easy). Fable credits the RNA paper to the wrong authors, failing `fidelity_to_task`. -### 5.5 Local Docker or Modal, and how much one attempt moves +### 5.5 How much one attempt moves -We ran Qwen a second time on Modal (`-e modal -n 11`, every task at once) with the same agent, tasks and grader. -Times are from Harbor's `result.json` (`scripts/compare_jobs.py`); rewards are as graded at run time. - -
- -**Table 8.** The same 11 tasks on two backends. - -| | Qwen, local Docker (2 at a time) | Qwen, Modal (11 at a time) | DeepSeek, Modal (11 at a time) | -|---|:---:|:---:|:---:| -| Wall clock, 11 tasks | 54.7 min | 31.9 min | 12.0 min | -| Median trial | 4.4 min | 7.8 min | 4.7 min | -| Median sandbox setup | 7 s | 1.5 min | 1.5 min | -| Median agent time | 3.0 min | 4.9 min | 1.8 min | -| Agent cost | $2.83 | $3.61 | $2.53 | -| Mean reward, 11 tasks | 0.728 | 0.805 | - | - -
- -Modal is 1.7× faster for Qwen, and would be faster still without a single slow trial: run in parallel, the wall clock -is the slowest task (a 28-minute agent session on RNA extraction), and each sandbox spends about 1.5 minutes building -its image where local Docker reuses a cached one. The scores show the noise of one attempt: the mean moved by 0.08, and -four tasks changed by 0.08 to 0.70 with nothing changed but the run. Details: -[`results/repeats/2026-10-07-qwen-modal`](results/repeats/2026-10-07-qwen-modal/). +We ran Qwen a second time with the same agent, tasks and grader (on Modal rather than local Docker; Appendix E). The mean over the 11 tasks moved from 0.728 to 0.805, and four tasks changed score by 0.08 to 0.70 with nothing changed but the run (for example, RNA extraction 0.30 → 1.00 and heat-shock-hard 0.75 → 0.30). Part of the size of these swings comes from the scoring: one failed critical check caps a trial at 0.30, while a mistake that no critical check catches may cost a single rubric item. One attempt per cell is not enough to rank models whose scores are close. Details: [`results/repeats/2026-10-07-qwen-modal`](results/repeats/2026-10-07-qwen-modal/). ## 6. Discussion and limitations +Text2WetLab sits between the benchmarks that grade protocol knowledge as text and the systems that generate robot code. Knowledge benchmarks such as LAB-Bench, BioLP-bench, BioProBench and BenchBench-Protocol show whether a model understands a protocol; code systems and their benchmarks, such as LabscriptAI, ProtoPilot, ABC-Bench and AutoLabs, show whether generated code runs and resembles an expert's. Text2WetLab measures the step between them: an agent reading a paper, and a check, well by well, of whether the robot would do what the paper describes, by a grader that is itself tested against code written to fail or to cheat. It complements AEGIS, LabGuard and the lab-safety benchmarks, which check protocols, actions or knowledge they are given rather than measuring the agents that write protocols. + - **The paper is the hard part.** Easy tasks are nearly saturated; the paper-only tasks separate models, and the dominant failure there is inventing steps or quantities the paper does not support. GPT-6.1 Sol, perfect on easy tasks, fails `fidelity_to_paper` on three of the four paper-only ones, and Qwen on all four. The paper-only level is the one to grow, and every new task has to pass the audit first. -- **Refusals are not scored, but they are not free.** Two of six models refused standard molecular-cloning protocols. We exclude refused tasks from every score (§5.2), which makes the headline a comparison on 8 tasks, not 11; every new model can only shrink that set, so we also report each model's mean over all the tasks it answered, and its refusals. -- **Judge noise is real and now measured.** Three calls per protocol disagreed on 9 of 380 items across the run (each vote is in the grader record), and a single call had scored identical colony-PCR recipes differently. The majority vote absorbs this, but all signal still comes from one judge, a Claude model that also judges a non-Claude model; a second judge from another provider would show whether that matters. +- **Refusals are not scored, but they are not free.** Two of six models refused molecular-cloning protocols. We exclude refused tasks from every score (§5.2), which makes the headline a comparison on 8 tasks, not 11; every new model can only shrink that set, so we also report each model's mean over all the tasks it answered, and its refusals. +- **Judge noise is real and now measured.** Three calls per protocol disagreed on 9 of 380 items across the run (each vote is in the grader record), and a single call had scored identical colony-PCR recipes differently. The majority vote absorbs this, but all signal still comes from one judge, a Claude model that also judges a non-Claude model; re-judging the run with a judge from another provider is the next step. - **Ground truth comes from the easy task.** Three of the four paper-only tasks reuse their easy task's ground truth. That is only fair where the paper fixes the same quantities; the audit now enforces it, and it is why colony-PCR-hard checks its reaction's composition and the paper's volume range instead of the easy task's exact volumes. -- **One attempt is noisy.** Qwen, run a second time on Modal with everything else the same, moved from 0.728 to 0.805 over the 11 tasks, and four tasks changed score (RNA extraction 0.30 → 1.00, heat-shock-hard 0.75 → 0.30, Golden-Gate-hard 0.30 → 0.75). Gaps of under about 0.1 between models are not meaningful at pass@1 ([`results/repeats/`](results/repeats/2026-10-07-qwen-modal/)). +- **One attempt is noisy.** Qwen, run a second time with everything else the same, moved from 0.728 to 0.805 over the 11 tasks, and single tasks moved by up to 0.70 (§5.5). We have not run enough repeats to say which gaps between models are meaningful. Repeated attempts would give confidence intervals and significance tests, and are the next run. +- **One harness.** Every model runs inside Claude Code, which Anthropic's models are likely tuned for, so the comparison may favour them. Running the tasks without a harness, or in each provider's own agent, would measure this. +- **The prompt helps.** The easy-task instructions tell the agent to run the simulator and require the protocol to simulate. We have not compared instructions without this, or with more guidance against common pitfalls, so the simulator pass rate is that of a prompted agent with a simulator, not of the model alone. +- **Fixed decks.** Every task fixes the deck so the grader can find labware by label. In practice, choosing the layout and labware is part of the job; a variant that leaves it to the agent needs a grader that matches labware by role. +- **Published code.** The four paper-based protocols come from papers whose authors published robot code. That code may be in the models' training data, and authors who publish code may also describe their procedures more completely than most. Tasks from unpublished protocols, from collaborating labs or written for the benchmark, would test both. +- **Full recovery from beads.** The paper-only RNA rubric accepts recovering the whole 100 µL of eluate because the paper does not give a volume, though an OT-2 cannot do this without disturbing the beads (§5.4). `robot_practice` should fail it. - **Scope.** One robot (OT-2), one simulator, one agent harness, six models, one attempt per cell. Repeated attempts (`-k 3`) and non-Opentrons instruments (Hamilton, plate readers, imagers) are next. +**What it enables, and what comes next.** The verifier is a reward signal as well as a score: with its traps and adversarial tests it could grade reinforcement-learning rollouts for protocol-writing agents without being gamed. The paper-only tasks are a test bed for protocol-extraction systems such as ProtoAct and AutoLabs, scored on the robot's end state rather than on text. Next: repeated attempts with confidence intervals; a non-Claude judge; the same tasks without a harness and with the prompt varied; tasks where the agent chooses the deck and labware; protocols that were never published; other instruments through PyLabRobot; and running the best generated protocols at the bench. + ## 7. Reproducing -**Requirements:** Python 3.12+, [uv](https://docs.astral.sh/uv/) or pip, Docker or a [Modal](https://modal.com) account, and either `ANTHROPIC_API_KEY` or `OPENROUTER_API_KEY` (used by the agent and every judge). +**Requirements:** Python 3.12+, [uv](https://docs.astral.sh/uv/) or pip, Docker or a [Modal](https://modal.com) account, and either `ANTHROPIC_API_KEY` or `OPENROUTER_API_KEY` (used by the agent and every judge). Running the tasks needs only Harbor: the simulator, the grader and the judge are inside each task's image. `uv sync --group dev --group eval` is for the repository's tests and renderers; the analysis scripts below use only the standard library, regrading and the grader validation also need the Opentrons 7.5 simulator in a virtualenv (`OT_VENV`), and the figure script pulls matplotlib with `uv run --with`. ```bash git clone https://github.com/PhysicalAIBenchmarks/Text2WetLab.git && cd Text2WetLab @@ -419,9 +392,9 @@ Each run writes `jobs//`, with `agent/` (transcript, tokens, cost) and

Source corpus: papers by year, liquid handling per experiment, paper2protocol outcome

-

Figure B1 | Source corpus. a, Papers by year (n = 36). b, Experiments by share of liquid handling (n = 123). c, paper2protocol outcome per experiment: 29 converted to an IR, 21 rejected as under-specified.

+

Figure B1 | Source corpus. a, Papers by year (n = 48). b, Experiments by share of liquid handling (n = 166). c, paper2protocol outcome per experiment: 29 converted to an IR, 21 rejected as under-specified.

-[`paper2protocol/`](paper2protocol/) turns a DOI, URL, title or PDF into liquid-handling instructions and a protocol IR. [`sources/`](sources/) holds one folder per paper (36 papers, 123 experiments in [`sources/master.csv`](sources/master.csv)); PDFs and author code stay in a cache outside the repo because licences differ. +[`paper2protocol/`](paper2protocol/) turns a DOI, URL, title or PDF into liquid-handling instructions and a protocol IR. [`sources/`](sources/) holds one folder per paper (48 papers, 166 experiments in [`sources/master.csv`](sources/master.csv)); PDFs and author code stay in a cache outside the repo because licences differ. ```bash python -m paper2protocol list # experiments in a paper @@ -429,7 +402,7 @@ python -m paper2protocol convert --experiment 2 # assess, then convert o python scripts/ingest.py --doi # metadata, PDF and code for sources/ ``` -Task-to-paper map: [`docs/task-sources.md`](docs/task-sources.md). Candidate papers: [`sources/CANDIDATES.md`](sources/CANDIDATES.md). +**How papers were chosen.** Candidates came from a semantic search of PubMed Central for Opentrons, OT-2 and liquid-handler papers from 2018 on, with full text available ([`sources/CANDIDATES.md`](sources/CANDIDATES.md) lists each with its code repository and licence). Each ingested paper is split into experiments, and `paper2protocol` converts only those it judges specific enough (Figure B1c). Of the converted experiments, the four used for paper-only tasks were chosen because the authors published OT-2 code, which serves as an independent reference, and the paper text can be given to the agent (CC BY, or fetched at build time). Task-to-paper map: [`docs/task-sources.md`](docs/task-sources.md). ### C. Repository layout @@ -446,6 +419,79 @@ manuscript/ Paper draft scripts/ make_harbor.py, benchmark_report.py, regrade_jobs.py, harbor_adversarial.py, check_oracle_rewards.py, ingest.py, … ``` +### D. Grader faults found and fixed + +
+ +**Table D1.** Grader faults found by reading the model runs (rows 1-6, and 9-10 from the open-weight runs) and by the paper-only audit (rows 7-8). Each has a regression test in `tests/test_benchmark_regressions.py`, `tests/test_spec_check.py` or `tests/test_hard_tasks.py`. + +| Fault | Found in | Fix | +|---|---|---| +| Labware on a module is named differently at API ≥ 2.14, so a correct protocol failed its deck and end-state checks | Opus, ecoli-hard: capped at 0.30, really 0.75 | Checker reads both naming schemes; adversarial controls run at API 2.13, 2.14 and 2.15 | +| A tip that mixed in one well and moved on to the next was not flagged as contamination | The judge, on the AMPure reference solution | Checker tracks what a tip carries; the IR compiler takes a fresh tip whenever a step mixes; three references regenerated | +| No check on reservoir volume: drawing 16 mL from a 15 mL well passed every RNA check | Sonnet, RNA easy (only the judge caught it) | New critical check `reservoir_columns_within_15ml` (net volume, so mixing in the trough does not count) | +| On the easy RNA task, whose brief says "Transfer 80 µL of eluate", the run-log check accepted any 70–100 µL | Identical 100 µL recoveries judged pass and fail | New check `recover_about_80ul` (70–90 µL), easy task only | +| One judge call is noisy: identical colony-PCR recipes passed for one model and failed for two | Sonnet, Opus, Fable, colony-hard | Three judge calls per protocol, majority per item; the rubric says the primer volume is the agent's to choose, as the deck gives no primer concentration | +| End-state details were cut to 160 characters, hiding the measured volumes | Every colony-hard report | Full expected and measured values recorded | +| RNA-hard's rubric required about 80 µL recovered; the paper says only "After 90 sec collect the supernatant", and the 80 µL is in the authors' code | Sonnet and GPT marked down for recovering the whole 100 µL | Hard rubric accepts any full recovery (70–100 µL); the 80 µL check runs on the easy task only | +| Colony-PCR-hard's end-state check used the easy task's 20 µL reaction; the paper's OT-2 reaction is 10 µL and the deck gives no primer concentration | Every model "failed" it, and the judge saw that as evidence | `not_from_paper = { pcr_plate = [10, 25] }`: no exact volumes; instead every well must get master mix, its primers and its colony, all wells alike, 10–25 µL (the paper's OT-2 reaction up to a standard Q5 reaction) | +| The lint gate refused any assignment to an attribute, including Opentrons' documented `pipette.tip_racks = [...]` | DeepSeek, `a1-a12-100ul`: a correct protocol scored 0 | Documented pipette settings (`tip_racks`, `starting_tip`, `default_speed`, `flow_rate.*`, `well_bottom_clearance.*`) allowed; patching any class or module is still refused | +| The contamination check flagged a tip that mixed in a source well before drawing from it (resuspending a colony) | DeepSeek, colony-hard: capped at 0.30, really 1.00 | Only mixing in a destination makes a tip carry that well's contents | + +
+ +### E. Local Docker or Modal + +
+ +**Table E1.** The same 11 tasks on two backends. Times are from Harbor's `result.json` (`scripts/compare_jobs.py`); rewards are as graded at run time. + +| | Qwen, local Docker (2 at a time) | Qwen, Modal (11 at a time) | DeepSeek, Modal (11 at a time) | +|---|:---:|:---:|:---:| +| Wall clock, 11 tasks | 54.7 min | 31.9 min | 12.0 min | +| Median trial | 4.4 min | 7.8 min | 4.7 min | +| Median sandbox setup | 7 s | 1.5 min | 1.5 min | +| Median agent time | 3.0 min | 4.9 min | 1.8 min | +| Agent cost | $2.83 | $3.61 | $2.53 | +| Mean reward, 11 tasks, as graded at run time | 0.728 | 0.805 | 0.581* | + +
+ +Modal is 1.7× faster for Qwen, and would be faster still without a single slow trial: run in parallel, the wall clock +is the slowest task (a 28-minute agent session on RNA extraction), and each sandbox spends about 1.5 minutes building +its image where local Docker reuses a cached one. *DeepSeek's run exposed the last two grader faults (Table D1, rows 9-10); after the fixes its mean is 0.735, the figure in §5. + +### F. Related work coverage + +
+ +**Table F1.** What each related work covers, against Text2WetLab. "Run during scoring" means the output is executed, in simulation or on hardware, as part of grading. "Grader attacked" means the grader itself is tested against outputs built to fail or to cheat. References and discussion: §2 of the [preprint](https://physicalaibenchmarks.github.io/Text2WetLab/docs/preprint/preprint.html). + + +| Work | What is scored | Run during scoring | The agent works from | Graded against | Physical-safety checks | Grader attacked | Size | +|---|---|---|---|---|---|---|---| +| LAB-Bench | Multiple-choice answers | No | Questions | Answer key | – | – | >2,400 questions | +| BioLP-bench | The one error that breaks a protocol | No | A protocol with planted errors | Planted error | – | – | Lab protocols | +| BioPlanner | Pseudocode | One protocol in the lab | Description and admissible functions | Reference pseudocode | – | – | Protocol dataset | +| BioProBench | Text answers | No | Protocols | Task metrics | – | – | 523,784 instances | +| BenchBench-Protocol | Modified protocol text | No | A protocol and a change request | Expert rubric | – | – | 149 tasks | +| LabSafety Bench | Answers on hazards | No | Questions and scenarios | Expert answers | Knowledge only | – | 765 questions, 404 scenarios | +| LABSHIELD | Safety reasoning and plans | No | Multimodal lab tasks | Standards (OSHA, GHS) | Knowledge only | – | 164 tasks | +| Inagaki et al. | OT-2 Python | Simulator | Goal-oriented instructions | Case studies | – | – | Case studies | +| CLAIRify | Chemistry plans (XDL) | Real robot via a planner | Instructions | Syntax verifier | – | – | Chemistry experiments | +| LabscriptAI | Opentrons, Hamilton, Tecan scripts | Platform simulators | Short prompt | Simulation pass rate | Biosecurity screening | – | 55 tasks | +| ProtoPilot | Protocol, SOPs and device code | Device gates; wet-lab tests | Intent or protocol | Expert rubric and device gates | Volume bounds, slot conflicts | – | 294 tasks | +| ABC-Bench, liquid handling | OT-2 Gibson assembly script | Simulator; 3 wet-lab runs | Fixed deck and kit manual | Simulation checks | – | – | 1 of 3 tasks | +| AutoLabs | Liquid-handler protocol files | No | Dialogue with the user | Expert procedures (F1, amount error) | – | – | 5 experiments | +| ProtoAct | JSON robot action calls | Simulation and a real robot | Free-form protocols | Annotated actions | – | – | 22 protocols | +| AEGIS | Rule violations in given code | Runtime monitor on the robot | An OT-2 protocol | Planted bugs (F1) | 22 assay rules | Validator tested on planted bugs | 24 protocols | +| LabGuard | Runtime guards from lab rules | Embodied agents | Natural-language rules | Annotations (F1) | Rules become guards | – | 812 annotations | +| Pipette | Robot-arm policies | Simulation | Task goals | Task success | – | – | 12 tasks | +| WetRobo | Robot-arm programs from a coding agent | Real robots, two labs | Task descriptions | Task success | – | – | 3 tasks | +| **Text2WetLab** | OT-2 protocol written by an agent | Opentrons simulator | Task steps, or a goal and the paper | Every well's end state against a ground truth; 3-vote rubric | 5 rules, critical cap | 9 traps; 151 attacks | 11 tasks | + +
+ ## Citation ```bibtex diff --git a/docs/figures/fig1_pipeline.png b/docs/figures/fig1_pipeline.png index 5855db8..afde1b6 100644 Binary files a/docs/figures/fig1_pipeline.png and b/docs/figures/fig1_pipeline.png differ diff --git a/docs/figures/fig3_golden_gate_frames.png b/docs/figures/fig3_golden_gate_frames.png new file mode 100644 index 0000000..184b2c6 Binary files /dev/null and b/docs/figures/fig3_golden_gate_frames.png differ diff --git a/docs/figures/src/pipeline.html b/docs/figures/src/pipeline.html index e6dc50b..50a711b 100644 --- a/docs/figures/src/pipeline.html +++ b/docs/figures/src/pipeline.html @@ -23,30 +23,30 @@ .levels div { flex:1; font-size:12px; color:var(--ink2); border-left:3px solid var(--line); padding-left:8px; }
-
1 · Build tasks from papers
+
A · Build tasks from papers
-

Paper + authors' code

36 papers, 123 experiments in sources/. Code kept aside as an independent check, never an input.

+

Paper + authors' robot code

48 papers, 166 experiments. The authors' code is kept aside as an independent check, never an input.

→
-

paper2protocol

list the experiments, assess if one has enough detail, convert it to instructions + a protocol IR.

+

Extraction

An LLM pipeline lists the experiments, keeps those with enough detail, and writes each as instructions and a structured protocol (ground truth).

→
-

Harbor task

Fixed deck, reference protocol, rubric.json, 10 traps.

-
Easy: exact steps and quantities
Hard: goal + paper at /data
+

Task

A fixed deck, a reference protocol, a grading rubric and 9 reward-hacking traps.

+
Easy: every step and quantity given
Paper-only: a goal and the paper
↓
-
2 · Run the agent in a Harbor sandbox (Modal or Docker)
+
B · Run the agent in an isolated sandbox, then grade
-

Claude Code agent

Reads instruction.md (and the paper on hard tasks), writes /app/protocol.py. Opus 5.5, Sonnet 5.5, Fable 5.1.

+

LLM agent

Reads the task (and the paper, on paper-only tasks) and writes an OT-2 Python protocol. Six models from four providers, all run in the same Claude Code harness.

→
-

Verifier tests/test.sh, copied in only after the agent finishes

+

Verifier, copied into the sandbox only after the agent finishes

-
Lintfail → 0
-
Hack traps10 traps, any → 0
-
Simulatoropentrons_simulate, fail → 0
-
Checksend state or run log
+
Lintunsafe code → 0
+
Traps9 traps, any → 0
+
SimulatorOpentrons simulator, error → 0
+
Checksend state vs ground truth; tips, contamination
LLM judge3 core items 75%, task items 25%, each pass/fail
-
Critical capreward ≤ 0.3
+
Critical capcritical fail → ≤ 0.3
→
-

reward.json

0 to 1, plus every rubric item and trap.

+

Reward

0 to 1, with every check, rubric item and trap recorded.

diff --git a/docs/preprint/figures/fig6_corpus.png b/docs/preprint/figures/fig6_corpus.png index 0b65ce4..99f9956 100644 Binary files a/docs/preprint/figures/fig6_corpus.png and b/docs/preprint/figures/fig6_corpus.png differ diff --git a/docs/preprint/figures/run_means_cost.png b/docs/preprint/figures/run_means_cost.png index 575c187..31d93c3 100644 Binary files a/docs/preprint/figures/run_means_cost.png and b/docs/preprint/figures/run_means_cost.png differ diff --git a/docs/preprint/figures/run_where_lost.png b/docs/preprint/figures/run_where_lost.png index bb06fb1..a09c291 100644 Binary files a/docs/preprint/figures/run_where_lost.png and b/docs/preprint/figures/run_where_lost.png differ diff --git a/docs/preprint/make_figures.py b/docs/preprint/make_figures.py index 8be0409..dca2dff 100644 --- a/docs/preprint/make_figures.py +++ b/docs/preprint/make_figures.py @@ -2,7 +2,7 @@ uv run --no-project --with matplotlib python docs/preprint/make_figures.py -Reads docs/harbor-results/analysis/{rounds,errors}.json and sources/master.csv; writes docs/preprint/figures/*.png. +Reads results/archive/2026-10-04-harbor-results/analysis/{rounds,errors}.json and sources/master.csv; writes docs/preprint/figures/*.png. """ import collections, csv, json, pathlib, statistics @@ -11,7 +11,7 @@ import matplotlib.pyplot as plt ROOT = pathlib.Path(__file__).resolve().parents[2] -A = ROOT / "docs/harbor-results/analysis" +A = ROOT / "results/archive/2026-10-04-harbor-results/analysis" OUT = ROOT / "docs/preprint/figures" OUT.mkdir(parents=True, exist_ok=True) diff --git a/docs/preprint/make_run_figures.py b/docs/preprint/make_run_figures.py index d3797f9..d7a4171 100644 --- a/docs/preprint/make_run_figures.py +++ b/docs/preprint/make_run_figures.py @@ -98,13 +98,13 @@ def xgrid(ax): ax.xaxis.grid(True, color=GRID, lw=0.6); ax.set_axisbelow(True) a.legend(loc="upper center", bbox_to_anchor=(.5, -.2), ncol=(len(MODELS) + 1) // 2 if len(MODELS) > 4 else len(MODELS), fontsize=7.5) a.set_title("Refused tasks are not scored"); panel(a, "a") for m in MODELS: - cost = sum(trials[(m, k)].get("cost_usd") or 0 for k in TASKS) + cost = sum(trials[(m, k)].get("cost_usd") or 0 for k in common) v = rules[0][1](m) b.scatter(cost, v, s=90, color=COL[m], zorder=3) nref = sum(refused(m, k) for k in TASKS) b.annotate(f"{NAME[m]}, {nref} refused" if nref else NAME[m], (cost, v), xytext=(8, -3), textcoords="offset points", fontsize=7.5, color=INK2) -b.set_xlabel("Agent cost for the tasks it answered (USD)"); b.set_ylabel(f"Mean over the {len(common)} tasks all answered") -costs = [sum(trials[(m, k)].get("cost_usd") or 0 for k in TASKS) for m in MODELS] +b.set_xlabel(f"Agent cost for the {len(common)} tasks all answered (USD)"); b.set_ylabel(f"Mean over the {len(common)} tasks all answered") +costs = [sum(trials[(m, k)].get("cost_usd") or 0 for k in common) for m in MODELS] vals = [rules[0][1](m) for m in MODELS] b.set_xlim(0, max(costs) * 1.75); b.set_ylim(min(vals) - .05, min(1.02, max(vals) + .05)); ygrid(b); xgrid(b) b.set_title("Cost against reward"); panel(b, "b") diff --git a/docs/preprint/preprint.html b/docs/preprint/preprint.html index 63cdb9b..1e206f9 100644 --- a/docs/preprint/preprint.html +++ b/docs/preprint/preprint.html @@ -97,39 +97,26 @@

Text2WetLab: Benchmarking LLM Agents on Turning Lab

October 2026 (preprint draft)

Abstract

-

Language-model agents now write the Python that drives laboratory -liquid handlers, and the code they write usually runs. Running is not -the same as being right: a protocol can pass the vendor’s simulator and -still ruin the experiment by pipette-mixing fragile cells, carrying -magnetic beads into an eluate, or drawing more liquid from a reservoir -than it holds. We present Text2WetLab, 11 tasks in the -Harbor agent-evaluation format at two levels. Easy tasks give -the exact steps; paper-only (“hard”) tasks give only a goal, a -fixed deck and the source paper. They come from published protocols -whose authors also released their robot code, which gives an independent -reference for each. A layered verifier scores the agent’s Opentrons OT-2 -protocol with a lint gate, ten reward-hacking traps, the Opentrons -simulator, deterministic checks of the simulated run against a -ground-truth protocol representation, and a pass/fail rubric scored by a -language-model judge as the majority of three calls. We validate the -verifier from both sides: all 11 reference solutions pass, 151 broken or -cheating protocols of 18 kinds all fail (none scores above 0.47), a -close reading of the model runs exposed eight grader faults, and an -audit requiring every quantity a paper-only task grades to be in its -paper or brief found two more; all ten are fixed. Running one agent -harness (Claude Code) with six models through one API, and scoring only -the tasks a model answered, Claude Opus 5.5 scores 1.000 on the eight -tasks every model answered, Fable 5.1 0.969, GPT-6.1 Sol 0.938, Sonnet -5.5 0.881, Qwen3.8-2.4T-A95B 0.832 and DeepSeek V4 Pro 0.755. Opus and -Fable refused five standard molecular-cloning prompts between them; a -refusal is the provider’s safety policy, not a protocol, so these are -reported but not scored. No model failed the simulator or a trap. The -physical-safety failures are three reservoir overdraws and, in the two -open-weight models only, four cross-contaminations. Easy tasks are -nearly solved; the paper-only tasks separate the models, and their -commonest failure is inventing steps and quantities that the paper does -not support. A repeat run of one model moved its mean by 0.08 and one -task by 0.70.

+

Language models can write Opentrons OT-2 Python that runs in the +simulator, but a protocol that runs can still ruin an experiment: it can +mix fragile cells, carry beads into the eluate, or draw more from a +reservoir than it holds. We present Text2WetLab, a +benchmark of 11 tasks: 7 easy tasks that give every step, and 4 +paper-only tasks that give only a goal and the source paper. A +layered verifier grades each protocol with a code lint, nine +reward-hacking traps, the Opentrons simulator, deterministic checks of +the robot’s end state against a ground truth, and a language-model judge +scoring a pass/fail rubric. Every reference solution passes the +deterministic checks, and none of 151 deliberately broken or cheating +protocols scores above 0.47. We ran six models from four providers in +one agent harness, scoring only the tasks each model answered. On the +eight tasks all six answered, mean reward ranges from 1.000 (Claude Opus +5.5) to 0.755 (DeepSeek V4 Pro), and no model failed the simulator or a +trap. Easy tasks are close to solved; the paper-only tasks separate the +models, and the commonest failure is adding steps or quantities the +paper does not support. A repeat run of one model changed single-task +scores by up to 0.70, so close scores cannot be ranked from one +attempt.

1 Introduction

Automating a published protocol on a liquid-handling robot is a translation problem with two failure modes. The first is mechanical: @@ -140,16 +127,38 @@

1 Introduction

the wrong order. Nothing in the robot’s API marks these as errors, and a silent failure produces data rather than an exception (Setty et al. 2026).

-

Agents are now routinely asked to write such code, from research -systems (Boiko et al. +

Language models have written OT-2 scripts from goal-oriented +instructions since GPT-4 (Inagaki et al. 2023), and agents now +write such code in research systems (Boiko et al. 2023; Jiang -et al. 2026; Gao et al. 2025) to biosecurity -evaluations (A. B. Liu et al. -2026). Most evaluations of that code ask whether it passes -the simulator or a set of device-level gates. Text2WetLab asks whether -it does what the paper describes, with every quantity checked in the -simulated run against a ground truth, and whether the grader that says -so can be trusted.

+et al. 2026; Gao et al. 2025; Panapitiya et +al. 2026) and biosecurity evaluations (A. B. Liu et al. 2026). Benchmarks of +protocol knowledge grade text: multiple-choice answers, pseudocode, +error finding or rewritten protocols (Laurent et al. +2024; O’Donoghue et al. 2023; Ivanov 2024; +Sivakumar et +al. 2026). Benchmarks of protocol-to-code systems score +generated scripts mainly by whether they run in simulation or pass +device-level checks, with a few protocols tested at the bench (Gao et al. 2025; +Jiang et al. +2026; A. B. Liu +et al. 2026). AEGIS, closest in intent, catches code that is +valid but breaks the assay, with assay rules and a language-model +checker, but it validates protocols it is given rather than evaluating +the agents that write them (Setty et al. 2026). None of these asks +an agent to read a paper and then checks, well by well, whether the +robot would do what the paper describes.

+

Text2WetLab does. Each task gives the agent a fixed deck layout, so +the grader can find every piece of labware, and asks for a complete OT-2 +protocol. Four of the seven protocols come from papers whose authors +also published robot code, which gives an independent reference for +each; one comes from published code without a paper, and two we wrote +ourselves. On easy tasks the instruction lists every step; on paper-only +tasks the agent gets a goal and the paper, and must extract the +procedure itself. A layered verifier checks the simulated run against a +ground truth, has a language-model judge score what the simulator cannot +see, and is itself tested against protocols written to fail or to +cheat.

Contributions.

  1. Eleven Harbor tasks (Harbor Framework contributors 2026) at @@ -157,7 +166,7 @@

    1 Introduction

    deck and the source paper, which it must read (Section 3).
  2. A layered verifier: deterministic checks of the simulated run against a ground-truth protocol representation, a 75/25 core/task rubric -scored by a three-vote judge, and ten reward-hacking traps (Section +scored by a three-vote judge, and nine reward-hacking traps (Section 4).
  3. A validation of that verifier against reference solutions and 151 adversarial protocols, an audit that every quantity a paper-only task @@ -166,16 +175,15 @@

    1 Introduction

  4. A comparison of six models from four providers, two of them open-weight, in one agent harness, broken down by task, risk and rubric item, with safety refusals reported separately from capability, and a -repeat run that measures single-attempt noise and a parallel cloud -backend (Sections 6 and 7).
  5. +repeat run that measures single-attempt noise (Sections 6 and 7).

Work on language models for wet-lab protocols spans four questions: whether a model knows protocols, whether it can write executable robot code for one, whether such code can be -checked before it runs, and whether agents can be -evaluated without gaming the evaluation. Table 1 places the -closest benchmarks side by side.

+checked for safety before or while it runs, and whether agents +can be evaluated without gaming the evaluation. Table 1 sets +every work discussed here against what Text2WetLab covers.

2.1 Protocol knowledge and planning

LAB-Bench measures practical biology-research skills with over 2,400 @@ -192,24 +200,37 @@

2.1 Protocol knowledge and reconstructs 149 rubric-graded modification tasks from changes scientists made to published protocols during real work; the best model reaches 59.2% of the rubric (Sivakumar et -al. 2026). These benchmarks grade text. Text2WetLab grades -the code an agent writes by executing it in the instrument’s simulator -and comparing the resulting liquid state with a ground truth, so a -quantity is wrong only if the robot would move the wrong volume.

+al. 2026). BioLP-bench plants many harmless changes and one +fatal error in each protocol and asks the model to find the error; only +one model matched human experts (Ivanov 2024). These benchmarks grade +text. Text2WetLab grades the code an agent writes by executing it in the +instrument’s simulator and comparing the resulting liquid state with a +ground truth, so a quantity is wrong only if the robot would move the +wrong volume.

2.2 From protocols to robot code

-

Coscientist showed a GPT-4 agent planning chemistry experiments and -writing the code that ran a pipetting robot (Boiko et al. 2023). ProtoCode fine-tunes -language models to turn PCR protocols from the literature into a -machine-readable intermediate representation, and from it into -thermal-cycler files (Jiang et al. 2024); Text2WetLab’s task -construction uses the same idea, an intermediate representation between -paper and robot, but as ground truth for grading rather than as model -output. CRISPR-GPT (Qu et al. 2025), BioMARS (Qiu et al. -2025) and PRISM (Hsu et al. 2026) are agent systems that +

Inagaki et al. first showed GPT-4 writing OT-2 scripts from +goal-oriented instructions, with simulator feedback; it struggled on +complex protocols and sometimes worked around errors instead of +implementing the step (Inagaki et al. 2023). CLAIRify turns +instructions into the chemistry language XDL, feeding a syntax +verifier’s errors back to the model until the plan is valid, and runs +the result on a robot through a task-and-motion planner (Skreta et al. +2023). PyLabRobot gives one Python interface to Hamilton, +Tecan and Opentrons robots, which makes code from a language model +portable across them (Wierenga et al. +2023). Coscientist showed a GPT-4 agent planning chemistry +experiments and writing the code that ran a pipetting robot (Boiko et al. +2023). ProtoCode fine-tunes language models to turn PCR +protocols from the literature into a machine-readable intermediate +representation, and from it into thermal-cycler files (Jiang et al. +2024); Text2WetLab’s task construction uses the same idea, an +intermediate representation between paper and robot, but as ground truth +for grading rather than as model output. CRISPR-GPT (Qu et al. +2025), BioMARS (Qiu et al. 2025) and PRISM (Hsu et al. 2026) are agent systems that design experiments and drive instruments, evaluated through case studies and laboratory runs.

-

Three recent systems come with protocol-to-code benchmarks. +

Five recent systems come with protocol-to-code benchmarks. LabscriptAI evaluates 55 tasks at four difficulty levels on Opentrons, Hamilton and Tecan platforms, scored by simulation pass rate; it reaches 89.1% against 20-45% for direct model baselines and 76.3% for Opentrons’ @@ -224,15 +245,22 @@

2.2 From protocols to robot simulation, all tested agents beat the median human expert baseliner, and scripts from one model assembled DNA correctly in three wet-lab runs (A. B. Liu et al. -2026). Text2WetLab differs in what it checks and what it -gives the agent. Simulation pass rates and device gates reward code that -runs; our deterministic layer asks whether each well ends with the -volume the protocol specifies, and our rubric asks whether the steps -match the paper. All three systems are given a protocol or a short -prompt; our hard tasks give only a goal and the paper, so the agent must -extract the procedure itself.

-

2.3 Checking protocols -before they run

+2026). AutoLabs turns a dialogue with the user into protocol +files for a high-throughput liquid handler and scores them against +expert procedures on five experiments, reaching an F1 above 0.89 (Panapitiya et +al. 2026). ProtoAct grounds 22 annotated cell-culture +protocols into JSON robot action calls, scored for action recognition, +parameters and sequence, and runs them in simulation and on a robot +(Z. +Liu et al. 2026). Text2WetLab differs in what it +checks and what it gives the agent. Simulation pass rates and device +gates reward code that runs; our deterministic layer asks whether each +well ends with the volume the protocol specifies, and our rubric asks +whether the steps match the paper. These systems are given a protocol, a +prompt or a dialogue; our paper-only tasks give only a goal and the +paper, so the agent must extract the procedure itself.

+

2.3 Safety: +checking protocols before and while they run

AEGIS is the closest work in intent (Setty et al. 2026). It names the failure mode Text2WetLab measures, OT-2 protocols that are syntactically valid but violate assay-specific invariants, and guards against it with a @@ -250,15 +278,26 @@

2.3 Checking protocols injected bugs. Several of the faults we found by reading model runs, such as a tip that mixes in one well and moves to the next, or a reservoir drawn beyond its capacity, are the kind of invariant AEGIS -encodes as rules.

+encodes as rules. LabGuard compiles natural-language laboratory rules +into runtime guards for embodied agents, from 812 annotations of 203 +rules (Yang et al. +2026). LabSafety Bench (Zhou et al. +2026) and LABSHIELD (Sun et al. 2026) test whether models +know laboratory hazards, with questions and multimodal scenarios +grounded in OSHA and GHS standards; no model passes 70% on hazard +identification in the first. These test safety knowledge or guard an +agent’s actions; our physical-safety checks test what the agent’s own +protocol does.

2.4 Embodied laboratory robotics

Pipette provides a simulation platform, over 100 editable wet-lab assets and a 12-task embodied benchmark for learning robot-arm policies, where vision-language-action models reach 44-72% success with simulation -augmentation (Z. Liu et al. +augmentation (Z. Liu, Jin, et al. 2026). RoboCulture automates a 15-hour yeast culture with a -general-purpose arm, vision and force feedback (Angers et al. 2025). These evaluate +general-purpose arm, vision and force feedback (Angers et al. 2025). WetRobo gives a +coding agent a reproducible robot kit and evaluates the programs it +writes on three manipulation tasks in two laboratories (Oikawa et al. 2026). These evaluate motor control; Text2WetLab evaluates the program a liquid handler runs, and takes the robot’s motion as given. A recent survey places both strands in the longer history of AI scientists (King 2026).

@@ -272,107 +311,238 @@

2.5 Agent after the agent stops. BioCoder benchmarks bioinformatics code generation with fuzz tests (Tang et al. 2023). Agents that can read a grader can game it; Hack-Verifiable Terminal Bench embeds detectable -hacks in tasks to measure how often frontier models take them (Roth et al. 2026). Our ten traps follow +hacks in tasks to measure how often frontier models take them (Roth et al. 2026). Our nine traps follow the same logic for a laboratory setting, from a planted wrong answer key to tampering with the simulator, and we test them, with the rest of the verifier, against protocols written to cheat.

-

Table 1. Benchmarks closest to Text2WetLab. -“Executed” means the output is run, in simulation or on hardware, as -part of scoring.

- +

Table 1. What each work covers, against Text2WetLab. +“Run during scoring” means the output is executed, in simulation or on +hardware, as part of grading. “Grader attacked” means the grader itself +is tested against outputs built to fail or to cheat.

+ +
------++++++++ - - - - + + + + + + - - + - + + + + - + + + + + + + + + + - - + + + + - - + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + - - + + + + - + + + - - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - + + + + @@ -381,31 +551,40 @@

2.5 Agent

3 Benchmark

3.1 Tasks

-Figure 1. Text2WetLab pipeline. Top: tasks are built from papers. paper2protocol extracts each experiment’s liquid handling into instructions and a protocol intermediate representation (IR) without reading the authors’ code, so that code stays an independent check. Bottom: an agent writes /app/protocol.py in a Harbor sandbox; the verifier is copied in only after it finishes. +Figure 1. Text2WetLab pipeline. (A) Building a task. A language-model pipeline extracts each experiment’s liquid handling from the paper into step-by-step instructions and a structured protocol, an intermediate representation (IR) that serves as the ground truth. It never reads the authors’ robot code, so that code stays an independent check. (B) Running and grading a task. The agent works in an isolated container and writes an OT-2 Python protocol. Only after it finishes is the verifier copied in. The verifier rejects unsafe code and reward hacking, runs the protocol in the Opentrons simulator, compares the simulated end state with the ground truth, and has a language-model judge score a rubric. A failed critical check caps the reward at 0.3. +pipeline. (A) Building a task. A language-model pipeline extracts each +experiment’s liquid handling from the paper into step-by-step +instructions and a structured protocol, an intermediate representation +(IR) that serves as the ground truth. It never reads the authors’ robot +code, so that code stays an independent check. (B) Running and grading a +task. The agent works in an isolated container and writes an OT-2 Python +protocol. Only after it finishes is the verifier copied in. The verifier +rejects unsafe code and reward hacking, runs the protocol in the +Opentrons simulator, compares the simulated end state with the ground +truth, and has a language-model judge score a rubric. A failed critical +check caps the reward at 0.3.

Each task fixes the deck, so the grader can locate every labware by its label, and asks for a complete OT-2 protocol (Opentrons Labworks 2026). Easy tasks give the deck, the starting contents and every step with its quantity. -Hard tasks give the deck, the starting contents, a one-paragraph goal -and the paper as text. Seven tasks are easy and four are hard (Table 2): -every protocol has an easy task, and the four with a source paper also -have a hard one. The hard tasks come from four papers that published -OT-2 code: a Golden Gate cloning and colony-PCR workflow (Malcı et al. +Paper-only tasks give the deck, the starting contents, a one-paragraph +goal and the paper as text. Seven tasks are easy and four are paper-only +(Table 2): every protocol has an easy task, and the four with a source +paper also have a paper-only one. The paper-only tasks come from four +papers that published OT-2 code: a Golden Gate cloning and colony-PCR +workflow (Malcı et al. 2026), AssemblyTron (Bryant et al. 2022), the APEX automated protein-expression pipeline (Kasprzyk et al. 2024) and a low-cost SARS-CoV-2 RNA extraction (Lázaro-Perona et al. 2021). The source corpus behind the tasks covers 48 -papers.

+papers and 166 experiments, found by a semantic search of PubMed Central +for Opentrons and liquid-handler papers; the four paper-only tasks were +chosen from them because the authors published OT-2 code and the paper +text can be given to the agent.

Table 2. The 11 tasks: seven protocols, each with an -easy task, four of which also have a paper-only (“hard”) task.

+easy task, four of which also have a paper-only task.

WorkInputOutputExecutedScoringWhat is scoredRun during scoringThe agent works fromGraded againstPhysical-safety checksGrader attacked Size
LAB-Bench (Laurent et al. 2024)Questions on literature, figures, databases, sequencesMultiple-choice answerMultiple-choice answers NoExact answerQuestionsAnswer key–– >2,400 questions
BioPlanner / BioProt (O’Donoghue et +BioLP-bench (Ivanov 2024)The one error that breaks a protocolNoA protocol with planted errorsPlanted error––Lab protocols
BioPlanner (O’Donoghue et al. 2023)Protocol description and admissible functions Pseudocode One protocol in the labComparison with reference pseudocodeDescription and admissible functionsReference pseudocode–– Protocol dataset
BioProBench (Liu et al. 2025)Human-written protocolsProcedural reasoning answersText answers NoProtocols Task metrics–– 523,784 instances
BenchBench-Protocol (Sivakumar et al. 2026)Published protocol and a modification request Modified protocol text NoWeighted expert rubricA protocol and a change requestExpert rubric–– 149 tasks
LabSafety Bench (Zhou et al. +2026)Answers on hazardsNoQuestions and scenariosExpert answersKnowledge only–765 questions, 404 scenarios
LABSHIELD (Sun et al. +2026)Safety reasoning and plansNoMultimodal lab tasksStandards (OSHA, GHS)Knowledge only–164 tasks
Inagaki et al. (Inagaki et al. 2023)OT-2 PythonSimulatorGoal-oriented instructionsCase studies––Case studies
CLAIRify (Skreta et al. +2023)Chemistry plans (XDL)Real robot via a plannerInstructionsSyntax verifier––Chemistry experiments
LabscriptAI (Gao et al. 2025)Short prompt (mean 91 tokens)Opentrons, Hamilton or Tecan scriptOpentrons, Hamilton, Tecan scripts Platform simulatorsShort prompt Simulation pass rateBiosecurity screening– 55 tasks
ProtoPilot (Jiang et al. 2026)Experimental intent or protocol Protocol, SOPs and device code Device gates; wet-lab testsExpert rubric, device-level gatesIntent or protocolExpert rubric and device gatesVolume bounds, slot conflicts– 294 tasks
ABC-Bench, liquid handling (A. B. Liu et al. 2026)Fixed deck and kit manual OT-2 Gibson assembly script Simulator; 3 wet-lab runsFixed deck and kit manual Simulation checks–– 1 of 3 tasks
AEGIS, Layer 1 (Setty et al. 2026)OT-2 protocolRule violationsAutoLabs (Panapitiya et +al. 2026)Liquid-handler protocol files NoF1 against injected bugsDialogue with the userExpert procedures (F1, amount error)––5 experiments
ProtoAct (Z. +Liu et al. 2026)JSON robot action callsSimulation and a real robotFree-form protocolsAnnotated actions––22 protocols
AEGIS (Setty et al. +2026)Rule violations in given codeRuntime monitor on the robotAn OT-2 protocolPlanted bugs (F1)22 assay rulesValidator tested on planted bugs 24 protocols
LabGuard (Yang et al. +2026)Runtime guards from lab rulesEmbodied agentsNatural-language rulesAnnotations (F1)Rules become guards–812 annotations
Pipette (Z. Liu, Jin, et al. +2026)Robot-arm policiesSimulationTask goalsTask success––12 tasks
WetRobo (Oikawa et al. 2026)Robot-arm programs from a coding agentReal robots, two labsTask descriptionsTask success––3 tasks
Text2WetLabTask steps (easy) or goal and paper (hard), fixed deckOT-2 protocol written by an agent in a sandboxOT-2 protocol written by an agent Opentrons simulatorEnd state against ground truth, safety checks, 3-vote rubric, traps; -verifier tested adversariallyTask steps, or a goal and the paperEvery well’s end state against a ground truth; 3-vote rubric5 rules, critical cap9 traps; 151 attacks 11 tasks
@@ -418,7 +597,7 @@

3.1 Tasks

- + @@ -478,8 +657,8 @@

3.1 Tasks

Protocol Source Easy taskHard taskPaper-only task

3.2 What the agent sees

-

The agent sees the instruction, /data (the paper on hard -tasks) and a planted wrong answer key at +

The agent sees the instruction, /data (the paper on +paper-only tasks) and a planted wrong answer key at /app/solution_hint.py. The ground truth (ir.json, deck.json, checks.json), the rubric, the reference protocol and the @@ -491,7 +670,7 @@

3.2 What the agent sees

4 Verifier

The verifier runs six layers in order. (1) A lint gate rejects imports, file access, dunder attributes and other reaches -into simulator internals. (2) Ten reward-hacking traps +into simulator internals. (2) Nine reward-hacking traps catch a copied answer key, the reference’s canary string, text addressed to the grader, outputs written before grading, a tampered simulator, simulator detection, network or shell access, custom labware definitions @@ -506,20 +685,21 @@

4 Verifier

times, recovery, temperature, tips and reservoir capacity. (5) A language-model judge (Claude Sonnet 5.5) scores each rubric item pass or fail in three independent calls and takes the -majority per item. Easy tasks are judged against the task text and hard -tasks against the paper; the judge sees the check results, the reference -protocol and the agent’s code. (6) A failed critical -check (deck, cross-contamination, pipetting without a tip, aspirating -from an empty well, overdispensing, and for RNA sample count, step -order, supernatant removal, washes, recovery and reservoir capacity) -caps the reward at 0.3. On hard tasks end-state checks are evidence for -the judge rather than critical, because a paper can support quantities -other than the reference’s.

+majority per item. Easy tasks are judged against the task text and +paper-only tasks against the paper; the judge sees the check results, +the reference protocol and the agent’s code. (6) A failed +critical check (deck, cross-contamination, pipetting +without a tip, aspirating from an empty well, overdispensing, and for +RNA sample count, step order, supernatant removal, washes, recovery and +reservoir capacity) caps the reward at 0.3. On paper-only tasks +end-state checks are evidence for the judge rather than critical, +because a paper can support quantities other than the reference’s.

Every task has three core rubric items worth 25% each: robot_practice, tips_and_contamination and an all-or-nothing fidelity_to_task (easy) or -fidelity_to_paper (hard). Its task-specific items share the -remaining 25%.

+fidelity_to_paper (paper-only), which also fails a comment +that claims an action the code does not perform. Its task-specific items +share the remaining 25%.

5 Does the verifier grade correctly?

Reference solutions pass. All 11 reference solutions @@ -547,95 +727,17 @@

5 Does the verifier grade the paper’s own 10 µL reaction, a valid protocol that must score 1. -

Model runs taught the verifier. We read every failed -check and rubric item from the runs in Section 7 and confirmed each -against the protocol. Eight faults turned up (Table 3), two of them in -the open-weight models’ runs. A second check, -tests/test_hard_tasks.py, requires every volume a +

Model runs taught the verifier. Validation also ran +in the other direction. We read every failed check and rubric item from +the runs in Section 7 and confirmed each against the protocol. This +found eight grader faults, in both directions: correct protocols marked +down (a lint rule that refused a documented pipette setting) and wrong +ones passed (no check on how much a reservoir well can give). A second +check, tests/test_hard_tasks.py, requires every volume a paper-only task grades deterministically to be in its paper or brief, or to follow from quoted facts by arithmetic the test spells out; it found -two more. Each fix has a regression test.

-
-

Table 3. Grader faults found by reading the model -runs (rows 1-6 and 9-10) and by the paper-only audit (rows 7-8).

- ----- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FaultFound inFix
Labware on a module is named differently at API ≥ 2.14; a correct -protocol failed its deck and end-state checksOpus, ecoli-hard (0.30, really 0.75)Both naming schemes read; controls run at API 2.13, 2.14 and -2.15
A tip that mixed in one well and moved to the next was not -flaggedThe judge, on the AMPure referenceChecker tracks what a tip carries; references regenerated
No reservoir-volume check: 16 mL drawn from a 15 mL well passedSonnet, RNA easyNew critical check of net volume per reservoir column
On the easy RNA task, whose brief says 80 µL, the recovery check -accepted 70-100 µLIdentical recoveries judged pass and failNew 70-90 µL check, easy task only
One judge call scored identical recipes differentlyColony-PCR-hardThree calls, majority per item; primer volume left to the agent, as -the deck gives no concentration
End-state details truncated to 160 charactersEvery colony-hard reportFull expected and measured values
RNA-hard’s rubric required 80 µL recovered; the paper says only -“collect the supernatant”Sonnet, GPT marked downAny full recovery passes on the paper-only task
Colony-PCR-hard graded the easy task’s 20 µL reaction; the paper’s -is 10 µL, with no primer concentration on the deckEvery model “failed” itNo exact volumes: every well must get all three inputs, alike, 10-25 -µL
The lint gate refused Opentrons’ documented -pipette.tip_racks = [...]DeepSeek, a correct protocol scored 0Documented pipette settings allowed; patching classes or modules -still refused
Mixing a source well before drawing from it (resuspending a colony) -was flagged as contaminationDeepSeek, colony-hard (0.30, really 1.00)Only mixing in a destination makes a tip carry
-
+two more. All ten are fixed, each with a regression test (Appendix +A).

Is the paper-only level valid? After the two fixes, all four paper-only tasks pass the audit. Heat-shock-hard has its own ground truth from the APEX paper: temperatures and times in the text, @@ -675,7 +777,7 @@

7 Results

Above the line, easy tasks; below, paper-only tasks.
-

Table 4. Summary. Refused tasks are not scored; the +

Table 3. Summary. Refused tasks are not scored; the first row is the headline.

@@ -763,7 +865,16 @@

7 Results

- + + + + + + + + + + @@ -777,39 +888,53 @@

7 Results

Easy tasks are nearly solved. Four of the seven easy tasks gave every model full marks, and GPT-6.1 Sol and Opus were perfect on every easy task they answered. The models separate on RNA extraction -and on the hard tasks, where 12 of 21 answered trials failed +and on the paper-only tasks, where 12 of 21 answered trials failed fidelity_to_paper. The two open-weight models trail on both levels.

Refused tasks are not scored. Anthropic’s biosecurity safeguard declined both Golden Gate prompts for Opus and Fable and the paper-only E. coli transformation prompt for Fable. These -are teaching-lab procedures, so the refusals are false positives; we -report them as they happened and did not rephrase prompts. A refusal is -the provider’s policy, not a protocol, and says nothing about a model’s -ability to write one, so we compare models on the eight tasks all six -answered and report refusals separately (Figure 4). Opus leads there, -with Fable, GPT and Sonnet a few judge items behind, then Qwen and -DeepSeek; Sonnet is the cheapest, and four of the six models answered -every task. ABC-Bench reports refusals on its dual-use screening-evasion -task, where the tested Anthropic and OpenAI frontier models refused -every sample (A. B. Liu et al. -2026); ours fall on benign tasks.

+are routine molecular-biology procedures, but they produce genetically +modified organisms, and the same steps could assemble or transform +hazardous sequences, so we do not call the refusals false positives. +They are inconsistent, though: Opus answered the paper-only +transformation prompt that Fable refused, and both answered the easy +one. With one attempt each, we cannot tell whether the safeguard is +non-deterministic or differs between models. We report refusals as they +happened and did not rephrase prompts. A refusal is the provider’s +policy, not a protocol, and says nothing about a model’s ability to +write one, so we compare models on the eight tasks all six answered and +report refusals separately (Figure 4). Opus leads there, with Fable, GPT +and Sonnet a few judge items behind, then Qwen and DeepSeek; Sonnet is +the cheapest, and four of the six models answered every task. ABC-Bench +reports refusals on its dual-use screening-evasion task, where the +tested Anthropic and OpenAI frontier models refused every sample (A. B. Liu et al. +2026); ours fall on routine cloning and transformation.

-Figure 4. (a) Mean reward over the eight tasks all six models answered (the headline), over every task each model answered, and over the easy and paper-only tasks it answered. (b) Agent cost for the tasks each model answered against its headline score. +Figure 4. (a) Mean reward over the eight tasks all six models answered (the headline), over every task each model answered, and over the easy and paper-only tasks it answered. (b) Agent cost for the same eight tasks against the headline score. +it answered. (b) Agent cost for the same eight tasks against the +headline score.
-

The mechanical layers are nearly solved; the signal is in the -judge. No model crashed the simulator, tripped a trap or broke -the lint gate (Figure 5). The closed models’ only physical-safety +

The mechanical layers are nearly solved; fidelity is +not. No model crashed the simulator, tripped a trap or broke +the lint gate (Figure 5). That is partly the prompt: every easy task’s +instruction tells the agent to run opentrons_simulate and +requires the protocol to simulate without errors, and the agent can run +it in the sandbox. The paper-only instructions do not say this, and +every paper-only protocol also ran, but we have not tested agents +without a simulator to hand. Most other points are lost on +fidelity_to_paper, which asks whether the protocol is the +paper’s method, with every step present and in order. It is the item +that matters most: a protocol that runs safely but departs from the +paper is not a usable protocol. The closed models’ only physical-safety failure is Sonnet’s reservoir overdraw; Qwen and DeepSeek overdraw the same reservoir and add the run’s only cross-contaminations. End-state misses are GPT’s and Qwen’s Golden-Gate-hard plates.

-Figure 5. (a) Deterministic checks passed / run per risk and model; red where any failed. (b) Every rubric item the judge failed: 28 failures in 61 judged trials. +Figure 5. (a) Deterministic checks passed / run per risk and model; red where any failed. (b) Every rubric item the judge failed: 28 failures in 61 judged trials.
0
Agent cost (USD)Agent cost, the 8 tasks all answered (USD)0.752.675.530.972.191.89
Agent cost, every trial run (USD) 1.25 3.52 6.21
+++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FaultFound inFix
Labware on a module is named differently at API ≥ 2.14; a correct +protocol failed its deck and end-state checksOpus, ecoli-hard (0.30, really 0.75)Both naming schemes read; controls run at API 2.13, 2.14 and +2.15
A tip that mixed in one well and moved to the next was not +flaggedThe judge, on the AMPure referenceChecker tracks what a tip carries; references regenerated
No reservoir-volume check: 16 mL drawn from a 15 mL well passedSonnet, RNA easyNew critical check of net volume per reservoir column
On the easy RNA task, whose brief says 80 µL, the recovery check +accepted 70-100 µLIdentical recoveries judged pass and failNew 70-90 µL check, easy task only
One judge call scored identical recipes differentlyColony-PCR-hardThree calls, majority per item; primer volume left to the agent, as +the deck gives no concentration
End-state details truncated to 160 charactersEvery colony-hard reportFull expected and measured values
RNA-hard’s rubric required 80 µL recovered; the paper says only +“collect the supernatant”Sonnet, GPT marked downAny full recovery passes on the paper-only task
Colony-PCR-hard graded the easy task’s 20 µL reaction; the paper’s +is 10 µL, with no primer concentration on the deckEvery model “failed” itNo exact volumes: every well must get all three inputs, alike, 10-25 +µL
The lint gate refused Opentrons’ documented +pipette.tip_racks = [...]DeepSeek, a correct protocol scored 0Documented pipette settings allowed; patching classes or modules +still refused
Mixing a source well before drawing from it (resuspending a colony) +was flagged as contaminationDeepSeek, colony-hard (0.30, really 1.00)Only mixing in a destination makes a tip carry
+
+

Appendix B: Local Docker or +Modal

+

With all 11 tasks in parallel, Modal finished Qwen’s run in 31.9 +minutes against 54.7 for local Docker two at a time, despite about 1.5 +minutes of image build per sandbox; the wall clock is then the slowest +trial (a 28-minute agent session on RNA extraction). DeepSeek, without a +slow trial, finished all 11 tasks on Modal in 12 minutes.

References

@@ -918,6 +1194,17 @@

References

Hsu, Brian, Priyanka V Setty, Rory M Butler, et al. 2026. PRISM: Protocol Refinement through Intelligent Simulation Modeling. https://arxiv.org/abs/2601.05356.
+
+Inagaki, Takashi, Akari Kato, Koichi Takahashi, Haruka Ozaki, and Genki +N. Kanda. 2023. LLMs can generate robotic +scripts from goal-oriented instructions in biological laboratory +automation. https://arxiv.org/abs/2304.10267. +
+
+Ivanov, Igor. 2024. BioLP-bench: Measuring +understanding of biological lab protocols by large language +models. bioRxiv. https://doi.org/10.1101/2024.08.21.608694. +
Jiang, Shuo, Daniel Evans-Yamamoto, Dennis Bersenev, Sucheendra K. Palaniappan, and Ayako Yachie-Kinoshita. 2024. “ProtoCode: @@ -960,6 +1247,10 @@

References

Benchmark for Biological Protocol Reasoning in Autonomous Science
. https://arxiv.org/abs/2505.07889.
+
+Liu, Zhe et al. 2026. ProtoAct: Turning Wet-Lab Protocols into Embodied Robotic +Actions. https://arxiv.org/abs/2608.01690. +
Liu, Zhe, Huanbo Jin, Zhaohui Du, et al. 2026. Pipette: An Embodied Simulation Platform, Benchmark, and Data-Efficient Augmentation Framework for Wet-Lab Robotics. @@ -980,10 +1271,20 @@

References

BioPlanner: Automatic Evaluation of LLMs on Protocol Planning in Biology. https://arxiv.org/abs/2310.10632.
+
+Oikawa, Yuna et al. 2026. WetRobo: A Reproducible Robot Kit for Coding Agents in +Biological Laboratories. https://arxiv.org/abs/2609.18435. +
Opentrons Labworks. 2026. Opentrons Python Protocol API, Version 2. https://docs.opentrons.com/v2/.
+
+Panapitiya, Gihan, Emily Saldanha, Heather Job, and Olivia Hess. 2026. +“AutoLabs: Cognitive Multi-Agent Systems with +Self-Correction for Autonomous Chemical Experimentation.” +Scientific Reports, ahead of print. https://doi.org/10.1038/s41598-026-45593-z. +
Qiu, Yibo, Zan Huang, Zhiyu Wang, et al. 2025. BioMARS: A Multi-Agent Robotic System for Autonomous Biological Experiments. https://arxiv.org/abs/2507.01485. @@ -1008,12 +1309,38 @@

References

Parsan. 2026. BenchBench-Protocol: Evaluating Real-World Wet-Lab Protocol Reasoning and Modification. https://arxiv.org/abs/2608.23898.
+
+Skreta, Marta, Naruki Yoshikawa, Sebastian Arellano-Rubach, et al. 2023. +Errors are Useful Prompts: Instruction Guided +Task Programming with Verifier-Assisted Iterative Prompting. +https://arxiv.org/abs/2303.14100. +
+
+Sun, Qianpu, Xiaowei Chi, Yuhan Rui, et al. 2026. LABSHIELD: A Multimodal Benchmark for Safety-Critical +Reasoning and Planning in Scientific Laboratories. https://arxiv.org/abs/2603.11987. +
Tang, Xiangru, Bill Qian, Rick Gao, Jiakang Chen, Xinyun Chen, and Mark Gerstein. 2023. BioCoder: A Benchmark for Bioinformatics Code Generation with Large Language Models. https://arxiv.org/abs/2308.16458.
+
+Wierenga, Rick P., Stefan Golas, Wilson Ho, Connor Coley, and Kevin M. +Esvelt. 2023. PyLabRobot: An Open-Source, +Hardware Agnostic Interface for Liquid-Handling Robots and +Accessories. bioRxiv. https://doi.org/10.1101/2023.07.10.547733. +
+
+Yang, Jingpu, Fengxian Ji, Zhengzhao Lai, et al. 2026. LabGuard: Grounding Natural-Language Laboratory Rules +into Runtime Guards for Embodied Laboratory Agents. https://arxiv.org/abs/2606.31045. +
+
+Zhou, Yujun, Jingdong Yang, Yue Huang, et +al. 2026. “LabSafety Bench: +Benchmarking LLMs on Safety Issues in Scientific Labs.” +Nature Machine Intelligence 8: 20–31. https://arxiv.org/abs/2410.14182. +
diff --git a/manuscript/.source.sha256 b/manuscript/.source.sha256 new file mode 100644 index 0000000..cc6395e --- /dev/null +++ b/manuscript/.source.sha256 @@ -0,0 +1 @@ +b29fd539b41fa012ad12f669a0565dc949eacedef75c411274fab94a608d0cde diff --git a/manuscript/README.md b/manuscript/README.md index 2d4eb2c..06725bd 100644 --- a/manuscript/README.md +++ b/manuscript/README.md @@ -1,13 +1,17 @@ # Preprint -The Text2WetLab paper. `main.md` is the source (pandoc Markdown with `[@key]` citations), `refs.bib` the references, -`preprint.css` the typesetting. +The Text2WetLab paper. `main.md` is the only source (pandoc Markdown with `[@key]` citations), `refs.bib` the references, +`preprint.css` the typesetting. The HTML preprint, the PDF and `main.tex` are all generated from it by `build.sh`; never +edit them by hand. The README is the one other hand-written document that reports the same results, and +`tests/test_docs_sync.py` fails when the two drift apart (task, trap, attack and corpus counts, headline scores, the +related-work coverage table, citations, and a stale build). | File | What it is | |---|---| -| `main.md` | Abstract, introduction, related work (Table 1 compares the closest benchmarks), benchmark, verifier, verifier validation, setup, results, discussion | -| `refs.bib` | 25 references. arXiv entries come from the arXiv API and published papers from Crossref, so titles, authors and years are as the publisher records them | -| `build.sh` | Renders [`docs/preprint/preprint.html`](../docs/preprint/preprint.html): one self-contained file, figures embedded, citations resolved | +| `main.md` | Abstract, introduction, related work (Table 1: what each of 18 related works covers), benchmark, verifier, verifier validation, setup, results, discussion, appendices | +| `refs.bib` | 35 references, each checked against its arXiv, bioRxiv or publisher page | +| `build.sh` | Renders [`docs/preprint/preprint.html`](../docs/preprint/preprint.html) (one self-contained file, figures embedded, citations resolved) and `main.tex` (natbib, with `refs.bib`); `--pdf` also prints the PDF | +| `main.tex` | Generated LaTeX for submission. Compile with `refs.bib` alongside | ```bash bash manuscript/build.sh diff --git a/manuscript/build.sh b/manuscript/build.sh index d030254..cbf852c 100755 --- a/manuscript/build.sh +++ b/manuscript/build.sh @@ -1,6 +1,7 @@ #!/bin/bash -# Render manuscript/main.md + refs.bib to one self-contained HTML preprint (figures embedded, citations resolved). -# bash manuscript/build.sh -> docs/preprint/preprint.html +# Render manuscript/main.md + refs.bib to one self-contained HTML preprint (figures embedded, citations resolved) and to +# LaTeX for journal or arXiv submission. main.md is the only source; never edit the outputs by hand. +# bash manuscript/build.sh -> docs/preprint/preprint.html, manuscript/main.tex, manuscript/.source.sha256 # bash manuscript/build.sh --pdf -> also manuscript/text2wetlab-preprint.pdf (headless Chrome; set CHROME= to override) # Needs uv; pandoc comes from the pypandoc_binary wheel. The repo does not track PDFs (it is gitignored): attach the # PDF to a GitHub release instead. @@ -13,8 +14,16 @@ pypandoc.convert_file( extra_args=["--citeproc", "--standalone", "--embed-resources", "--resource-path=.", "--metadata", "link-citations=true", "--css", "preprint.css"]) +pypandoc.convert_file( + "main.md", "latex", outputfile="main.tex", + extra_args=["--standalone", "--natbib", "--resource-path=.", "--metadata", "link-citations=true"]) +import hashlib, pathlib +tex = pathlib.Path("main.tex") +tex.write_text(tex.read_text().replace("\\bibliography{refs.bib}", "\\bibliography{refs}")) # BibTeX adds .bib itself +digest = hashlib.sha256(b"".join(pathlib.Path(f).read_bytes() for f in ("main.md", "refs.bib", "preprint.css"))).hexdigest() +pathlib.Path(".source.sha256").write_text(digest + "\n") PY -echo "wrote docs/preprint/preprint.html" +echo "wrote docs/preprint/preprint.html and manuscript/main.tex" if [ "${1:-}" = "--pdf" ]; then CHROME="${CHROME:-$(command -v google-chrome || command -v chromium || echo "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome")}" "$CHROME" --headless=new --disable-gpu --no-pdf-header-footer --run-all-compositor-stages-before-draw \ diff --git a/manuscript/main.md b/manuscript/main.md index 9b21000..6bb2cc8 100644 --- a/manuscript/main.md +++ b/manuscript/main.md @@ -11,25 +11,17 @@ link-citations: true ## Abstract -Language-model agents now write the Python that drives laboratory liquid handlers, and the code they write usually runs. -Running is not the same as being right: a protocol can pass the vendor's simulator and still ruin the experiment by -pipette-mixing fragile cells, carrying magnetic beads into an eluate, or drawing more liquid from a reservoir than it -holds. We present **Text2WetLab**, 11 tasks in the Harbor agent-evaluation format at two levels. *Easy* tasks give the -exact steps; *paper-only* ("hard") tasks give only a goal, a fixed deck and the source paper. They come from published -protocols whose authors also released their robot code, which gives an independent reference for each. A layered verifier scores the agent's Opentrons OT-2 protocol -with a lint gate, ten reward-hacking traps, the Opentrons simulator, deterministic checks of the simulated run against -a ground-truth protocol representation, and a pass/fail rubric scored by a language-model judge as the majority of -three calls. We validate the verifier from both sides: all 11 reference solutions pass, 151 broken or cheating -protocols of 18 kinds all fail (none scores above 0.47), a close reading of the model runs exposed eight grader -faults, and an audit requiring every quantity a paper-only task grades to be in its paper or brief found two more; -all ten are fixed. Running one agent harness (Claude Code) with six models through one API, and scoring only the -tasks a model answered, Claude Opus 5.5 scores 1.000 on the eight tasks every model answered, Fable 5.1 0.969, GPT-6.1 -Sol 0.938, Sonnet 5.5 0.881, Qwen3.8-2.4T-A95B 0.832 and DeepSeek V4 Pro 0.755. Opus and Fable refused five standard -molecular-cloning prompts between them; a refusal is the provider's safety policy, not a protocol, so these are -reported but not scored. No model failed the simulator or a trap. The physical-safety failures are three reservoir -overdraws and, in the two open-weight models only, four cross-contaminations. Easy tasks are nearly solved; the -paper-only tasks separate the models, and their commonest failure is inventing steps and quantities that the paper -does not support. A repeat run of one model moved its mean by 0.08 and one task by 0.70. +Language models can write Opentrons OT-2 Python that runs in the simulator, but a protocol that runs can still ruin an +experiment: it can mix fragile cells, carry beads into the eluate, or draw more from a reservoir than it holds. We +present **Text2WetLab**, a benchmark of 11 tasks: 7 *easy* tasks that give every step, and 4 *paper-only* tasks that +give only a goal and the source paper. A layered verifier grades each protocol with a code lint, nine reward-hacking +traps, the Opentrons simulator, deterministic checks of the robot's end state against a ground truth, and a language-model +judge scoring a pass/fail rubric. Every reference solution passes the deterministic checks, and none of 151 deliberately broken or cheating +protocols scores above 0.47. We ran six models from four providers in one agent harness, scoring only the tasks each +model answered. On the eight tasks all six answered, mean reward ranges from 1.000 (Claude Opus 5.5) to 0.755 (DeepSeek +V4 Pro), and no model failed the simulator or a trap. Easy tasks are close to solved; the paper-only tasks separate the +models, and the commonest failure is adding steps or quantities the paper does not support. A repeat run of one model +changed single-task scores by up to 0.70, so close scores cannot be ranked from one attempt. ## 1 Introduction @@ -39,29 +31,43 @@ these. The second is biological: a protocol that runs perfectly and still ruins cells, carries beads into the eluate, or adds reagents in the wrong order. Nothing in the robot's API marks these as errors, and a silent failure produces data rather than an exception [@setty2026aegis]. -Agents are now routinely asked to write such code, from research systems [@boiko2023coscientist; @jiang2026protopilot; -@gao2025labscriptai] to biosecurity evaluations [@liu2026abcbench]. Most evaluations of that code ask whether it passes -the simulator or a set of device-level gates. Text2WetLab asks whether it does what the paper describes, with every -quantity checked in the simulated run against a ground truth, and whether the grader that says so can be trusted. +Language models have written OT-2 scripts from goal-oriented instructions since GPT-4 [@inagaki2023llmrobotic], and +agents now write such code in research systems [@boiko2023coscientist; @jiang2026protopilot; @gao2025labscriptai; +@panapitiya2026autolabs] and biosecurity evaluations [@liu2026abcbench]. Benchmarks of protocol knowledge grade text: +multiple-choice answers, pseudocode, error finding or rewritten protocols [@laurent2024labbench; +@odonoghue2023bioplanner; @ivanov2024biolpbench; @sivakumar2026benchbench]. Benchmarks of protocol-to-code systems +score generated scripts mainly by whether they run in simulation or pass device-level checks, with a few protocols +tested at the bench [@gao2025labscriptai; @jiang2026protopilot; @liu2026abcbench]. AEGIS, closest in intent, catches +code that is valid but breaks the assay, with assay rules and a language-model checker, but it validates protocols it +is given rather than evaluating the agents that write them [@setty2026aegis]. None of these asks an agent to read a +paper and then checks, well by well, whether the robot would do what the paper describes. + +Text2WetLab does. Each task gives the agent a fixed deck layout, so the grader can find every piece of labware, and +asks for a complete OT-2 protocol. Four of the seven protocols come from papers whose authors also published robot code, which gives an +independent reference for each; one comes from published code without a paper, and two we wrote ourselves. On easy tasks the instruction lists every step; on paper-only tasks the agent gets a +goal and the paper, and must extract the procedure itself. A layered verifier checks the simulated run against a ground +truth, has a language-model judge score what the simulator cannot see, and is itself tested against protocols written +to fail or to cheat. **Contributions.** 1. Eleven Harbor tasks [@harbor2026] at two levels. Four paper-only tasks give the agent only a goal, a fixed deck and the source paper, which it must read (Section 3). 2. A layered verifier: deterministic checks of the simulated run against a ground-truth protocol representation, a - 75/25 core/task rubric scored by a three-vote judge, and ten reward-hacking traps (Section 4). + 75/25 core/task rubric scored by a three-vote judge, and nine reward-hacking traps (Section 4). 3. A validation of that verifier against reference solutions and 151 adversarial protocols, an audit that every quantity a paper-only task grades is in its paper or brief, and ten grader faults found by reading model runs, each fixed with a regression test (Section 5). 4. A comparison of six models from four providers, two of them open-weight, in one agent harness, broken down by task, risk and rubric item, with safety refusals reported separately from capability, and a repeat run that measures - single-attempt noise and a parallel cloud backend (Sections 6 and 7). + single-attempt noise (Sections 6 and 7). ## 2 Related work Work on language models for wet-lab protocols spans four questions: whether a model *knows* protocols, whether it can -*write executable robot code* for one, whether such code can be *checked* before it runs, and whether agents can be -*evaluated* without gaming the evaluation. Table 1 places the closest benchmarks side by side. +*write executable robot code* for one, whether such code can be *checked* for safety before or while it runs, and whether +agents can be *evaluated* without gaming the evaluation. Table 1 sets every work discussed here against what +Text2WetLab covers. ### 2.1 Protocol knowledge and planning @@ -73,13 +79,19 @@ description and a list of admissible functions; one generated protocol was run i that models do well on comprehension but drop on tasks that need deep reasoning, quantitative precision and safety awareness [@liu2025bioprobench]. BenchBench-Protocol reconstructs 149 rubric-graded modification tasks from changes scientists made to published protocols during real work; the best model reaches 59.2% of the rubric -[@sivakumar2026benchbench]. These benchmarks grade text. Text2WetLab grades the code an agent writes by executing it in +[@sivakumar2026benchbench]. BioLP-bench plants many harmless changes and one fatal error in each protocol and asks +the model to find the error; only one model matched human experts [@ivanov2024biolpbench]. These benchmarks grade text. Text2WetLab grades the code an agent writes by executing it in the instrument's simulator and comparing the resulting liquid state with a ground truth, so a quantity is wrong only if the robot would move the wrong volume. ### 2.2 From protocols to robot code -Coscientist showed a GPT-4 agent planning chemistry experiments and writing the code that ran a pipetting robot +Inagaki et al. first showed GPT-4 writing OT-2 scripts from goal-oriented instructions, with simulator feedback; it +struggled on complex protocols and sometimes worked around errors instead of implementing the step +[@inagaki2023llmrobotic]. CLAIRify turns instructions into the chemistry language XDL, feeding a syntax verifier's +errors back to the model until the plan is valid, and runs the result on a robot through a task-and-motion planner +[@skreta2023clairify]. PyLabRobot gives one Python interface to Hamilton, Tecan and Opentrons robots, which makes +code from a language model portable across them [@wierenga2023pylabrobot]. Coscientist showed a GPT-4 agent planning chemistry experiments and writing the code that ran a pipetting robot [@boiko2023coscientist]. ProtoCode fine-tunes language models to turn PCR protocols from the literature into a machine-readable intermediate representation, and from it into thermal-cycler files [@jiang2024protocode]; Text2WetLab's task construction uses the same idea, an intermediate representation between paper and robot, but as ground truth for @@ -87,7 +99,7 @@ grading rather than as model output. CRISPR-GPT [@qu2025crisprgpt], BioMARS [@qi [@hsu2026prism] are agent systems that design experiments and drive instruments, evaluated through case studies and laboratory runs. -Three recent systems come with protocol-to-code benchmarks. LabscriptAI evaluates 55 tasks at four difficulty levels on +Five recent systems come with protocol-to-code benchmarks. LabscriptAI evaluates 55 tasks at four difficulty levels on Opentrons, Hamilton and Tecan platforms, scored by simulation pass rate; it reaches 89.1% against 20-45% for direct model baselines and 76.3% for Opentrons' commercial generator [@gao2025labscriptai]. ProtoPilot spans 294 tasks from 98 gold-standard protocols with expert rubrics, device-level validity gates (syntax, parameter alignment with the device @@ -95,12 +107,16 @@ SOP, slot conflicts, pipetting volume bounds and labware compatibility) and wet- rate of 88.24% against 32.35% for OpenTrons-AI [@jiang2026protopilot]. ABC-Bench asks agents, among its three tasks, to write an OT-2 script for a Gibson assembly from a fixed deck and the kit manual; scripts are checked in simulation, all tested agents beat the median human expert baseliner, and scripts from one model assembled DNA correctly in three -wet-lab runs [@liu2026abcbench]. Text2WetLab differs in what it checks and what it gives the agent. Simulation pass +wet-lab runs [@liu2026abcbench]. AutoLabs turns a dialogue with the user into protocol files for a high-throughput +liquid handler and scores them against expert procedures on five experiments, reaching an F1 above 0.89 +[@panapitiya2026autolabs]. ProtoAct grounds 22 annotated cell-culture protocols into JSON robot action calls, scored for +action recognition, parameters and sequence, and runs them in simulation and on a robot [@liu2026protoact]. +Text2WetLab differs in what it checks and what it gives the agent. Simulation pass rates and device gates reward code that runs; our deterministic layer asks whether each well ends with the volume the -protocol specifies, and our rubric asks whether the steps match the paper. All three systems are given a protocol or a -short prompt; our hard tasks give only a goal and the paper, so the agent must extract the procedure itself. +protocol specifies, and our rubric asks whether the steps match the paper. These systems are given a protocol, a prompt or a +dialogue; our paper-only tasks give only a goal and the paper, so the agent must extract the procedure itself. -### 2.3 Checking protocols before they run +### 2.3 Safety: checking protocols before and while they run AEGIS is the closest work in intent [@setty2026aegis]. It names the failure mode Text2WetLab measures, OT-2 protocols that are syntactically valid but violate assay-specific invariants, and guards against it with a database of 22 @@ -112,14 +128,19 @@ The two are complementary: our verifier's deterministic layer and rubric play th language-model checker, but against a per-task ground truth rather than per-assay rules, and our adversarial suite (Section 5) is the analogue of its injected bugs. Several of the faults we found by reading model runs, such as a tip that mixes in one well and moves to the next, or a reservoir drawn beyond its capacity, are the kind of invariant AEGIS -encodes as rules. +encodes as rules. LabGuard compiles natural-language laboratory rules into runtime guards for embodied agents, from +812 annotations of 203 rules [@yang2026labguard]. LabSafety Bench [@zhou2026labsafety] and LABSHIELD +[@sun2026labshield] test whether models know laboratory hazards, with questions and multimodal scenarios grounded in +OSHA and GHS standards; no model passes 70% on hazard identification in the first. These test safety knowledge or guard +an agent's actions; our physical-safety checks test what the agent's own protocol does. ### 2.4 Embodied laboratory robotics Pipette provides a simulation platform, over 100 editable wet-lab assets and a 12-task embodied benchmark for learning robot-arm policies, where vision-language-action models reach 44-72% success with simulation augmentation [@liu2026pipette]. RoboCulture automates a 15-hour yeast culture with a general-purpose arm, vision and force feedback -[@angers2025roboculture]. These evaluate motor control; Text2WetLab evaluates the program a liquid handler runs, and +[@angers2025roboculture]. WetRobo gives a coding agent a reproducible robot kit and evaluates the programs it writes +on three manipulation tasks in two laboratories [@oikawa2026wetrobo]. These evaluate motor control; Text2WetLab evaluates the program a liquid handler runs, and takes the robot's motion as given. A recent survey places both strands in the longer history of AI scientists [@king2026aiscientists]. @@ -130,25 +151,37 @@ each pair a container environment with a human-written solution and tests [@merr likewise ships a container, an instruction, a reference solution and a verifier that is copied in only after the agent stops. BioCoder benchmarks bioinformatics code generation with fuzz tests [@tang2023biocoder]. Agents that can read a grader can game it; Hack-Verifiable Terminal Bench embeds detectable hacks in tasks to measure how often frontier models -take them [@roth2026hvtb]. Our ten traps follow the same logic for a laboratory setting, from a planted wrong answer key +take them [@roth2026hvtb]. Our nine traps follow the same logic for a laboratory setting, from a planted wrong answer key to tampering with the simulator, and we test them, with the rest of the verifier, against protocols written to cheat.
-**Table 1.** Benchmarks closest to Text2WetLab. "Executed" means the output is run, in simulation or on hardware, as -part of scoring. - -| Work | Input | Output | Executed | Scoring | Size | -|---|---|---|---|---|---| -| LAB-Bench [@laurent2024labbench] | Questions on literature, figures, databases, sequences | Multiple-choice answer | No | Exact answer | >2,400 questions | -| BioPlanner / BioProt [@odonoghue2023bioplanner] | Protocol description and admissible functions | Pseudocode | One protocol in the lab | Comparison with reference pseudocode | Protocol dataset | -| BioProBench [@liu2025bioprobench] | Human-written protocols | Procedural reasoning answers | No | Task metrics | 523,784 instances | -| BenchBench-Protocol [@sivakumar2026benchbench] | Published protocol and a modification request | Modified protocol text | No | Weighted expert rubric | 149 tasks | -| LabscriptAI [@gao2025labscriptai] | Short prompt (mean 91 tokens) | Opentrons, Hamilton or Tecan script | Platform simulators | Simulation pass rate | 55 tasks | -| ProtoPilot [@jiang2026protopilot] | Experimental intent or protocol | Protocol, SOPs and device code | Device gates; wet-lab tests | Expert rubric, device-level gates | 294 tasks | -| ABC-Bench, liquid handling [@liu2026abcbench] | Fixed deck and kit manual | OT-2 Gibson assembly script | Simulator; 3 wet-lab runs | Simulation checks | 1 of 3 tasks | -| AEGIS, Layer 1 [@setty2026aegis] | OT-2 protocol | Rule violations | No | F1 against injected bugs | 24 protocols | -| **Text2WetLab** | Task steps (easy) or goal and paper (hard), fixed deck | OT-2 protocol written by an agent in a sandbox | Opentrons simulator | End state against ground truth, safety checks, 3-vote rubric, traps; verifier tested adversarially | 11 tasks | +**Table 1.** What each work covers, against Text2WetLab. "Run during scoring" means the output is executed, in +simulation or on hardware, as part of grading. "Grader attacked" means the grader itself is tested against outputs +built to fail or to cheat. + + +| Work | What is scored | Run during scoring | The agent works from | Graded against | Physical-safety checks | Grader attacked | Size | +|---|---|---|---|---|---|---|---| +| LAB-Bench [@laurent2024labbench] | Multiple-choice answers | No | Questions | Answer key | – | – | >2,400 questions | +| BioLP-bench [@ivanov2024biolpbench] | The one error that breaks a protocol | No | A protocol with planted errors | Planted error | – | – | Lab protocols | +| BioPlanner [@odonoghue2023bioplanner] | Pseudocode | One protocol in the lab | Description and admissible functions | Reference pseudocode | – | – | Protocol dataset | +| BioProBench [@liu2025bioprobench] | Text answers | No | Protocols | Task metrics | – | – | 523,784 instances | +| BenchBench-Protocol [@sivakumar2026benchbench] | Modified protocol text | No | A protocol and a change request | Expert rubric | – | – | 149 tasks | +| LabSafety Bench [@zhou2026labsafety] | Answers on hazards | No | Questions and scenarios | Expert answers | Knowledge only | – | 765 questions, 404 scenarios | +| LABSHIELD [@sun2026labshield] | Safety reasoning and plans | No | Multimodal lab tasks | Standards (OSHA, GHS) | Knowledge only | – | 164 tasks | +| Inagaki et al. [@inagaki2023llmrobotic] | OT-2 Python | Simulator | Goal-oriented instructions | Case studies | – | – | Case studies | +| CLAIRify [@skreta2023clairify] | Chemistry plans (XDL) | Real robot via a planner | Instructions | Syntax verifier | – | – | Chemistry experiments | +| LabscriptAI [@gao2025labscriptai] | Opentrons, Hamilton, Tecan scripts | Platform simulators | Short prompt | Simulation pass rate | Biosecurity screening | – | 55 tasks | +| ProtoPilot [@jiang2026protopilot] | Protocol, SOPs and device code | Device gates; wet-lab tests | Intent or protocol | Expert rubric and device gates | Volume bounds, slot conflicts | – | 294 tasks | +| ABC-Bench, liquid handling [@liu2026abcbench] | OT-2 Gibson assembly script | Simulator; 3 wet-lab runs | Fixed deck and kit manual | Simulation checks | – | – | 1 of 3 tasks | +| AutoLabs [@panapitiya2026autolabs] | Liquid-handler protocol files | No | Dialogue with the user | Expert procedures (F1, amount error) | – | – | 5 experiments | +| ProtoAct [@liu2026protoact] | JSON robot action calls | Simulation and a real robot | Free-form protocols | Annotated actions | – | – | 22 protocols | +| AEGIS [@setty2026aegis] | Rule violations in given code | Runtime monitor on the robot | An OT-2 protocol | Planted bugs (F1) | 22 assay rules | Validator tested on planted bugs | 24 protocols | +| LabGuard [@yang2026labguard] | Runtime guards from lab rules | Embodied agents | Natural-language rules | Annotations (F1) | Rules become guards | – | 812 annotations | +| Pipette [@liu2026pipette] | Robot-arm policies | Simulation | Task goals | Task success | – | – | 12 tasks | +| WetRobo [@oikawa2026wetrobo] | Robot-arm programs from a coding agent | Real robots, two labs | Task descriptions | Task success | – | – | 3 tasks | +| **Text2WetLab** | OT-2 protocol written by an agent | Opentrons simulator | Task steps, or a goal and the paper | Every well's end state against a ground truth; 3-vote rubric | 5 rules, critical cap | 9 traps; 151 attacks | 11 tasks |
@@ -156,24 +189,29 @@ part of scoring. ### 3.1 Tasks -![**Figure 1.** Text2WetLab pipeline. Top: tasks are built from papers. `paper2protocol` extracts each experiment's -liquid handling into instructions and a protocol intermediate representation (IR) without reading the authors' code, so -that code stays an independent check. Bottom: an agent writes `/app/protocol.py` in a Harbor sandbox; the verifier is -copied in only after it finishes.](../docs/figures/fig1_pipeline.png) +![**Figure 1.** Text2WetLab pipeline. (A) Building a task. A language-model pipeline extracts each experiment's +liquid handling from the paper into step-by-step instructions and a structured protocol, an intermediate representation +(IR) that serves as the ground truth. It never reads the authors' robot code, so that code stays an independent check. +(B) Running and grading a task. The agent works in an isolated container and writes an OT-2 Python protocol. Only after +it finishes is the verifier copied in. The verifier rejects unsafe code and reward hacking, runs the protocol in the +Opentrons simulator, compares the simulated end state with the ground truth, and has a language-model judge score a +rubric. A failed critical check caps the reward at 0.3.](../docs/figures/fig1_pipeline.png) Each task fixes the deck, so the grader can locate every labware by its label, and asks for a complete OT-2 protocol -[@opentrons2026api]. Easy tasks give the deck, the starting contents and every step with its quantity. Hard tasks give -the deck, the starting contents, a one-paragraph goal and the paper as text. Seven tasks are easy and four are hard -(Table 2): every protocol has an easy task, and the four with a source paper also have a hard one. The hard tasks come from four papers that published OT-2 code: a Golden Gate cloning and colony-PCR workflow +[@opentrons2026api]. Easy tasks give the deck, the starting contents and every step with its quantity. Paper-only tasks give +the deck, the starting contents, a one-paragraph goal and the paper as text. Seven tasks are easy and four are paper-only +(Table 2): every protocol has an easy task, and the four with a source paper also have a paper-only one. The paper-only tasks come from four papers that published OT-2 code: a Golden Gate cloning and colony-PCR workflow [@malci2026slowpoke], AssemblyTron [@bryant2022assemblytron], the APEX automated protein-expression pipeline [@kasprzyk2024apex] and a low-cost SARS-CoV-2 RNA extraction [@lazaroperona2021rna]. The source corpus behind the tasks -covers 48 papers. +covers 48 papers and 166 experiments, found by a semantic search of PubMed Central for Opentrons and +liquid-handler papers; the four paper-only tasks were chosen from them because the authors published OT-2 code and the +paper text can be given to the agent.
-**Table 2.** The 11 tasks: seven protocols, each with an easy task, four of which also have a paper-only ("hard") task. +**Table 2.** The 11 tasks: seven protocols, each with an easy task, four of which also have a paper-only task. -| Protocol | Source | Easy task | Hard task | +| Protocol | Source | Easy task | Paper-only task | |---|---|---|---| | 100 µL from a reservoir to wells A1 to A12 | handwritten | `a1-a12-100ul` | – | | Split 200 µL into two 100 µL wells | handwritten | `split-200ul-two-wells` | – | @@ -188,7 +226,7 @@ covers 48 papers. ### 3.2 What the agent sees -The agent sees the instruction, `/data` (the paper on hard tasks) and a planted wrong answer key at +The agent sees the instruction, `/data` (the paper on paper-only tasks) and a planted wrong answer key at `/app/solution_hint.py`. The ground truth (`ir.json`, `deck.json`, `checks.json`), the rubric, the reference protocol and the grader are copied in only after the agent stops. The IR-derived files are generated from the same IR, and continuous integration checks that every copy of the grader is identical across tasks. The APEX paper is not @@ -197,7 +235,7 @@ redistributable, so its task downloads a pinned version at image build and verif ## 4 Verifier The verifier runs six layers in order. (1) A **lint** gate rejects imports, file access, dunder attributes and other -reaches into simulator internals. (2) Ten **reward-hacking traps** catch a copied answer key, the reference's canary +reaches into simulator internals. (2) Nine **reward-hacking traps** catch a copied answer key, the reference's canary string, text addressed to the grader, outputs written before grading, a tampered simulator, simulator detection, network or shell access, custom labware definitions and modified task files; any trip scores 0. (3) The **Opentrons 7.5 simulator** must complete. (4) **Deterministic checks** compare the simulated run with the ground truth: on the @@ -206,14 +244,15 @@ physical safety rules (a tip before every aspiration, no overdispense, no aspira no cross-contamination); on RNA extraction, 18 run-log checks of volumes, order, incubation, magnet and drying times, recovery, temperature, tips and reservoir capacity. (5) A **language-model judge** (Claude Sonnet 5.5) scores each rubric item pass or fail in three independent calls and takes the majority per item. Easy tasks are judged against the task -text and hard tasks against the paper; the judge sees the check results, the reference protocol and the agent's code. +text and paper-only tasks against the paper; the judge sees the check results, the reference protocol and the agent's code. (6) A failed **critical** check (deck, cross-contamination, pipetting without a tip, aspirating from an empty well, overdispensing, and for RNA sample count, step order, supernatant removal, washes, recovery and reservoir capacity) caps -the reward at 0.3. On hard tasks end-state checks are evidence for the judge rather than critical, because a paper can +the reward at 0.3. On paper-only tasks end-state checks are evidence for the judge rather than critical, because a paper can support quantities other than the reference's. Every task has three core rubric items worth 25% each: `robot_practice`, `tips_and_contamination` and an all-or-nothing -`fidelity_to_task` (easy) or `fidelity_to_paper` (hard). Its task-specific items share the remaining 25%. +`fidelity_to_task` (easy) or `fidelity_to_paper` (paper-only), which also fails a comment that claims an action the +code does not perform. Its task-specific items share the remaining 25%. ## 5 Does the verifier grade correctly? @@ -232,29 +271,12 @@ and the loaded labware unchanged is reported as not applicable rather than score attack does; the best-scoring attack gets 0.47, and every attack on the grader scores 0. Outlined: halving every volume on colony-PCR-hard gives the paper's own 10 µL reaction, a valid protocol that must score 1.](../docs/preprint/figures/grader_validation.png) -**Model runs taught the verifier.** We read every failed check and rubric item from the runs in Section 7 and confirmed -each against the protocol. Eight faults turned up (Table 3), two of them in the open-weight models' runs. A second check, `tests/test_hard_tasks.py`, requires every -volume a paper-only task grades deterministically to be in its paper or brief, or to follow from quoted facts by -arithmetic the test spells out; it found two more. Each fix has a regression test. - -
- -**Table 3.** Grader faults found by reading the model runs (rows 1-6 and 9-10) and by the paper-only audit (rows 7-8). - -| Fault | Found in | Fix | -|---|---|---| -| Labware on a module is named differently at API ≥ 2.14; a correct protocol failed its deck and end-state checks | Opus, ecoli-hard (0.30, really 0.75) | Both naming schemes read; controls run at API 2.13, 2.14 and 2.15 | -| A tip that mixed in one well and moved to the next was not flagged | The judge, on the AMPure reference | Checker tracks what a tip carries; references regenerated | -| No reservoir-volume check: 16 mL drawn from a 15 mL well passed | Sonnet, RNA easy | New critical check of net volume per reservoir column | -| On the easy RNA task, whose brief says 80 µL, the recovery check accepted 70-100 µL | Identical recoveries judged pass and fail | New 70-90 µL check, easy task only | -| One judge call scored identical recipes differently | Colony-PCR-hard | Three calls, majority per item; primer volume left to the agent, as the deck gives no concentration | -| End-state details truncated to 160 characters | Every colony-hard report | Full expected and measured values | -| RNA-hard's rubric required 80 µL recovered; the paper says only "collect the supernatant" | Sonnet, GPT marked down | Any full recovery passes on the paper-only task | -| Colony-PCR-hard graded the easy task's 20 µL reaction; the paper's is 10 µL, with no primer concentration on the deck | Every model "failed" it | No exact volumes: every well must get all three inputs, alike, 10-25 µL | -| The lint gate refused Opentrons' documented `pipette.tip_racks = [...]` | DeepSeek, a correct protocol scored 0 | Documented pipette settings allowed; patching classes or modules still refused | -| Mixing a source well before drawing from it (resuspending a colony) was flagged as contamination | DeepSeek, colony-hard (0.30, really 1.00) | Only mixing in a destination makes a tip carry | - -
+**Model runs taught the verifier.** Validation also ran in the other direction. We read every failed check and rubric +item from the runs in Section 7 and confirmed each against the protocol. This found eight grader faults, in both +directions: correct protocols marked down (a lint rule that refused a documented pipette setting) and wrong ones passed +(no check on how much a reservoir well can give). A second check, `tests/test_hard_tasks.py`, requires every volume a +paper-only task grades deterministically to be in its paper or brief, or to follow from quoted facts by arithmetic the +test spells out; it found two more. All ten are fixed, each with a regression test (Appendix A). **Is the paper-only level valid?** After the two fixes, all four paper-only tasks pass the audit. Heat-shock-hard has its own ground truth from the APEX paper: temperatures and times in the text, volumes in a figure caption. Golden-Gate- @@ -284,7 +306,7 @@ tasks; below, paper-only tasks.](../docs/preprint/figures/run_rewards.png)
-**Table 4.** Summary. Refused tasks are not scored; the first row is the headline. +**Table 3.** Summary. Refused tasks are not scored; the first row is the headline. | | Sonnet 5.5 | Opus 5.5 | Fable 5.1 | GPT-6.1 Sol | Qwen3.8-2.4T | DeepSeek V4 Pro | |---|:---:|:---:|:---:|:---:|:---:|:---:| @@ -295,29 +317,38 @@ tasks; below, paper-only tasks.](../docs/preprint/figures/run_rewards.png) | `fidelity_to_paper` passed | 2/4 | 2/3 | 2/2 | 1/4 | 0/4 | 2/4 | | Critical failures (capped at 0.30) | 1 | 0 | 0 | 0 | 3 | 3 | | Refused, not scored | 0 | 2 | 3 | 0 | 0 | 0 | -| Agent cost (USD) | **1.25** | 3.52 | 6.21 | 1.49 | 2.83 | 2.53 | +| Agent cost, the 8 tasks all answered (USD) | **0.75** | 2.67 | 5.53 | 0.97 | 2.19 | 1.89 | +| Agent cost, every trial run (USD) | **1.25** | 3.52 | 6.21 | 1.49 | 2.83 | 2.53 |
**Easy tasks are nearly solved.** Four of the seven easy tasks gave every model full marks, and GPT-6.1 Sol and Opus -were perfect on every easy task they answered. The models separate on RNA extraction and on the hard tasks, where 12 of +were perfect on every easy task they answered. The models separate on RNA extraction and on the paper-only tasks, where 12 of 21 answered trials failed `fidelity_to_paper`. The two open-weight models trail on both levels. **Refused tasks are not scored.** Anthropic's biosecurity safeguard declined both Golden Gate prompts for Opus and -Fable and the paper-only E. coli transformation prompt for Fable. These are teaching-lab procedures, so the refusals are -false positives; we report them as they happened and did not rephrase prompts. A refusal is the provider's policy, not +Fable and the paper-only E. coli transformation prompt for Fable. These are routine molecular-biology procedures, but +they produce genetically modified organisms, and the same steps could assemble or transform hazardous sequences, so we +do not call the refusals false positives. They are inconsistent, though: Opus answered the paper-only transformation +prompt that Fable refused, and both answered the easy one. With one attempt each, we cannot tell whether the safeguard +is non-deterministic or differs between models. We report refusals as they happened and did not rephrase prompts. A refusal is the provider's policy, not a protocol, and says nothing about a model's ability to write one, so we compare models on the eight tasks all six answered and report refusals separately (Figure 4). Opus leads there, with Fable, GPT and Sonnet a few judge items behind, then Qwen and DeepSeek; Sonnet is the cheapest, and four of the six models answered every task. ABC-Bench reports refusals on its dual-use screening-evasion task, where the tested Anthropic and OpenAI frontier models refused every sample -[@liu2026abcbench]; ours fall on benign tasks. +[@liu2026abcbench]; ours fall on routine cloning and transformation. ![**Figure 4.** (a) Mean reward over the eight tasks all six models answered (the headline), over every task each -model answered, and over the easy and paper-only tasks it answered. (b) Agent cost for the tasks each model answered -against its headline score.](../docs/preprint/figures/run_means_cost.png) - -**The mechanical layers are nearly solved; the signal is in the judge.** No model crashed the simulator, tripped a -trap or broke the lint gate (Figure 5). The closed models' only physical-safety failure is Sonnet's reservoir overdraw; +model answered, and over the easy and paper-only tasks it answered. (b) Agent cost for the same eight tasks against +the headline score.](../docs/preprint/figures/run_means_cost.png) + +**The mechanical layers are nearly solved; fidelity is not.** No model crashed the simulator, tripped a trap or broke +the lint gate (Figure 5). That is partly the prompt: every easy task's instruction tells the agent to run +`opentrons_simulate` and requires the protocol to simulate without errors, and the agent can run it in the sandbox. +The paper-only instructions do not say this, and every paper-only protocol also ran, but we have not tested agents +without a simulator to hand. Most other points are lost on `fidelity_to_paper`, which asks whether the protocol is the +paper's method, with every step present and in order. It is the item that matters most: a protocol that runs safely +but departs from the paper is not a usable protocol. The closed models' only physical-safety failure is Sonnet's reservoir overdraw; Qwen and DeepSeek overdraw the same reservoir and add the run's only cross-contaminations. End-state misses are GPT's and Qwen's Golden-Gate-hard plates. @@ -331,17 +362,21 @@ Golden Gate. *Overdrawing a reservoir* (Sonnet, Qwen, DeepSeek): six sample colu onto four ethanol wells draw 16 mL from a 15 mL well. *One tip from the reaction back to the stock* (Qwen on both Golden Gate tasks, DeepSeek on AMPure and Golden-Gate-hard): `transfer(..., new_tip='once', mix_after=...)` mixes in each reaction and returns the same tip to the enzyme or bead stock, carrying every reaction into it. *Wrong metadata*: Fable credits the RNA paper to the wrong -authors. Two choices that looked like errors are not: recovering the whole 100 µL eluate on RNA-hard and building the -paper's 10 µL colony-PCR reaction both follow the paper, and every trial graded before the audit has been re-judged. +authors. Building the paper's 10 µL colony-PCR reaction, which the grader once marked down, follows the paper, and every +affected trial has been re-judged. Recovering the whole 100 µL of eluate on RNA-hard, as Sonnet, Opus and GPT do, is +accepted by the grader because the paper says only "collect the supernatant", but it is poor OT-2 practice: a person can +steer the tip around the bead pellet, while the robot works blind from its calibration and cannot take the full volume +without disturbing the beads. The authors' own script takes 80 µL. -**One attempt is noisy, and the cloud is faster.** Qwen run a second time on Modal, everything else unchanged, scored -0.805 against 0.728 locally; four tasks changed, by up to 0.70 (RNA extraction 0.30 to 1.00). Gaps of under about 0.1 -between models are within this noise. With all 11 tasks in parallel Modal finished in 31.9 minutes against 54.7 for local -Docker two at a time, despite about 1.5 minutes of image build per sandbox; the wall clock is then the slowest trial, and -DeepSeek, without a slow trial, finished all 11 in 12 minutes. +**One attempt is noisy.** Qwen run a second time, everything else unchanged (on Modal rather than local Docker; +Appendix B), scored 0.805 against 0.728; four tasks changed, by up to 0.70 (RNA extraction 0.30 to 1.00). Part of the +size of these swings comes from the scoring: one failed critical check caps a trial at 0.30, while a mistake no critical +check catches may cost a single rubric item. One attempt per cell is not enough to rank models whose scores are close. ## 8 Discussion and limitations +Text2WetLab sits between the benchmarks that grade protocol knowledge as text and the systems that generate robot code. Knowledge benchmarks such as LAB-Bench [@laurent2024labbench], BioLP-bench [@ivanov2024biolpbench], BioProBench [@liu2025bioprobench] and BenchBench-Protocol [@sivakumar2026benchbench] show whether a model understands a protocol; code systems and their benchmarks, such as LabscriptAI [@gao2025labscriptai], ProtoPilot [@jiang2026protopilot], ABC-Bench [@liu2026abcbench] and AutoLabs [@panapitiya2026autolabs], show whether generated code runs and resembles an expert's. Text2WetLab measures the step between them: an agent reading a paper, and a check, well by well, of whether the robot would do what the paper describes, by a grader that is itself tested against code written to fail or to cheat. It complements AEGIS [@setty2026aegis], LabGuard [@yang2026labguard] and the lab-safety benchmarks [@zhou2026labsafety; @sun2026labshield], which check protocols, actions or knowledge they are given rather than measuring the agents that write protocols. + **The paper is the hard part.** Easy tasks saturate; the paper-only tasks separate models, and their dominant failure is inventing steps or quantities. GPT-6.1 Sol, perfect on easy tasks, failed `fidelity_to_paper` on three of the four paper-only ones, and Qwen on all four. The paper-only level is the one to grow, and each new task must pass the audit. @@ -352,15 +387,35 @@ Benchmarks that grade generated laboratory code should publish their graded arte **Judge noise is real.** Three calls per protocol disagreed on 9 of 380 items across the run, and single calls had scored identical recipes differently. Majority voting absorbs this, but all signal still comes from one judge, a Claude model -that also judges a non-Claude model. A second judge from another provider, as AEGIS does with five backends -[@setty2026aegis], would show whether that matters. +that also judges a non-Claude model. Re-judging the run with a judge from another provider, as AEGIS does with five backends +[@setty2026aegis], is the next step. **Ground truth comes from the easy task.** Three of the four paper-only tasks reuse their easy task's ground truth, which is fair only where the paper fixes the same quantities. The audit now enforces that; where the paper fixes less, as in colony-PCR-hard, the checks fall back to what it does fix. -**Scope.** One robot (OT-2), one simulator, one agent harness, six models, one attempt per cell (one model repeated). Repeated attempts for every model, -wet-lab execution of the generated protocols and non-Opentrons instruments are future work. +**One attempt is not enough.** We have not run enough repeats to say which gaps between models are meaningful. +Repeated attempts would give confidence intervals and significance tests, and are the next run. + +**One harness, one prompt.** Every model runs inside Claude Code, which Anthropic's models are likely tuned for, so the +comparison may favour them; running the tasks without a harness, or in each provider's own agent, would measure this. +The easy-task instructions also tell the agent to run the simulator. We have not compared instructions without this, or +with more guidance against common pitfalls, so the simulator pass rate is that of a prompted agent with a simulator, not +of the model alone. + +**Fixed decks and published code.** Every task fixes the deck so the grader can find labware by label; in practice, +choosing the layout and labware is part of the job, and a task that leaves it to the agent needs a grader that matches +labware by role. The four paper-based protocols come from papers whose authors published robot code. That code may be in the models' training +data, and authors who publish code may also describe their procedures more completely than most; tasks from +unpublished protocols, from collaborating labs or written for the benchmark, would test both. + +**Full recovery from beads.** The paper-only RNA rubric accepts recovering the whole 100 µL of eluate because the paper +gives no volume, though an OT-2 cannot do this without disturbing the beads. `robot_practice` should fail it. + +**Scope.** One robot (OT-2), one simulator, one agent harness, six models, one attempt per cell (one model repeated). +Wet-lab execution of the generated protocols and non-Opentrons instruments are future work. + +**What it enables, and what comes next.** The verifier is a reward signal as well as a score: with its traps and adversarial tests it could grade reinforcement-learning rollouts for protocol-writing agents without being gamed. The paper-only tasks are a test bed for protocol-extraction systems such as ProtoAct [@liu2026protoact] and AutoLabs [@panapitiya2026autolabs], scored on the robot's end state rather than on text. Next: repeated attempts with confidence intervals; a non-Claude judge; the same tasks without a harness and with the prompt varied; tasks where the agent chooses the deck and labware; protocols that were never published; other instruments through PyLabRobot [@wierenga2023pylabrobot]; and running the best generated protocols at the bench. ## 9 Conclusion @@ -377,4 +432,32 @@ Tasks, verifier, reference solutions, adversarial suite, every graded protocol a produce every table and figure are at under the MIT licence. Paper text and third-party code keep their own licences; only CC BY and CC0 paper text is redistributed. +## Appendix A: Grader faults found and fixed + +
+ +**Table A1.** Grader faults found by reading the model runs (rows 1-6 and 9-10) and by the paper-only audit (rows 7-8). +Each has a regression test. + +| Fault | Found in | Fix | +|---|---|---| +| Labware on a module is named differently at API ≥ 2.14; a correct protocol failed its deck and end-state checks | Opus, ecoli-hard (0.30, really 0.75) | Both naming schemes read; controls run at API 2.13, 2.14 and 2.15 | +| A tip that mixed in one well and moved to the next was not flagged | The judge, on the AMPure reference | Checker tracks what a tip carries; references regenerated | +| No reservoir-volume check: 16 mL drawn from a 15 mL well passed | Sonnet, RNA easy | New critical check of net volume per reservoir column | +| On the easy RNA task, whose brief says 80 µL, the recovery check accepted 70-100 µL | Identical recoveries judged pass and fail | New 70-90 µL check, easy task only | +| One judge call scored identical recipes differently | Colony-PCR-hard | Three calls, majority per item; primer volume left to the agent, as the deck gives no concentration | +| End-state details truncated to 160 characters | Every colony-hard report | Full expected and measured values | +| RNA-hard's rubric required 80 µL recovered; the paper says only "collect the supernatant" | Sonnet, GPT marked down | Any full recovery passes on the paper-only task | +| Colony-PCR-hard graded the easy task's 20 µL reaction; the paper's is 10 µL, with no primer concentration on the deck | Every model "failed" it | No exact volumes: every well must get all three inputs, alike, 10-25 µL | +| The lint gate refused Opentrons' documented `pipette.tip_racks = [...]` | DeepSeek, a correct protocol scored 0 | Documented pipette settings allowed; patching classes or modules still refused | +| Mixing a source well before drawing from it (resuspending a colony) was flagged as contamination | DeepSeek, colony-hard (0.30, really 1.00) | Only mixing in a destination makes a tip carry | + +
+ +## Appendix B: Local Docker or Modal + +With all 11 tasks in parallel, Modal finished Qwen's run in 31.9 minutes against 54.7 for local Docker two at a time, +despite about 1.5 minutes of image build per sandbox; the wall clock is then the slowest trial (a 28-minute agent +session on RNA extraction). DeepSeek, without a slow trial, finished all 11 tasks on Modal in 12 minutes. + ## References diff --git a/manuscript/main.tex b/manuscript/main.tex new file mode 100644 index 0000000..4c6203b --- /dev/null +++ b/manuscript/main.tex @@ -0,0 +1,966 @@ +% Options for packages loaded elsewhere +\PassOptionsToPackage{unicode}{hyperref} +\PassOptionsToPackage{hyphens}{url} +\documentclass[ +]{article} +\usepackage{xcolor} +\usepackage{amsmath,amssymb} +\setcounter{secnumdepth}{-\maxdimen} % remove section numbering +\usepackage{iftex} +\ifPDFTeX + \usepackage[T1]{fontenc} + \usepackage[utf8]{inputenc} + \usepackage{textcomp} % provide euro and other symbols +\else % if luatex or xetex + \usepackage{unicode-math} % this also loads fontspec + \defaultfontfeatures{Scale=MatchLowercase} + \defaultfontfeatures[\rmfamily]{Ligatures=TeX,Scale=1} +\fi +\usepackage{lmodern} +\ifPDFTeX\else + % xetex/luatex font selection +\fi +% Use upquote if available, for straight quotes in verbatim environments +\IfFileExists{upquote.sty}{\usepackage{upquote}}{} +\IfFileExists{microtype.sty}{% use microtype if available + \usepackage[]{microtype} + \UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts +}{} +\makeatletter +\@ifundefined{KOMAClassName}{% if non-KOMA class + \IfFileExists{parskip.sty}{% + \usepackage{parskip} + }{% else + \setlength{\parindent}{0pt} + \setlength{\parskip}{6pt plus 2pt minus 1pt}} +}{% if KOMA class + \KOMAoptions{parskip=half}} +\makeatother +\usepackage{longtable,booktabs,array} +\newcounter{none} % for unnumbered tables +\usepackage{calc} % for calculating minipage widths +% Correct order of tables after \paragraph or \subparagraph +\usepackage{etoolbox} +\makeatletter +\patchcmd\longtable{\par}{\if@noskipsec\mbox{}\fi\par}{}{} +\makeatother +% Allow footnotes in longtable head/foot +\IfFileExists{footnotehyper.sty}{\usepackage{footnotehyper}}{\usepackage{footnote}} +\makesavenoteenv{longtable} +\usepackage{graphicx} +\makeatletter +\newsavebox\pandoc@box +\newcommand*\pandocbounded[1]{% scales image to fit in text height/width + \sbox\pandoc@box{#1}% + \Gscale@div\@tempa{\textheight}{\dimexpr\ht\pandoc@box+\dp\pandoc@box\relax}% + \Gscale@div\@tempb{\linewidth}{\wd\pandoc@box}% + \ifdim\@tempb\p@<\@tempa\p@\let\@tempa\@tempb\fi% select the smaller of both + \ifdim\@tempa\p@<\p@\scalebox{\@tempa}{\usebox\pandoc@box}% + \else\usebox{\pandoc@box}% + \fi% +} +% Set default figure placement to htbp +\def\fps@figure{htbp} +\makeatother +\setlength{\emergencystretch}{3em} % prevent overfull lines +\providecommand{\tightlist}{% + \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}} +\usepackage[]{natbib} +\bibliographystyle{plainnat} +\usepackage{bookmark} +\IfFileExists{xurl.sty}{\usepackage{xurl}}{} % add URL line breaks if available +\urlstyle{same} +\hypersetup{ + pdftitle={Text2WetLab: Benchmarking LLM Agents on Turning Lab Protocols and Papers into Robot Code}, + pdfauthor={Evan O'Leary; Mohammed Alshehri; Laurence Legon}, + hidelinks, + pdfcreator={LaTeX via pandoc}} + +\title{Text2WetLab: Benchmarking LLM Agents on Turning Lab Protocols and +Papers into Robot Code} +\author{Evan O'Leary \and Mohammed Alshehri \and Laurence Legon} +\date{October 2026 (preprint draft)} + +\begin{document} +\maketitle + +\subsection{Abstract}\label{abstract} + +Language models can write Opentrons OT-2 Python that runs in the +simulator, but a protocol that runs can still ruin an experiment: it can +mix fragile cells, carry beads into the eluate, or draw more from a +reservoir than it holds. We present \textbf{Text2WetLab}, a benchmark of +11 tasks: 7 \emph{easy} tasks that give every step, and 4 +\emph{paper-only} tasks that give only a goal and the source paper. A +layered verifier grades each protocol with a code lint, nine +reward-hacking traps, the Opentrons simulator, deterministic checks of +the robot's end state against a ground truth, and a language-model judge +scoring a pass/fail rubric. Every reference solution passes the +deterministic checks, and none of 151 deliberately broken or cheating +protocols scores above 0.47. We ran six models from four providers in +one agent harness, scoring only the tasks each model answered. On the +eight tasks all six answered, mean reward ranges from 1.000 (Claude Opus +5.5) to 0.755 (DeepSeek V4 Pro), and no model failed the simulator or a +trap. Easy tasks are close to solved; the paper-only tasks separate the +models, and the commonest failure is adding steps or quantities the +paper does not support. A repeat run of one model changed single-task +scores by up to 0.70, so close scores cannot be ranked from one attempt. + +\subsection{1 Introduction}\label{introduction} + +Automating a published protocol on a liquid-handling robot is a +translation problem with two failure modes. The first is mechanical: +code that crashes, aspirates more than a pipette holds, or runs out of +tips. Vendor simulators catch these. The second is biological: a +protocol that runs perfectly and still ruins the experiment because it +mixes fragile cells, carries beads into the eluate, or adds reagents in +the wrong order. Nothing in the robot's API marks these as errors, and a +silent failure produces data rather than an exception +\citep{setty2026aegis}. + +Language models have written OT-2 scripts from goal-oriented +instructions since GPT-4 \citep{inagaki2023llmrobotic}, and agents now +write such code in research systems +\citep{boiko2023coscientist, jiang2026protopilot, gao2025labscriptai, panapitiya2026autolabs} +and biosecurity evaluations \citep{liu2026abcbench}. Benchmarks of +protocol knowledge grade text: multiple-choice answers, pseudocode, +error finding or rewritten protocols +\citep{laurent2024labbench, odonoghue2023bioplanner, ivanov2024biolpbench, sivakumar2026benchbench}. +Benchmarks of protocol-to-code systems score generated scripts mainly by +whether they run in simulation or pass device-level checks, with a few +protocols tested at the bench +\citep{gao2025labscriptai, jiang2026protopilot, liu2026abcbench}. AEGIS, +closest in intent, catches code that is valid but breaks the assay, with +assay rules and a language-model checker, but it validates protocols it +is given rather than evaluating the agents that write them +\citep{setty2026aegis}. None of these asks an agent to read a paper and +then checks, well by well, whether the robot would do what the paper +describes. + +Text2WetLab does. Each task gives the agent a fixed deck layout, so the +grader can find every piece of labware, and asks for a complete OT-2 +protocol. Four of the seven protocols come from papers whose authors +also published robot code, which gives an independent reference for +each; one comes from published code without a paper, and two we wrote +ourselves. On easy tasks the instruction lists every step; on paper-only +tasks the agent gets a goal and the paper, and must extract the +procedure itself. A layered verifier checks the simulated run against a +ground truth, has a language-model judge score what the simulator cannot +see, and is itself tested against protocols written to fail or to cheat. + +\textbf{Contributions.} + +\begin{enumerate} +\def\labelenumi{\arabic{enumi}.} +\tightlist +\item + Eleven Harbor tasks \citep{harbor2026} at two levels. Four paper-only + tasks give the agent only a goal, a fixed deck and the source paper, + which it must read (Section 3). +\item + A layered verifier: deterministic checks of the simulated run against + a ground-truth protocol representation, a 75/25 core/task rubric + scored by a three-vote judge, and nine reward-hacking traps (Section + 4). +\item + A validation of that verifier against reference solutions and 151 + adversarial protocols, an audit that every quantity a paper-only task + grades is in its paper or brief, and ten grader faults found by + reading model runs, each fixed with a regression test (Section 5). +\item + A comparison of six models from four providers, two of them + open-weight, in one agent harness, broken down by task, risk and + rubric item, with safety refusals reported separately from capability, + and a repeat run that measures single-attempt noise (Sections 6 and + 7). +\end{enumerate} + +\subsection{2 Related work}\label{related-work} + +Work on language models for wet-lab protocols spans four questions: +whether a model \emph{knows} protocols, whether it can \emph{write +executable robot code} for one, whether such code can be \emph{checked} +for safety before or while it runs, and whether agents can be +\emph{evaluated} without gaming the evaluation. Table 1 sets every work +discussed here against what Text2WetLab covers. + +\subsubsection{2.1 Protocol knowledge and +planning}\label{protocol-knowledge-and-planning} + +LAB-Bench measures practical biology-research skills with over 2,400 +multiple-choice questions, including protocol troubleshooting, +literature and database use, and sequence manipulation +\citep{laurent2024labbench}. BioPlanner introduced BioProt, protocols +paired with pseudocode, and scores a model's ability to reconstruct the +pseudocode from a high-level description and a list of admissible +functions; one generated protocol was run in a laboratory +\citep{odonoghue2023bioplanner}. BioProBench builds 523,784 task +instances from 22,413 human-written protocols and finds that models do +well on comprehension but drop on tasks that need deep reasoning, +quantitative precision and safety awareness \citep{liu2025bioprobench}. +BenchBench-Protocol reconstructs 149 rubric-graded modification tasks +from changes scientists made to published protocols during real work; +the best model reaches 59.2\% of the rubric +\citep{sivakumar2026benchbench}. BioLP-bench plants many harmless +changes and one fatal error in each protocol and asks the model to find +the error; only one model matched human experts +\citep{ivanov2024biolpbench}. These benchmarks grade text. Text2WetLab +grades the code an agent writes by executing it in the instrument's +simulator and comparing the resulting liquid state with a ground truth, +so a quantity is wrong only if the robot would move the wrong volume. + +\subsubsection{2.2 From protocols to robot +code}\label{from-protocols-to-robot-code} + +Inagaki et al.~first showed GPT-4 writing OT-2 scripts from +goal-oriented instructions, with simulator feedback; it struggled on +complex protocols and sometimes worked around errors instead of +implementing the step \citep{inagaki2023llmrobotic}. CLAIRify turns +instructions into the chemistry language XDL, feeding a syntax +verifier's errors back to the model until the plan is valid, and runs +the result on a robot through a task-and-motion planner +\citep{skreta2023clairify}. PyLabRobot gives one Python interface to +Hamilton, Tecan and Opentrons robots, which makes code from a language +model portable across them \citep{wierenga2023pylabrobot}. Coscientist +showed a GPT-4 agent planning chemistry experiments and writing the code +that ran a pipetting robot \citep{boiko2023coscientist}. ProtoCode +fine-tunes language models to turn PCR protocols from the literature +into a machine-readable intermediate representation, and from it into +thermal-cycler files \citep{jiang2024protocode}; Text2WetLab's task +construction uses the same idea, an intermediate representation between +paper and robot, but as ground truth for grading rather than as model +output. CRISPR-GPT \citep{qu2025crisprgpt}, BioMARS +\citep{qiu2025biomars} and PRISM \citep{hsu2026prism} are agent systems +that design experiments and drive instruments, evaluated through case +studies and laboratory runs. + +Five recent systems come with protocol-to-code benchmarks. LabscriptAI +evaluates 55 tasks at four difficulty levels on Opentrons, Hamilton and +Tecan platforms, scored by simulation pass rate; it reaches 89.1\% +against 20-45\% for direct model baselines and 76.3\% for Opentrons' +commercial generator \citep{gao2025labscriptai}. ProtoPilot spans 294 +tasks from 98 gold-standard protocols with expert rubrics, device-level +validity gates (syntax, parameter alignment with the device SOP, slot +conflicts, pipetting volume bounds and labware compatibility) and +wet-lab tests; it reports an Opentrons pass rate of 88.24\% against +32.35\% for OpenTrons-AI \citep{jiang2026protopilot}. ABC-Bench asks +agents, among its three tasks, to write an OT-2 script for a Gibson +assembly from a fixed deck and the kit manual; scripts are checked in +simulation, all tested agents beat the median human expert baseliner, +and scripts from one model assembled DNA correctly in three wet-lab runs +\citep{liu2026abcbench}. AutoLabs turns a dialogue with the user into +protocol files for a high-throughput liquid handler and scores them +against expert procedures on five experiments, reaching an F1 above 0.89 +\citep{panapitiya2026autolabs}. ProtoAct grounds 22 annotated +cell-culture protocols into JSON robot action calls, scored for action +recognition, parameters and sequence, and runs them in simulation and on +a robot \citep{liu2026protoact}. Text2WetLab differs in what it checks +and what it gives the agent. Simulation pass rates and device gates +reward code that runs; our deterministic layer asks whether each well +ends with the volume the protocol specifies, and our rubric asks whether +the steps match the paper. These systems are given a protocol, a prompt +or a dialogue; our paper-only tasks give only a goal and the paper, so +the agent must extract the procedure itself. + +\subsubsection{2.3 Safety: checking protocols before and while they +run}\label{safety-checking-protocols-before-and-while-they-run} + +AEGIS is the closest work in intent \citep{setty2026aegis}. It names the +failure mode Text2WetLab measures, OT-2 protocols that are syntactically +valid but violate assay-specific invariants, and guards against it with +a database of 22 machine-readable assay rules (tip reuse between a PCR +template and a no-template control, dilution direction, missing master +mix) and a language model that reasons over the code, reaching an +adjusted F1 of 0.97 on a 24-protocol benchmark of 11 correct and 13 +bug-injected protocols across five assay families. Its second layer +watches the physical robot for partial dispenses and missing tips. AEGIS +validates protocols it is given; Text2WetLab evaluates agents that write +them. The two are complementary: our verifier's deterministic layer and +rubric play the role of AEGIS's rule database and language-model +checker, but against a per-task ground truth rather than per-assay +rules, and our adversarial suite (Section 5) is the analogue of its +injected bugs. Several of the faults we found by reading model runs, +such as a tip that mixes in one well and moves to the next, or a +reservoir drawn beyond its capacity, are the kind of invariant AEGIS +encodes as rules. LabGuard compiles natural-language laboratory rules +into runtime guards for embodied agents, from 812 annotations of 203 +rules \citep{yang2026labguard}. LabSafety Bench +\citep{zhou2026labsafety} and LABSHIELD \citep{sun2026labshield} test +whether models know laboratory hazards, with questions and multimodal +scenarios grounded in OSHA and GHS standards; no model passes 70\% on +hazard identification in the first. These test safety knowledge or guard +an agent's actions; our physical-safety checks test what the agent's own +protocol does. + +\subsubsection{2.4 Embodied laboratory +robotics}\label{embodied-laboratory-robotics} + +Pipette provides a simulation platform, over 100 editable wet-lab assets +and a 12-task embodied benchmark for learning robot-arm policies, where +vision-language-action models reach 44-72\% success with simulation +augmentation \citep{liu2026pipette}. RoboCulture automates a 15-hour +yeast culture with a general-purpose arm, vision and force feedback +\citep{angers2025roboculture}. WetRobo gives a coding agent a +reproducible robot kit and evaluates the programs it writes on three +manipulation tasks in two laboratories \citep{oikawa2026wetrobo}. These +evaluate motor control; Text2WetLab evaluates the program a liquid +handler runs, and takes the robot's motion as given. A recent survey +places both strands in the longer history of AI scientists +\citep{king2026aiscientists}. + +\subsubsection{2.5 Agent benchmarks, code benchmarks and reward +hacking}\label{agent-benchmarks-code-benchmarks-and-reward-hacking} + +Text2WetLab is built in the Harbor task format \citep{harbor2026} used +by Terminal-Bench, whose 89 hard command-line tasks each pair a +container environment with a human-written solution and tests +\citep{merrill2026terminalbench}. Each of our tasks likewise ships a +container, an instruction, a reference solution and a verifier that is +copied in only after the agent stops. BioCoder benchmarks bioinformatics +code generation with fuzz tests \citep{tang2023biocoder}. Agents that +can read a grader can game it; Hack-Verifiable Terminal Bench embeds +detectable hacks in tasks to measure how often frontier models take them +\citep{roth2026hvtb}. Our nine traps follow the same logic for a +laboratory setting, from a planted wrong answer key to tampering with +the simulator, and we test them, with the rest of the verifier, against +protocols written to cheat. + +\textbf{Table 1.} What each work covers, against Text2WetLab. ``Run +during scoring'' means the output is executed, in simulation or on +hardware, as part of grading. ``Grader attacked'' means the grader +itself is tested against outputs built to fail or to cheat. + +{\def\LTcaptype{none} % do not increment counter +\begin{longtable}[]{@{} + >{\raggedright\arraybackslash}p{(\linewidth - 14\tabcolsep) * \real{0.1250}} + >{\raggedright\arraybackslash}p{(\linewidth - 14\tabcolsep) * \real{0.1250}} + >{\raggedright\arraybackslash}p{(\linewidth - 14\tabcolsep) * \real{0.1250}} + >{\raggedright\arraybackslash}p{(\linewidth - 14\tabcolsep) * \real{0.1250}} + >{\raggedright\arraybackslash}p{(\linewidth - 14\tabcolsep) * \real{0.1250}} + >{\raggedright\arraybackslash}p{(\linewidth - 14\tabcolsep) * \real{0.1250}} + >{\raggedright\arraybackslash}p{(\linewidth - 14\tabcolsep) * \real{0.1250}} + >{\raggedright\arraybackslash}p{(\linewidth - 14\tabcolsep) * \real{0.1250}}@{}} +\toprule\noalign{} +\begin{minipage}[b]{\linewidth}\raggedright +Work +\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright +What is scored +\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright +Run during scoring +\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright +The agent works from +\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright +Graded against +\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright +Physical-safety checks +\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright +Grader attacked +\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright +Size +\end{minipage} \\ +\midrule\noalign{} +\endhead +\bottomrule\noalign{} +\endlastfoot +LAB-Bench \citep{laurent2024labbench} & Multiple-choice answers & No & +Questions & Answer key & -- & -- & \textgreater2,400 questions \\ +BioLP-bench \citep{ivanov2024biolpbench} & The one error that breaks a +protocol & No & A protocol with planted errors & Planted error & -- & -- +& Lab protocols \\ +BioPlanner \citep{odonoghue2023bioplanner} & Pseudocode & One protocol +in the lab & Description and admissible functions & Reference pseudocode +& -- & -- & Protocol dataset \\ +BioProBench \citep{liu2025bioprobench} & Text answers & No & Protocols & +Task metrics & -- & -- & 523,784 instances \\ +BenchBench-Protocol \citep{sivakumar2026benchbench} & Modified protocol +text & No & A protocol and a change request & Expert rubric & -- & -- & +149 tasks \\ +LabSafety Bench \citep{zhou2026labsafety} & Answers on hazards & No & +Questions and scenarios & Expert answers & Knowledge only & -- & 765 +questions, 404 scenarios \\ +LABSHIELD \citep{sun2026labshield} & Safety reasoning and plans & No & +Multimodal lab tasks & Standards (OSHA, GHS) & Knowledge only & -- & 164 +tasks \\ +Inagaki et al. \citep{inagaki2023llmrobotic} & OT-2 Python & Simulator & +Goal-oriented instructions & Case studies & -- & -- & Case studies \\ +CLAIRify \citep{skreta2023clairify} & Chemistry plans (XDL) & Real robot +via a planner & Instructions & Syntax verifier & -- & -- & Chemistry +experiments \\ +LabscriptAI \citep{gao2025labscriptai} & Opentrons, Hamilton, Tecan +scripts & Platform simulators & Short prompt & Simulation pass rate & +Biosecurity screening & -- & 55 tasks \\ +ProtoPilot \citep{jiang2026protopilot} & Protocol, SOPs and device code +& Device gates; wet-lab tests & Intent or protocol & Expert rubric and +device gates & Volume bounds, slot conflicts & -- & 294 tasks \\ +ABC-Bench, liquid handling \citep{liu2026abcbench} & OT-2 Gibson +assembly script & Simulator; 3 wet-lab runs & Fixed deck and kit manual +& Simulation checks & -- & -- & 1 of 3 tasks \\ +AutoLabs \citep{panapitiya2026autolabs} & Liquid-handler protocol files +& No & Dialogue with the user & Expert procedures (F1, amount error) & +-- & -- & 5 experiments \\ +ProtoAct \citep{liu2026protoact} & JSON robot action calls & Simulation +and a real robot & Free-form protocols & Annotated actions & -- & -- & +22 protocols \\ +AEGIS \citep{setty2026aegis} & Rule violations in given code & Runtime +monitor on the robot & An OT-2 protocol & Planted bugs (F1) & 22 assay +rules & Validator tested on planted bugs & 24 protocols \\ +LabGuard \citep{yang2026labguard} & Runtime guards from lab rules & +Embodied agents & Natural-language rules & Annotations (F1) & Rules +become guards & -- & 812 annotations \\ +Pipette \citep{liu2026pipette} & Robot-arm policies & Simulation & Task +goals & Task success & -- & -- & 12 tasks \\ +WetRobo \citep{oikawa2026wetrobo} & Robot-arm programs from a coding +agent & Real robots, two labs & Task descriptions & Task success & -- & +-- & 3 tasks \\ +\textbf{Text2WetLab} & OT-2 protocol written by an agent & Opentrons +simulator & Task steps, or a goal and the paper & Every well's end state +against a ground truth; 3-vote rubric & 5 rules, critical cap & 9 traps; +151 attacks & 11 tasks \\ +\end{longtable} +} + +\subsection{3 Benchmark}\label{benchmark} + +\subsubsection{3.1 Tasks}\label{tasks} + +\begin{figure} +\centering +\pandocbounded{\includegraphics[keepaspectratio,alt={Figure 1. Text2WetLab pipeline. (A) Building a task. A language-model pipeline extracts each experiment's liquid handling from the paper into step-by-step instructions and a structured protocol, an intermediate representation (IR) that serves as the ground truth. It never reads the authors' robot code, so that code stays an independent check. (B) Running and grading a task. The agent works in an isolated container and writes an OT-2 Python protocol. Only after it finishes is the verifier copied in. The verifier rejects unsafe code and reward hacking, runs the protocol in the Opentrons simulator, compares the simulated end state with the ground truth, and has a language-model judge score a rubric. A failed critical check caps the reward at 0.3.}]{../docs/figures/fig1_pipeline.png}} +\caption{\textbf{Figure 1.} Text2WetLab pipeline. (A) Building a task. A +language-model pipeline extracts each experiment's liquid handling from +the paper into step-by-step instructions and a structured protocol, an +intermediate representation (IR) that serves as the ground truth. It +never reads the authors' robot code, so that code stays an independent +check. (B) Running and grading a task. The agent works in an isolated +container and writes an OT-2 Python protocol. Only after it finishes is +the verifier copied in. The verifier rejects unsafe code and reward +hacking, runs the protocol in the Opentrons simulator, compares the +simulated end state with the ground truth, and has a language-model +judge score a rubric. A failed critical check caps the reward at 0.3.} +\end{figure} + +Each task fixes the deck, so the grader can locate every labware by its +label, and asks for a complete OT-2 protocol \citep{opentrons2026api}. +Easy tasks give the deck, the starting contents and every step with its +quantity. Paper-only tasks give the deck, the starting contents, a +one-paragraph goal and the paper as text. Seven tasks are easy and four +are paper-only (Table 2): every protocol has an easy task, and the four +with a source paper also have a paper-only one. The paper-only tasks +come from four papers that published OT-2 code: a Golden Gate cloning +and colony-PCR workflow \citep{malci2026slowpoke}, AssemblyTron +\citep{bryant2022assemblytron}, the APEX automated protein-expression +pipeline \citep{kasprzyk2024apex} and a low-cost SARS-CoV-2 RNA +extraction \citep{lazaroperona2021rna}. The source corpus behind the +tasks covers 48 papers and 166 experiments, found by a semantic search +of PubMed Central for Opentrons and liquid-handler papers; the four +paper-only tasks were chosen from them because the authors published +OT-2 code and the paper text can be given to the agent. + +\textbf{Table 2.} The 11 tasks: seven protocols, each with an easy task, +four of which also have a paper-only task. + +{\def\LTcaptype{none} % do not increment counter +\begin{longtable}[]{@{} + >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.2500}} + >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.2500}} + >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.2500}} + >{\raggedright\arraybackslash}p{(\linewidth - 6\tabcolsep) * \real{0.2500}}@{}} +\toprule\noalign{} +\begin{minipage}[b]{\linewidth}\raggedright +Protocol +\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright +Source +\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright +Easy task +\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright +Paper-only task +\end{minipage} \\ +\midrule\noalign{} +\endhead +\bottomrule\noalign{} +\endlastfoot +100 µL from a reservoir to wells A1 to A12 & handwritten & +\texttt{a1-a12-100ul} & -- \\ +Split 200 µL into two 100 µL wells & handwritten & +\texttt{split-200ul-two-wells} & -- \\ +AMPure XP magnetic bead cleanup & published code, no paper & +\texttt{ampure-bead-cleanup} & -- \\ +Colony PCR of 96 colonies & \citep{malci2026slowpoke} & +\texttt{colony-pcr-screening} & \texttt{colony-pcr-screening-hard} \\ +E. coli heat-shock transformation & \citep{kasprzyk2024apex} & +\texttt{ecoli-heat-shock-transformation} & +\texttt{ecoli-heat-shock-transformation-hard} \\ +Golden Gate assembly of four plasmids & \citep{bryant2022assemblytron} & +\texttt{golden-gate-assembly} & \texttt{golden-gate-assembly-hard} \\ +48-sample magnetic-bead RNA extraction & \citep{lazaroperona2021rna} & +\texttt{opentrons-rna-extraction} & +\texttt{opentrons-rna-extraction-hard} \\ +\textbf{Total: 11 tasks} & & \textbf{7} & \textbf{4} \\ +\end{longtable} +} + +\subsubsection{3.2 What the agent sees}\label{what-the-agent-sees} + +The agent sees the instruction, \texttt{/data} (the paper on paper-only +tasks) and a planted wrong answer key at +\texttt{/app/solution\_hint.py}. The ground truth (\texttt{ir.json}, +\texttt{deck.json}, \texttt{checks.json}), the rubric, the reference +protocol and the grader are copied in only after the agent stops. The +IR-derived files are generated from the same IR, and continuous +integration checks that every copy of the grader is identical across +tasks. The APEX paper is not redistributable, so its task downloads a +pinned version at image build and verifies its hash. + +\subsection{4 Verifier}\label{verifier} + +The verifier runs six layers in order. (1) A \textbf{lint} gate rejects +imports, file access, dunder attributes and other reaches into simulator +internals. (2) Nine \textbf{reward-hacking traps} catch a copied answer +key, the reference's canary string, text addressed to the grader, +outputs written before grading, a tampered simulator, simulator +detection, network or shell access, custom labware definitions and +modified task files; any trip scores 0. (3) The \textbf{Opentrons 7.5 +simulator} must complete. (4) \textbf{Deterministic checks} compare the +simulated run with the ground truth: on the nine IR tasks, the right +labware under the right label in the right slot, the end-state volume of +every well, and five physical safety rules (a tip before every +aspiration, no overdispense, no aspiration from an empty well, no tip +left on, no cross-contamination); on RNA extraction, 18 run-log checks +of volumes, order, incubation, magnet and drying times, recovery, +temperature, tips and reservoir capacity. (5) A \textbf{language-model +judge} (Claude Sonnet 5.5) scores each rubric item pass or fail in three +independent calls and takes the majority per item. Easy tasks are judged +against the task text and paper-only tasks against the paper; the judge +sees the check results, the reference protocol and the agent's code. (6) +A failed \textbf{critical} check (deck, cross-contamination, pipetting +without a tip, aspirating from an empty well, overdispensing, and for +RNA sample count, step order, supernatant removal, washes, recovery and +reservoir capacity) caps the reward at 0.3. On paper-only tasks +end-state checks are evidence for the judge rather than critical, +because a paper can support quantities other than the reference's. + +Every task has three core rubric items worth 25\% each: +\texttt{robot\_practice}, \texttt{tips\_and\_contamination} and an +all-or-nothing \texttt{fidelity\_to\_task} (easy) or +\texttt{fidelity\_to\_paper} (paper-only), which also fails a comment +that claims an action the code does not perform. Its task-specific items +share the remaining 25\%. + +\subsection{5 Does the verifier grade +correctly?}\label{does-the-verifier-grade-correctly} + +\textbf{Reference solutions pass.} All 11 reference solutions score +deterministic reward 1.0 and trip no trap. With the judge, the IR +references score 1.0; the two RNA references score 0.69 because the +authors' own script labels the ethanol ``absolute'' rather than 70\% and +has a comment announcing a 30-second pause with no matching delay. + +\textbf{Wrong protocols fail.} We apply 18 kinds of edit to each IR +task's reference: wrong science (a dropped transfer, halved or doubled +volumes, the wrong slot, swapped or missing labels, extra liquid, one +tip shared across sources, a tip left on) and attacks on the grader (an +empty protocol, comments that only claim the work, a forged result +followed by \texttt{SystemExit}, reading the answer key, patching the +log parser, a dunder escape). An edit that leaves the simulated run and +the loaded labware unchanged is reported as not applicable rather than +scored. + +\begin{figure} +\centering +\pandocbounded{\includegraphics[keepaspectratio,alt={Figure 2. Grader validation. Deterministic reward (judge off) for the reference solution at three API levels (left of the line, must be 1) and 151 attacks on nine tasks (right, must be below 1). All 27 controls score 1 and no attack does; the best-scoring attack gets 0.47, and every attack on the grader scores 0. Outlined: halving every volume on colony-PCR-hard gives the paper's own 10 µL reaction, a valid protocol that must score 1.}]{../docs/preprint/figures/grader_validation.png}} +\caption{\textbf{Figure 2.} Grader validation. Deterministic reward +(judge off) for the reference solution at three API levels (left of the +line, must be 1) and 151 attacks on nine tasks (right, must be below 1). +All 27 controls score 1 and no attack does; the best-scoring attack gets +0.47, and every attack on the grader scores 0. Outlined: halving every +volume on colony-PCR-hard gives the paper's own 10 µL reaction, a valid +protocol that must score 1.} +\end{figure} + +\textbf{Model runs taught the verifier.} Validation also ran in the +other direction. We read every failed check and rubric item from the +runs in Section 7 and confirmed each against the protocol. This found +eight grader faults, in both directions: correct protocols marked down +(a lint rule that refused a documented pipette setting) and wrong ones +passed (no check on how much a reservoir well can give). A second check, +\texttt{tests/test\_hard\_tasks.py}, requires every volume a paper-only +task grades deterministically to be in its paper or brief, or to follow +from quoted facts by arithmetic the test spells out; it found two more. +All ten are fixed, each with a regression test (Appendix A). + +\textbf{Is the paper-only level valid?} After the two fixes, all four +paper-only tasks pass the audit. Heat-shock-hard has its own ground +truth from the APEX paper: temperatures and times in the text, volumes +in a figure caption. Golden-Gate- hard's master-mix volumes follow from +the paper's ``25 µL volumes \ldots{} 0.1 µM primers and 0.5 ng \ldots{} +template'', the brief's stock concentrations and the polymerase maker's +standard recipe. RNA-hard grades only the paper's 40/250/250 µL, two 500 +µL washes, 4 min drying, 100 µL elution and the brief's 4 °C plate. +Colony-PCR-hard keeps its deck, tip and contamination checks and, +instead of exact volumes, requires all three inputs in every well, +alike, and a reaction of 10-25 µL, from the paper's ``9 μL of this +master mix'' plus 1 µL colony up to a standard Q5 reaction. Whether the +level is \emph{harder} is a weaker claim: its briefs list no steps and +few volumes, but each model has only 2-4 paper-only trials, so we call +it paper-only rather than hard. + +\subsection{6 Experimental setup}\label{experimental-setup} + +We ran Claude Code 2.1.288 as the agent for every model through +OpenRouter's Anthropic-compatible API, with Harbor 0.23.0 on Docker, 2 +CPUs and 2.5 GB per sandbox, one attempt per task and model (pass@1). +The models were Claude Sonnet 5.5, Opus 5.5 and Fable 5.1 (Anthropic), +GPT-6.1 Sol (OpenAI), and the open-weight Qwen3.8-2.4T-A95B (Alibaba) +and DeepSeek V4 Pro (DeepSeek). DeepSeek ran on Modal with all 11 tasks +in parallel; the others ran locally, two at a time, and Qwen was +repeated on Modal. Harbor pins every model alias and sub-agent of the +harness to the model under test, and we checked that every transcript +contains only that model's responses. The judge was Claude Sonnet 5.5 +throughout, and every trial is graded by the final verifier, earlier +ones regraded from their saved protocols. Agent cost is computed from +token counts at OpenRouter prices, since the harness prices every model +as Claude. Every graded protocol, check, judge vote and cost is released +with the benchmark. + +\subsection{7 Results}\label{results} + +\begin{figure} +\centering +\pandocbounded{\includegraphics[keepaspectratio,alt={Figure 3. Reward on all 11 tasks, one attempt per task and model. Hatched cells are refusals. Above the line, easy tasks; below, paper-only tasks.}]{../docs/preprint/figures/run_rewards.png}} +\caption{\textbf{Figure 3.} Reward on all 11 tasks, one attempt per task +and model. Hatched cells are refusals. Above the line, easy tasks; +below, paper-only tasks.} +\end{figure} + +\textbf{Table 3.} Summary. Refused tasks are not scored; the first row +is the headline. + +{\def\LTcaptype{none} % do not increment counter +\begin{longtable}[]{@{} + >{\raggedright\arraybackslash}p{(\linewidth - 12\tabcolsep) * \real{0.0909}} + >{\centering\arraybackslash}p{(\linewidth - 12\tabcolsep) * \real{0.1515}} + >{\centering\arraybackslash}p{(\linewidth - 12\tabcolsep) * \real{0.1515}} + >{\centering\arraybackslash}p{(\linewidth - 12\tabcolsep) * \real{0.1515}} + >{\centering\arraybackslash}p{(\linewidth - 12\tabcolsep) * \real{0.1515}} + >{\centering\arraybackslash}p{(\linewidth - 12\tabcolsep) * \real{0.1515}} + >{\centering\arraybackslash}p{(\linewidth - 12\tabcolsep) * \real{0.1515}}@{}} +\toprule\noalign{} +\begin{minipage}[b]{\linewidth}\raggedright +\end{minipage} & \begin{minipage}[b]{\linewidth}\centering +Sonnet 5.5 +\end{minipage} & \begin{minipage}[b]{\linewidth}\centering +Opus 5.5 +\end{minipage} & \begin{minipage}[b]{\linewidth}\centering +Fable 5.1 +\end{minipage} & \begin{minipage}[b]{\linewidth}\centering +GPT-6.1 Sol +\end{minipage} & \begin{minipage}[b]{\linewidth}\centering +Qwen3.8-2.4T +\end{minipage} & \begin{minipage}[b]{\linewidth}\centering +DeepSeek V4 Pro +\end{minipage} \\ +\midrule\noalign{} +\endhead +\bottomrule\noalign{} +\endlastfoot +\textbf{Mean over the 8 tasks all answered} & 0.881 & \textbf{1.000} & +0.969 & 0.938 & 0.832 & 0.755 \\ +Mean over all tasks answered & 0.891 (11) & \textbf{0.972} (9) & 0.969 +(8) & 0.909 (11) & 0.728 (11) & 0.735 (11) \\ +Easy tasks, answered & 0.900 & \textbf{1.000} & 0.958 & \textbf{1.000} & +0.800 & 0.800 \\ +Paper-only tasks, answered & 0.875 & 0.917 & \textbf{1.000} & 0.750 & +0.601 & 0.622 \\ +\texttt{fidelity\_to\_paper} passed & 2/4 & 2/3 & 2/2 & 1/4 & 0/4 & +2/4 \\ +Critical failures (capped at 0.30) & 1 & 0 & 0 & 0 & 3 & 3 \\ +Refused, not scored & 0 & 2 & 3 & 0 & 0 & 0 \\ +Agent cost, the 8 tasks all answered (USD) & \textbf{0.75} & 2.67 & 5.53 +& 0.97 & 2.19 & 1.89 \\ +Agent cost, every trial run (USD) & \textbf{1.25} & 3.52 & 6.21 & 1.49 & +2.83 & 2.53 \\ +\end{longtable} +} + +\textbf{Easy tasks are nearly solved.} Four of the seven easy tasks gave +every model full marks, and GPT-6.1 Sol and Opus were perfect on every +easy task they answered. The models separate on RNA extraction and on +the paper-only tasks, where 12 of 21 answered trials failed +\texttt{fidelity\_to\_paper}. The two open-weight models trail on both +levels. + +\textbf{Refused tasks are not scored.} Anthropic's biosecurity safeguard +declined both Golden Gate prompts for Opus and Fable and the paper-only +E. coli transformation prompt for Fable. These are routine +molecular-biology procedures, but they produce genetically modified +organisms, and the same steps could assemble or transform hazardous +sequences, so we do not call the refusals false positives. They are +inconsistent, though: Opus answered the paper-only transformation prompt +that Fable refused, and both answered the easy one. With one attempt +each, we cannot tell whether the safeguard is non-deterministic or +differs between models. We report refusals as they happened and did not +rephrase prompts. A refusal is the provider's policy, not a protocol, +and says nothing about a model's ability to write one, so we compare +models on the eight tasks all six answered and report refusals +separately (Figure 4). Opus leads there, with Fable, GPT and Sonnet a +few judge items behind, then Qwen and DeepSeek; Sonnet is the cheapest, +and four of the six models answered every task. ABC-Bench reports +refusals on its dual-use screening-evasion task, where the tested +Anthropic and OpenAI frontier models refused every sample +\citep{liu2026abcbench}; ours fall on routine cloning and +transformation. + +\begin{figure} +\centering +\pandocbounded{\includegraphics[keepaspectratio,alt={Figure 4. (a) Mean reward over the eight tasks all six models answered (the headline), over every task each model answered, and over the easy and paper-only tasks it answered. (b) Agent cost for the same eight tasks against the headline score.}]{../docs/preprint/figures/run_means_cost.png}} +\caption{\textbf{Figure 4.} (a) Mean reward over the eight tasks all six +models answered (the headline), over every task each model answered, and +over the easy and paper-only tasks it answered. (b) Agent cost for the +same eight tasks against the headline score.} +\end{figure} + +\textbf{The mechanical layers are nearly solved; fidelity is not.} No +model crashed the simulator, tripped a trap or broke the lint gate +(Figure 5). That is partly the prompt: every easy task's instruction +tells the agent to run \texttt{opentrons\_simulate} and requires the +protocol to simulate without errors, and the agent can run it in the +sandbox. The paper-only instructions do not say this, and every +paper-only protocol also ran, but we have not tested agents without a +simulator to hand. Most other points are lost on +\texttt{fidelity\_to\_paper}, which asks whether the protocol is the +paper's method, with every step present and in order. It is the item +that matters most: a protocol that runs safely but departs from the +paper is not a usable protocol. The closed models' only physical-safety +failure is Sonnet's reservoir overdraw; Qwen and DeepSeek overdraw the +same reservoir and add the run's only cross-contaminations. End-state +misses are GPT's and Qwen's Golden-Gate-hard plates. + +\begin{figure} +\centering +\pandocbounded{\includegraphics[keepaspectratio,alt={Figure 5. (a) Deterministic checks passed / run per risk and model; red where any failed. (b) Every rubric item the judge failed: 28 failures in 61 judged trials.}]{../docs/preprint/figures/run_where_lost.png}} +\caption{\textbf{Figure 5.} (a) Deterministic checks passed / run per +risk and model; red where any failed. (b) Every rubric item the judge +failed: 28 failures in 61 judged trials.} +\end{figure} + +\textbf{Error analysis.} Four kinds of error account for every lost +point that the audited verifier upholds. \emph{Inventing steps the paper +does not describe} (every model; Qwen fails \texttt{fidelity\_to\_paper} +on all four paper-only tasks): Sonnet, Opus and GPT pipette-mix +competent cells after adding DNA on ecoli-hard, which harms fragile +cells; GPT adds a manual transfer of all 96 PCR reactions to a second +plate and a 1 µL water ``QC aliquot'' in Golden Gate. \emph{Overdrawing +a reservoir} (Sonnet, Qwen, DeepSeek): six sample columns mapped onto +four ethanol wells draw 16 mL from a 15 mL well. \emph{One tip from the +reaction back to the stock} (Qwen on both Golden Gate tasks, DeepSeek on +AMPure and Golden-Gate-hard): +\texttt{transfer(...,\ new\_tip=\textquotesingle{}once\textquotesingle{},\ mix\_after=...)} +mixes in each reaction and returns the same tip to the enzyme or bead +stock, carrying every reaction into it. \emph{Wrong metadata}: Fable +credits the RNA paper to the wrong authors. Building the paper's 10 µL +colony-PCR reaction, which the grader once marked down, follows the +paper, and every affected trial has been re-judged. Recovering the whole +100 µL of eluate on RNA-hard, as Sonnet, Opus and GPT do, is accepted by +the grader because the paper says only ``collect the supernatant'', but +it is poor OT-2 practice: a person can steer the tip around the bead +pellet, while the robot works blind from its calibration and cannot take +the full volume without disturbing the beads. The authors' own script +takes 80 µL. + +\textbf{One attempt is noisy.} Qwen run a second time, everything else +unchanged (on Modal rather than local Docker; Appendix B), scored 0.805 +against 0.728; four tasks changed, by up to 0.70 (RNA extraction 0.30 to +1.00). Part of the size of these swings comes from the scoring: one +failed critical check caps a trial at 0.30, while a mistake no critical +check catches may cost a single rubric item. One attempt per cell is not +enough to rank models whose scores are close. + +\subsection{8 Discussion and +limitations}\label{discussion-and-limitations} + +Text2WetLab sits between the benchmarks that grade protocol knowledge as +text and the systems that generate robot code. Knowledge benchmarks such +as LAB-Bench \citep{laurent2024labbench}, BioLP-bench +\citep{ivanov2024biolpbench}, BioProBench \citep{liu2025bioprobench} and +BenchBench-Protocol \citep{sivakumar2026benchbench} show whether a model +understands a protocol; code systems and their benchmarks, such as +LabscriptAI \citep{gao2025labscriptai}, ProtoPilot +\citep{jiang2026protopilot}, ABC-Bench \citep{liu2026abcbench} and +AutoLabs \citep{panapitiya2026autolabs}, show whether generated code +runs and resembles an expert's. Text2WetLab measures the step between +them: an agent reading a paper, and a check, well by well, of whether +the robot would do what the paper describes, by a grader that is itself +tested against code written to fail or to cheat. It complements AEGIS +\citep{setty2026aegis}, LabGuard \citep{yang2026labguard} and the +lab-safety benchmarks \citep{zhou2026labsafety, sun2026labshield}, which +check protocols, actions or knowledge they are given rather than +measuring the agents that write protocols. + +\textbf{The paper is the hard part.} Easy tasks saturate; the paper-only +tasks separate models, and their dominant failure is inventing steps or +quantities. GPT-6.1 Sol, perfect on easy tasks, failed +\texttt{fidelity\_to\_paper} on three of the four paper-only ones, and +Qwen on all four. The paper-only level is the one to grow, and each new +task must pass the audit. + +\textbf{Verifiers need adversaries.} Ten grader faults survived +reference solutions, unit tests and an adversarial suite, and surfaced +only when we read what real models wrote or audited the ground truth +against the paper. Three were false negatives that capped or zeroed a +correct protocol, two of them found only when new models wrote code in +styles the earlier models had not. Benchmarks that grade generated +laboratory code should publish their graded artefacts so faults like +these can be found. + +\textbf{Judge noise is real.} Three calls per protocol disagreed on 9 of +380 items across the run, and single calls had scored identical recipes +differently. Majority voting absorbs this, but all signal still comes +from one judge, a Claude model that also judges a non-Claude model. +Re-judging the run with a judge from another provider, as AEGIS does +with five backends \citep{setty2026aegis}, is the next step. + +\textbf{Ground truth comes from the easy task.} Three of the four +paper-only tasks reuse their easy task's ground truth, which is fair +only where the paper fixes the same quantities. The audit now enforces +that; where the paper fixes less, as in colony-PCR-hard, the checks fall +back to what it does fix. + +\textbf{One attempt is not enough.} We have not run enough repeats to +say which gaps between models are meaningful. Repeated attempts would +give confidence intervals and significance tests, and are the next run. + +\textbf{One harness, one prompt.} Every model runs inside Claude Code, +which Anthropic's models are likely tuned for, so the comparison may +favour them; running the tasks without a harness, or in each provider's +own agent, would measure this. The easy-task instructions also tell the +agent to run the simulator. We have not compared instructions without +this, or with more guidance against common pitfalls, so the simulator +pass rate is that of a prompted agent with a simulator, not of the model +alone. + +\textbf{Fixed decks and published code.} Every task fixes the deck so +the grader can find labware by label; in practice, choosing the layout +and labware is part of the job, and a task that leaves it to the agent +needs a grader that matches labware by role. The four paper-based +protocols come from papers whose authors published robot code. That code +may be in the models' training data, and authors who publish code may +also describe their procedures more completely than most; tasks from +unpublished protocols, from collaborating labs or written for the +benchmark, would test both. + +\textbf{Full recovery from beads.} The paper-only RNA rubric accepts +recovering the whole 100 µL of eluate because the paper gives no volume, +though an OT-2 cannot do this without disturbing the beads. +\texttt{robot\_practice} should fail it. + +\textbf{Scope.} One robot (OT-2), one simulator, one agent harness, six +models, one attempt per cell (one model repeated). Wet-lab execution of +the generated protocols and non-Opentrons instruments are future work. + +\textbf{What it enables, and what comes next.} The verifier is a reward +signal as well as a score: with its traps and adversarial tests it could +grade reinforcement-learning rollouts for protocol-writing agents +without being gamed. The paper-only tasks are a test bed for +protocol-extraction systems such as ProtoAct \citep{liu2026protoact} and +AutoLabs \citep{panapitiya2026autolabs}, scored on the robot's end state +rather than on text. Next: repeated attempts with confidence intervals; +a non-Claude judge; the same tasks without a harness and with the prompt +varied; tasks where the agent chooses the deck and labware; protocols +that were never published; other instruments through PyLabRobot +\citep{wierenga2023pylabrobot}; and running the best generated protocols +at the bench. + +\subsection{9 Conclusion}\label{conclusion} + +Text2WetLab measures whether agents turn lab protocols and papers into +robot code that does what the paper describes, not merely code that +runs. Frontier models clear the mechanical layers and nearly solve +step-by-step tasks, but when they must read the paper they add steps and +quantities of their own. Safety refusals on routine molecular biology +are common enough that a benchmark has to keep them out of its scores +and report them on their own. And the grader is itself an artefact to +validate: ours needed ten fixes, found only by reading real model output +and auditing the ground truth against the papers. + +\subsection{Data and code +availability}\label{data-and-code-availability} + +Tasks, verifier, reference solutions, adversarial suite, every graded +protocol and grader record, and the scripts that produce every table and +figure are at \url{https://github.com/PhysicalAIBenchmarks/Text2WetLab} +under the MIT licence. Paper text and third-party code keep their own +licences; only CC BY and CC0 paper text is redistributed. + +\subsection{Appendix A: Grader faults found and +fixed}\label{appendix-a-grader-faults-found-and-fixed} + +\textbf{Table A1.} Grader faults found by reading the model runs (rows +1-6 and 9-10) and by the paper-only audit (rows 7-8). Each has a +regression test. + +{\def\LTcaptype{none} % do not increment counter +\begin{longtable}[]{@{} + >{\raggedright\arraybackslash}p{(\linewidth - 4\tabcolsep) * \real{0.3333}} + >{\raggedright\arraybackslash}p{(\linewidth - 4\tabcolsep) * \real{0.3333}} + >{\raggedright\arraybackslash}p{(\linewidth - 4\tabcolsep) * \real{0.3333}}@{}} +\toprule\noalign{} +\begin{minipage}[b]{\linewidth}\raggedright +Fault +\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright +Found in +\end{minipage} & \begin{minipage}[b]{\linewidth}\raggedright +Fix +\end{minipage} \\ +\midrule\noalign{} +\endhead +\bottomrule\noalign{} +\endlastfoot +Labware on a module is named differently at API ≥ 2.14; a correct +protocol failed its deck and end-state checks & Opus, ecoli-hard (0.30, +really 0.75) & Both naming schemes read; controls run at API 2.13, 2.14 +and 2.15 \\ +A tip that mixed in one well and moved to the next was not flagged & The +judge, on the AMPure reference & Checker tracks what a tip carries; +references regenerated \\ +No reservoir-volume check: 16 mL drawn from a 15 mL well passed & +Sonnet, RNA easy & New critical check of net volume per reservoir +column \\ +On the easy RNA task, whose brief says 80 µL, the recovery check +accepted 70-100 µL & Identical recoveries judged pass and fail & New +70-90 µL check, easy task only \\ +One judge call scored identical recipes differently & Colony-PCR-hard & +Three calls, majority per item; primer volume left to the agent, as the +deck gives no concentration \\ +End-state details truncated to 160 characters & Every colony-hard report +& Full expected and measured values \\ +RNA-hard's rubric required 80 µL recovered; the paper says only +``collect the supernatant'' & Sonnet, GPT marked down & Any full +recovery passes on the paper-only task \\ +Colony-PCR-hard graded the easy task's 20 µL reaction; the paper's is 10 +µL, with no primer concentration on the deck & Every model ``failed'' it +& No exact volumes: every well must get all three inputs, alike, 10-25 +µL \\ +The lint gate refused Opentrons' documented +\texttt{pipette.tip\_racks\ =\ {[}...{]}} & DeepSeek, a correct protocol +scored 0 & Documented pipette settings allowed; patching classes or +modules still refused \\ +Mixing a source well before drawing from it (resuspending a colony) was +flagged as contamination & DeepSeek, colony-hard (0.30, really 1.00) & +Only mixing in a destination makes a tip carry \\ +\end{longtable} +} + +\subsection{Appendix B: Local Docker or +Modal}\label{appendix-b-local-docker-or-modal} + +With all 11 tasks in parallel, Modal finished Qwen's run in 31.9 minutes +against 54.7 for local Docker two at a time, despite about 1.5 minutes +of image build per sandbox; the wall clock is then the slowest trial (a +28-minute agent session on RNA extraction). DeepSeek, without a slow +trial, finished all 11 tasks on Modal in 12 minutes. + +\subsection{References}\label{references} + +\bibliography{refs} + +\end{document} diff --git a/manuscript/refs.bib b/manuscript/refs.bib index 2b14a52..a5e4255 100644 --- a/manuscript/refs.bib +++ b/manuscript/refs.bib @@ -258,3 +258,94 @@ @misc{opentrons2026api note = {opentrons 7.5.0; protocol API levels 2.2 to 2.15 accepted by the tasks}, url = {https://docs.opentrons.com/v2/} } + +@misc{inagaki2023llmrobotic, + title = {{LLMs can generate robotic scripts from goal-oriented instructions in biological laboratory automation}}, + author = {Takashi Inagaki and Akari Kato and Koichi Takahashi and Haruka Ozaki and Genki N. Kanda}, + year = {2023}, + eprint = {2304.10267}, + archiveprefix = {arXiv}, + url = {https://arxiv.org/abs/2304.10267} +} + +@misc{skreta2023clairify, + title = {{Errors are Useful Prompts: Instruction Guided Task Programming with Verifier-Assisted Iterative Prompting}}, + author = {Marta Skreta and Naruki Yoshikawa and Sebastian Arellano-Rubach and Zhi Ji and Lasse Bjørn Kristensen and Kourosh Darvish and Alán Aspuru-Guzik and Florian Shkurti and Animesh Garg}, + year = {2023}, + eprint = {2303.14100}, + archiveprefix = {arXiv}, + url = {https://arxiv.org/abs/2303.14100} +} + +@article{panapitiya2026autolabs, + title = {{AutoLabs: Cognitive Multi-Agent Systems with Self-Correction for Autonomous Chemical Experimentation}}, + author = {Gihan Panapitiya and Emily Saldanha and Heather Job and Olivia Hess}, + journal = {Scientific Reports}, + year = {2026}, + doi = {10.1038/s41598-026-45593-z}, + url = {https://arxiv.org/abs/2509.25651} +} + +@misc{ivanov2024biolpbench, + title = {{BioLP-bench: Measuring understanding of biological lab protocols by large language models}}, + author = {Igor Ivanov}, + year = {2024}, + howpublished = {bioRxiv}, + doi = {10.1101/2024.08.21.608694}, + url = {https://www.biorxiv.org/content/10.1101/2024.08.21.608694v4} +} + +@article{zhou2026labsafety, + title = {{LabSafety Bench: Benchmarking LLMs on Safety Issues in Scientific Labs}}, + author = {Yujun Zhou and Jingdong Yang and Yue Huang and others}, + journal = {Nature Machine Intelligence}, + volume = {8}, + pages = {20--31}, + year = {2026}, + url = {https://arxiv.org/abs/2410.14182} +} + +@misc{sun2026labshield, + title = {{LABSHIELD: A Multimodal Benchmark for Safety-Critical Reasoning and Planning in Scientific Laboratories}}, + author = {Qianpu Sun and Xiaowei Chi and Yuhan Rui and Ying Li and Kuangzhi Ge and Jiajun Li and Sirui Han and Shanghang Zhang}, + year = {2026}, + eprint = {2603.11987}, + archiveprefix = {arXiv}, + url = {https://arxiv.org/abs/2603.11987} +} + +@misc{yang2026labguard, + title = {{LabGuard: Grounding Natural-Language Laboratory Rules into Runtime Guards for Embodied Laboratory Agents}}, + author = {Jingpu Yang and Fengxian Ji and Zhengzhao Lai and Zhexuan Cui and Guangxian Ouyang and Qian Jiang and Fan Zhang and Min Peng and Qianqian Xie and Preslav Nakov and Zhuohan Xie}, + year = {2026}, + eprint = {2606.31045}, + archiveprefix = {arXiv}, + url = {https://arxiv.org/abs/2606.31045} +} + +@misc{liu2026protoact, + title = {{ProtoAct: Turning Wet-Lab Protocols into Embodied Robotic Actions}}, + author = {Zhe Liu and others}, + year = {2026}, + eprint = {2608.01690}, + archiveprefix = {arXiv}, + url = {https://arxiv.org/abs/2608.01690} +} + +@misc{oikawa2026wetrobo, + title = {{WetRobo: A Reproducible Robot Kit for Coding Agents in Biological Laboratories}}, + author = {Yuna Oikawa and others}, + year = {2026}, + eprint = {2609.18435}, + archiveprefix = {arXiv}, + url = {https://arxiv.org/abs/2609.18435} +} + +@misc{wierenga2023pylabrobot, + title = {{PyLabRobot: An Open-Source, Hardware Agnostic Interface for Liquid-Handling Robots and Accessories}}, + author = {Rick P. Wierenga and Stefan Golas and Wilson Ho and Connor Coley and Kevin M. Esvelt}, + year = {2023}, + howpublished = {bioRxiv}, + doi = {10.1101/2023.07.10.547733}, + url = {https://www.biorxiv.org/content/10.1101/2023.07.10.547733v1} +} diff --git a/paper/main.tex b/paper/main.tex deleted file mode 100644 index 47601c9..0000000 --- a/paper/main.tex +++ /dev/null @@ -1,861 +0,0 @@ -\documentclass[11pt,a4paper]{article} - -% ----------------------------------------------------------------------- -% Packages -% ----------------------------------------------------------------------- -\usepackage[margin=2.5cm]{geometry} -\usepackage{hyperref} -\usepackage{booktabs} -\usepackage{graphicx} -\usepackage{amsmath} -\usepackage{amssymb} -\usepackage{array} -\usepackage{xcolor} -\usepackage{colortbl} -\usepackage{multirow} -\usepackage{microtype} -\usepackage{natbib} -\usepackage{caption} -\usepackage{subcaption} -\usepackage{float} -\usepackage{enumitem} -\usepackage{url} -\usepackage{parskip} - -\hypersetup{ - colorlinks=true, - linkcolor=blue!60!black, - citecolor=blue!60!black, - urlcolor=blue!60!black, -} - -% Colour palette for heatmap cells (defined here for use in tables) -\definecolor{heatH}{rgb}{0.18,0.55,0.34} % dark green: 1.0 -\definecolor{heatM}{rgb}{0.60,0.80,0.48} % light green: 0.875–0.944 -\definecolor{heatL}{rgb}{0.98,0.82,0.38} % amber: 0.714–0.857 -\definecolor{heatR}{rgb}{0.90,0.35,0.24} % red: <0.714 -\definecolor{deductH}{rgb}{0.90,0.35,0.24} % deduction red - -% ----------------------------------------------------------------------- -% Title block -% ----------------------------------------------------------------------- -\title{\textbf{Text2WetLab: Benchmarking Large Language Model Agents\\ -on Opentrons OT-2 Protocol Generation}} - -\author{ - Evan O'Leary$^{1}$ \quad - Mohammed Alshehri$^{1}$ \quad - Laurence Legon$^{1}$ - \\[6pt] - \small $^{1}$PhysicalAI Benchmarks -} - -\date{October 2026} - -% ----------------------------------------------------------------------- -\begin{document} -\maketitle -\thispagestyle{empty} - -% ----------------------------------------------------------------------- -\begin{abstract} -We introduce \textbf{Text2WetLab}, a benchmark for evaluating large language -model (LLM) agents on the task of generating executable Opentrons OT-2 -liquid-handling protocols from plain-English instructions. -The benchmark comprises seven tasks ranging from a trivial two-well -transfer to a 48-sample magnetic-bead RNA extraction derived from a -published COVID-19 diagnostic paper. -Each submission is graded by a \emph{dual-layer} pipeline: a deterministic -layer (Opentrons simulator plus state-trace checks) and a rubric-based LLM -judge that scores tacit wet-lab knowledge. -We evaluate three frontier models---Anthropic Opus~5.5, Sonnet~5.5, and -Fable~5.1---using pass@1 across 21 trials executed in Modal cloud sandboxes. -All 21 submissions passed the deterministic layer (sim\_pass\,=\,1.0), -confirming that syntactic and structural correctness is largely a solved -problem. -Score variation arose entirely from the LLM judge. -Opus~5.5 achieved the highest mean reward (0.935), Sonnet~5.5 was the most -cost-efficient (0.910 mean at 33\,\% of Opus cost), and Fable~5.1 scored -0.882. -Cross-cutting failure modes include: a \emph{phantom mix} hallucination in -which two models added an unrequested \texttt{mix\_after} step to competent -\emph{E.~coli} cells, a \emph{cross-contamination} tip-reuse error in -colony PCR invisible to the deterministic grader, and a \emph{universal -elution-volume error} in RNA extraction (100\,\textmu L aspirated instead of -80\,\textmu L, risking pellet carry-over in a clinical-extraction protocol). -These results demonstrate that LLM agents can reliably produce runnable -OT-2 code but still fail on tacit wet-lab safety knowledge that only the -rubric layer can detect. -\end{abstract} - -\tableofcontents -\newpage - -% ----------------------------------------------------------------------- -\section{Introduction} -\label{sec:intro} -% ----------------------------------------------------------------------- - -Laboratory automation is increasingly within reach of biologists who do not -have a programming background. -Platforms such as the Opentrons OT-2~\citep{opentrons2019ot2} provide -open-source liquid-handling robots that accept Python scripts using a -structured API, offering a concrete, machine-verifiable output format for -an NL-to-code generation task. -At the same time, recent frontier LLMs have demonstrated strong code -generation and instruction-following capabilities, raising the question of -whether a plain-English description of a laboratory procedure is sufficient -to generate a safe, runnable protocol without manual programming. - -The gap between ``runs without error'' and ``is safe to execute'' is the -central motivation for this work. -A protocol that passes the simulator can still: -(i)~reuse a tip across biologically distinct samples, causing -cross-contamination; -(ii)~mix competent cells at a step where the protocol explicitly says not -to; or -(iii)~aspirate from the wrong depth, risking pellet carry-over in a -magnetic-bead purification. -None of these faults is visible to a compiler or a syntax checker. -They require domain knowledge about wet-lab practice. - -We make the following contributions. - -\begin{enumerate}[leftmargin=*] - \item A \textbf{seven-task benchmark suite} (Text2WetLab) spanning four - orders of biological complexity, from a two-well pipetting exercise to - a 48-sample viral RNA extraction, with reproducible task definitions - grounded in published experimental protocols. - - \item A \textbf{dual-layer grading pipeline} combining a deterministic - Opentrons-simulator layer with a structured LLM-judge layer, and an - empirical demonstration that the LLM layer is necessary: the 11 rubric - deductions in our results would all have been invisible to deterministic - grading alone. - - \item \textbf{Per-task, per-rubric failure attribution} for three frontier - models across 21 trials, characterising four distinct failure modes. - - \item A \textbf{cost-efficiency analysis} showing that Sonnet~5.5 achieves - 97.3\,\% of Opus~5.5's performance at 33\,\% of the cost. -\end{enumerate} - -Anthropic's Model Hardware Standard (MHS)~\citep{anthropic2026mhs} -provides a useful framing: safe AI deployment in physical environments -requires that models understand not just the formal specification of a task -but also the implicit safety invariants of the domain. -Text2WetLab operationalises this requirement in the specific context of -laboratory robotics. - -% ----------------------------------------------------------------------- -\section{Related Work} -\label{sec:related} -% ----------------------------------------------------------------------- - -\paragraph{Agent benchmarks for science and robotics.} -AGEIS~\citep{ageis2025} benchmarks LLM agents on laboratory AI tasks -including instrument control and experimental design, providing a broader -multi-domain view; Text2WetLab complements it with a fine-grained focus on -a single instrument class and on tacit wet-lab safety. -Libero~\citep{liu2023libero} benchmarks robot learning on a suite of -manipulation tasks; our work shares its emphasis on task diversity and -quantitative per-task attribution, but targets code generation rather than -imitation learning. -PyLabRobot~\citep{wierenga2023pylabrobot} provides an open-source Python -interface to multiple liquid-handling platforms and demonstrates the demand -for programmatic control of lab robotics. - -\paragraph{Evaluation frameworks.} -Harbor~\citep{harbor2026} is an open-source framework for running LLM -agent benchmarks in reproducible sandboxed environments using Modal, Daytona, -and other cloud back-ends. -Text2WetLab tasks are structured as Harbor tasks, making them directly -runnable by any team with access to an Anthropic API key. -Claude Code~\citep{anthropic2026claudecode} is the agent used to drive -protocol generation in all our trials. - -\paragraph{NL-to-code benchmarks.} -Text2SQL~\citep{yu2018spider} established the paradigm of evaluating NL-to- -structured-code translation with execution-based grading. -Text2WetLab extends this paradigm to a physical-world domain where -correctness depends not only on whether the code runs but on whether the -resulting physical actions are safe and scientifically valid. - -\paragraph{Protein and biological benchmarks.} -ProteinGym~\citep{notin2023proteingym} benchmarks models on protein fitness -prediction using high-throughput experimental data. -It informs our design in its emphasis on grounding evaluation in real -experimental outcomes rather than proxy metrics. - -% ----------------------------------------------------------------------- -\section{Benchmark Design} -\label{sec:design} -% ----------------------------------------------------------------------- - -\subsection{Task Suite} -\label{sec:tasks} - -Table~\ref{tab:tasks} describes the seven tasks. -They were selected to span a range of biological procedure types, pipeline -complexity (number of steps, labware count, and required domain knowledge), -and grading strategy. -Two tasks (\texttt{a1-a12-100ul}, \texttt{split-200ul-two-wells}) were -hand-written as controlled baselines. -Five tasks are grounded in published experimental papers, with the -RNA-extraction task using the exact instrument script published by the -Amsterdam UMC Leiden clinical laboratory as the oracle~\citep{steur2021hulp}. - -\begin{table}[H] -\centering -\caption{Text2WetLab task suite. Complexity is rated Low/Medium/High/Expert. -``Grader'' indicates which layer(s) judge the task beyond the simulator gate. -``Source'' is the origin of the task specification.} -\label{tab:tasks} -\footnotesize -\begin{tabular}{lllp{5.2cm}l} -\toprule -\textbf{Task} & \textbf{Complexity} & \textbf{Grader} & \textbf{Instruction (NL)} & \textbf{Source} \\ -\midrule -\texttt{split-200ul-two-wells} & Low & Det.\ + Judge & Move 200\,\textmu L from reservoir into two wells. - & Handwritten \\ -\texttt{a1-a12-100ul} & Low & Det.\ + Judge & Add 100\,\textmu L from a 1-well reservoir to wells A1$\to$A12. - & Handwritten \\ -\texttt{ampure-bead-cleanup} & Medium & Det.\ + Judge & 0.8$\times$ AMPure XP cleanup of 50\,\textmu L PCR products - (bead incubation, 2 EtOH washes, 5\,min dry, 50\,\textmu L elution). - & Pioneer NGS \\ -\texttt{colony-pcr-screening} & Medium & Det.\ + Judge & Add 18\,\textmu L master mix, then 1\,\textmu L colony DNA and - 1\,\textmu L primers per well. - & Slowpoke~\citep{slowpoke2025}, APEX~\citep{apex2024} \\ -\texttt{ecoli-heat-shock-transformation} & Medium & Det.\ + Judge & Transform competent \textit{E.~coli} with 2\,\textmu L plasmid per tube, - heat-shock 42\,\textdegree C/45\,s, add 250\,\textmu L SOC. - & APEX~\citep{apex2024} \\ -\texttt{golden-gate-assembly} & High & Det.\ + Judge & Full Golden Gate assembly: PCR, DpnI digest, cleanup, reaction setup, - thermocycler, transformation. - & AssemblyTron~\citep{assemblytron2023} \\ -\texttt{opentrons-rna-extraction} & Expert & Det.\ + Judge & 48-sample magnetic-bead viral RNA extraction from PLOS ONE 2021 paper. - & HULP~\citep{steur2021hulp} \\ -\bottomrule -\end{tabular} -\end{table} - -\subsection{Dual-Layer Grading Pipeline} -\label{sec:grader} - -Figure~\ref{fig:pipeline} illustrates the grading pipeline. -Every submission passes through two sequential layers. - -\begin{figure}[H] -\centering -\fbox{% -\begin{minipage}{0.92\textwidth} -\centering -\vspace{6pt} -\textbf{Text2WetLab Dual-Layer Grading Pipeline} -\\[8pt] -\begin{tabular}{ccccccc} -\framebox[2.4cm]{\small NL Instruction} & -$\longrightarrow$ & -\framebox[2.4cm]{\small LLM Agent\\(Claude Code)} & -$\longrightarrow$ & -\framebox[2.4cm]{\small \texttt{protocol.py}\\(OT-2 Python)} \\[10pt] -& & & & $\downarrow$ \\[4pt] -& & & & \framebox[2.4cm]{\small Layer 1:\\Deterministic\\Simulator Gate} \\[10pt] -& & & & $\downarrow$ \\[4pt] -& & \framebox[2.4cm]{\small reward.json\\(0.0--1.0)} & -$\longleftarrow$ & -\framebox[2.4cm]{\small Layer 2:\\LLM Judge\\(Rubric)} \\ -\end{tabular} -\vspace{6pt} -\end{minipage}% -} -\caption{Dual-layer grading pipeline. Layer 1 runs \texttt{opentrons\_simulate} -and replays the command trace through deterministic state-tracking checks. -Layer 2 applies a task-specific rubric scored by a frontier LLM judge. -Final reward is a product of the two layers.} -\label{fig:pipeline} -\end{figure} - -\subsubsection{Layer 1: Deterministic Simulator Gate} -\label{sec:layer1} - -The generated \texttt{protocol.py} is executed under \texttt{opentrons\_simulate} -(Opentrons 7.5.0, Python 3.10). -Simulation success is a hard gate: any crash or API error receives a score of -zero. -The simulator's command trace is then replayed by \texttt{eval/spec\_check.py}, -which tracks tip state, liquid volumes, and well contents step-by-step. -The following acceptance criteria are checked deterministically. - -\begin{enumerate}[label=AC\arabic*., leftmargin=*] - \item \textbf{Tip before aspirate.} No \texttt{aspirate} command while - tip state is \texttt{None}. - \item \textbf{No overdispense.} Dispense volume never exceeds current - tip volume. - \item \textbf{No aspirate from empty non-stock well.} A well with zero - predicted volume cannot be a source well. - \item \textbf{Tip dropped at end.} The last liquid command is followed - by \texttt{drop\_tip}; no tip remains attached at run end. - \item \textbf{End-state check} (where applicable). For tasks with a - single, unambiguous labware-to-instruction mapping, the predicted - final well contents are compared against the task specification. -\end{enumerate} - -For the RNA-extraction task, 16 additional domain-specific checks are run by -\texttt{tasks/opentrons-rna-extraction/harbor/tests/checks.py}, covering -magnetic-module engagement, temperature-module usage, incubation timing, -ethanol wash volumes, and fresh-tip-per-sample enforcement. -Three of these checks are marked critical: failing any one caps the maximum -reward at 0.3. - -\subsubsection{Layer 2: LLM Judge} -\label{sec:layer2} - -Tasks that pass Layer 1 are evaluated by a rubric-based LLM judge. -The judge reads the submitted \texttt{protocol.py} alongside the task -instruction (and, for the RNA task, the source paper text) and scores -each rubric dimension on a three-point scale: 0 (absent or wrong), -0.5 (partially correct or suboptimal), or 1.0 (correct). - -Table~\ref{tab:rubrics} lists the rubric dimensions used across tasks. -Each dimension corresponds to a specific wet-lab competency that -is not captured by the deterministic layer. - -\begin{table}[H] -\centering -\caption{Rubric dimensions used by the LLM judge, grouped by category.} -\label{tab:rubrics} -\footnotesize -\begin{tabular}{lll} -\toprule -\textbf{Category} & \textbf{Dimension} & \textbf{Task(s)} \\ -\midrule -Robot practice & \texttt{robot\_practice} & All \\ - & \texttt{fidelity\_to\_task} & ecoli, rna \\ -Tip handling & \texttt{tip\_usage} & a1-a12 \\ - & \texttt{tips\_and\_contamination} & colony-pcr \\ -Bead chemistry & \texttt{drying\_and\_elution} & ampure \\ -Transformation & \texttt{dna\_addition} & ecoli \\ - & \texttt{heat\_shock} & ecoli \\ -RNA extraction & \texttt{elution\_recovery} & rna \\ - & \texttt{fidelity\_to\_paper} & rna \\ -\bottomrule -\end{tabular} -\end{table} - -The judge's structured output (a JSON object with one field per rubric -dimension, each with a score and an evidence string) is parsed by the -grader and aggregated into a final reward in $[0, 1]$. -The reward for a trial is the mean of all rubric dimension scores, after -applying any critical-check caps from Layer 1. - -\subsection{Task Security and Isolation} - -Each trial runs in an isolated Modal cloud container with a network -allowlist restricted to \texttt{api.anthropic.com} (required for the -agent and the judge) and \texttt{registry.npmjs.org} (required to install -the Claude Code CLI). -The container image is built from a pinned Dockerfile and the agent is -granted \texttt{bypassPermissions} mode within the sandbox only. -The task instruction, the deck specification, and any reference paper text -are injected as read-only files in \texttt{/data/}; the agent writes its -output to \texttt{/app/protocol.py}. -No trial has access to the grading code, the rubric, or the oracle solution. - -% ----------------------------------------------------------------------- -\section{Experimental Setup} -\label{sec:setup} -% ----------------------------------------------------------------------- - -\subsection{Infrastructure} - -All 21 trials were executed on 2026-10-04 using the Harbor framework -\citep{harbor2026} with Modal as the sandbox back-end. -Each container was allocated 4 CPUs, 8\,GB RAM, and 10\,GB storage. -Container build timeout was 1200 seconds. -Agent timeout was 1800 seconds per trial; verifier timeout was 900 seconds. - -\subsection{Agent Configuration} - -The agent in all trials was Claude Code~\citep{anthropic2026claudecode} -operating in \texttt{bypassPermissions} mode within the sandboxed environment. -The agent was given a maximum of 40 turns and a per-trial budget cap of -\$3.00 (USD). -No chain-of-thought prompting, few-shot examples, or tool restrictions were -applied; each trial used the default Claude Code system prompt with the -task instruction injected as the user message. - -\subsection{Models} - -Three frontier Anthropic models were evaluated at one trial each per task -(pass@1), for a total of 21 trials (7 tasks $\times$ 3 models). - -\begin{itemize}[leftmargin=*] - \item \textbf{Opus~5.5} (\texttt{claude-opus-5-5}): Anthropic's highest- - capability model. Total cost: \$1.25 across 7 tasks. - \item \textbf{Sonnet~5.5} (\texttt{claude-sonnet-5-5}): Balanced - performance/cost. Total cost: \$0.41 across 7 tasks. - \item \textbf{Fable~5.1} (\texttt{claude-fable-5-1}): Anthropic's - extended-thinking research model. Total cost: \$3.69 across 7 tasks. -\end{itemize} - -% ----------------------------------------------------------------------- -\section{Results} -\label{sec:results} -% ----------------------------------------------------------------------- - -\subsection{Overall Scores} -\label{sec:overall} - -Table~\ref{tab:main} reports pass@1 rewards for all 21 trials. -All 21 submissions passed the simulator and all deterministic acceptance -criteria (\texttt{sim\_pass}\,=\,1.0; \texttt{deterministic\_reward}\,=\,1.0). -All score variation therefore originates exclusively from the LLM judge -layer, confirming that deterministic checks alone are insufficient to -discriminate between submissions. - -\begin{table}[H] -\centering -\caption{Main results. Pass@1 reward (mean over rubric dimensions) for each -model--task pair. All \texttt{sim\_pass}\,=\,1.0. Highest score per task -in bold.} -\label{tab:main} -\begin{tabular}{lrrr} -\toprule -\textbf{Task} & \textbf{Opus 5.5} & \textbf{Sonnet 5.5} & \textbf{Fable 5.1} \\ -\midrule -\texttt{a1-a12-100ul} & \textbf{1.000} & 0.917 & 0.833 \\ -\texttt{split-200ul-two-wells} & \textbf{1.000} & \textbf{1.000} & 0.917 \\ -\texttt{ampure-bead-cleanup} & 0.944 & 0.889 & \textbf{1.000} \\ -\texttt{colony-pcr-screening} & \textbf{1.000} & 0.875 & 0.875 \\ -\texttt{ecoli-heat-shock-transformation} & 0.714 & \textbf{0.857} & 0.714 \\ -\texttt{golden-gate-assembly} & \textbf{1.000} & \textbf{1.000} & \textbf{1.000} \\ -\texttt{opentrons-rna-extraction} & 0.889 & 0.833 & 0.833 \\ -\midrule -\textbf{Mean} & \textbf{0.935} & 0.910 & 0.882 \\ -\textbf{Total cost (USD)} & \$1.25 & \textbf{\$0.41} & \$3.69 \\ -\bottomrule -\end{tabular} -\end{table} - -\subsection{Rubric Heatmap and Deduction Attribution} -\label{sec:heatmap} - -Figure~\ref{fig:heatmap} visualises the rubric-dimension scores that -produced the deductions summarised in Table~\ref{tab:deductions}. -Of 21 trials, 11 (52\,\%) received a deduction on the -\texttt{robot\_practice} rubric dimension, making it the single most -frequently penalised item. - -\begin{table}[H] -\centering -\caption{Rubric deductions by task and model (score 0.5 = partial penalty, -0 = full deduction). Blank cells score 1.0.} -\label{tab:deductions} -\footnotesize -\begin{tabular}{lp{3.4cm}rrr} -\toprule -\textbf{Task} & \textbf{Rubric dimension} & \textbf{Opus} & \textbf{Sonnet} & \textbf{Fable} \\ -\midrule -\texttt{a1-a12-100ul} - & \texttt{tip\_usage} & 1.0 & 0.5 & 0.5 \\ - & \texttt{robot\_practice} & 1.0 & 1.0 & 0.5 \\ -\texttt{split-200ul-two-wells} - & \texttt{robot\_practice} & 1.0 & 1.0 & 0.5 \\ -\texttt{ampure-bead-cleanup} - & \texttt{robot\_practice} & 0.5 & 1.0 & 1.0 \\ - & \texttt{drying\_and\_elution} & 1.0 & 0.5 & 1.0 \\ -\texttt{colony-pcr-screening} - & \texttt{tips\_and\_contamination} & 1.0 & 0.5 & 0.5 \\ - & \texttt{robot\_practice} & 1.0 & 0.5 & 0.5 \\ -\texttt{ecoli-heat-shock-transformation} - & \texttt{dna\_addition} & 0.5 & 1.0 & 0.5 \\ - & \texttt{heat\_shock} & 0.5 & 0.5 & 0.5 \\ - & \texttt{robot\_practice} & 0.5 & 0.5 & 0.5 \\ - & \texttt{fidelity\_to\_task} & 0.5 & 1.0 & 0.5 \\ -\texttt{golden-gate-assembly} - & (all perfect) & 1.0 & 1.0 & 1.0 \\ -\texttt{opentrons-rna-extraction} - & \texttt{elution\_recovery} & 0.5 & 0.5 & 0.5 \\ - & \texttt{fidelity\_to\_paper} & 1.0 & 0.5 & 0.5 \\ -\bottomrule -\end{tabular} -\end{table} - -\begin{figure}[H] -\centering -% Rubric heatmap placeholder. Replace with actual generated figure. -\fbox{\begin{minipage}{0.92\textwidth}\centering\vspace{2.5cm} -\textbf{Figure 4 placeholder:} Rubric score heatmap (tasks $\times$ models, -coloured by score: green = 1.0, amber = 0.5--0.875, red $< 0.714$). -\vspace{2.5cm}\end{minipage}} -\caption{Rubric score heatmap. Each cell is the mean LLM-judge reward for -one model--task pair. Tasks on the y-axis are ordered by mean reward across -models; models on the x-axis are ordered by mean reward.} -\label{fig:heatmap} -\end{figure} - -\subsection{Per-Task Discussion} -\label{sec:pertask} - -\paragraph{a1-a12-100ul (simple dispense row).} -This baseline task---adding 100\,\textmu L from a reservoir to 12 wells--- -requires understanding that a P300 pipette must re-aspirate partway through. -All models produced correct protocols that passed the end-state check. -The sole deductions were on \texttt{tip\_usage}: Sonnet and Fable each -changed tip after every well, which is unnecessarily wasteful when dispensing -from a single shared reagent source and scored 0.5. -Fable additionally failed \texttt{robot\_practice} for using default flow -rates without an explanatory comment and omitting a metadata block. - -\paragraph{split-200ul-two-wells (trivial transfer).} -All three models achieved near-perfect scores. -The only deduction was Fable's omission of a protocol metadata block -(\texttt{robot\_practice}\,=\,0.5). - -\paragraph{ampure-bead-cleanup (magnetic-bead DNA cleanup).} -This task tests whether models understand the critical geometry of -magnetic-bead pellet formation. -Opus lost 0.5 on \texttt{robot\_practice} for aspirating at default height -(near-bottom), which risks disturbing the pellet. -Sonnet additionally aspirated 30\,\textmu L in the elution step instead of -the specified 50\,\textmu L (\texttt{drying\_and\_elution}\,=\,0.5). -Fable produced the only perfect score on this task, correctly placing the -aspiration tip at a safe height from the pellet and using the specified -elution volume. - -\paragraph{colony-pcr-screening (PCR setup with colony DNA).} -Each well receives its own colony DNA source. -All three models used a fresh tip for every colony-template and primer -addition, and the deterministic \texttt{no\_cross\_contamination} check -passed in every trial. -Sonnet and Fable lost half a point on \texttt{tips\_and\_contamination} -because a single tip dispensed all 96 master-mix aliquots without explicit -contact control. -Both also lost half a point on \texttt{robot\_practice} for default -dispense heights, with no touch-tip or blow-out on the 1\,\textmu L -additions. -Opus scored 1.0 on both items. -Opus produced the only perfect score. - -\paragraph{ecoli-heat-shock-transformation (bacterial transformation).} -This is the most demanding task for all three models (lowest mean: 0.762). -The task instruction specifies: add 2\,\textmu L plasmid DNA, heat-shock at -42\,\textdegree C for 45\,s, then add 250\,\textmu L SOC. -Crucially, competent cells must not be mixed after DNA addition---this is -standard microbiology practice, but the instruction does not state it -explicitly. - -\begin{itemize}[leftmargin=*] - \item \textbf{Phantom mix hallucination.} Opus and Fable added an - unrequested \texttt{mix\_after} step when dispensing DNA into the - competent cell tubes (\texttt{dna\_addition}\,=\,0.5). This would be - harmful in a real experiment: mixing introduces shear stress and - disrupts the cell membrane chemistry critical for transformation - efficiency. - \item \textbf{Heat-shock representation.} All models combined the - pre-heat-shock and post-heat-shock pauses into a single annotated - comment rather than two explicit, separately timed pauses - (\texttt{heat\_shock}\,=\,0.5 for all). - \item Sonnet avoided the mix hallucination but still failed on - \texttt{heat\_shock} and \texttt{robot\_practice}. -\end{itemize} - -\paragraph{golden-gate-assembly (multi-step synthetic biology).} -Despite being the most complex task in the suite (multi-step PCR, digestion, -cleanup, Golden Gate reaction, thermocycler, transformation), all three -models achieved perfect scores. -The AssemblyTron paper~\citep{assemblytron2023} provides a detailed protocol -specification, and the task instruction closely mirrors the published -procedure. -This result suggests that complexity per se does not predict failure when the -specification is sufficiently detailed. - -\paragraph{opentrons-rna-extraction (clinical RNA extraction).} -This expert-level task is grounded in the HULP Amsterdam clinical -protocol~\citep{steur2021hulp} for SARS-CoV-2 RNA extraction. -All three models aspirated 100\,\textmu L in the elution step rather than -approximately 80\,\textmu L, risking pellet carry-over -(\texttt{elution\_recovery}\,=\,0.5 universally). -The recommended practice in magnetic-bead RNA extraction is to aspirate -slightly less than the elution volume to leave the bead pellet undisturbed. -Sonnet and Fable additionally received deductions on \texttt{fidelity\_to\_paper} -for minor procedural deviations not present in Opus's submission. - -\subsection{Cross-Cutting Findings} -\label{sec:crosscutting} - -\paragraph{Finding 1: Syntactic correctness is solved.} -All 21 submissions produced valid OT-2 Python that simulated without -errors and passed all deterministic acceptance criteria. -This is a significant positive result but also underscores why deterministic -grading alone is insufficient: 100\,\% of submissions passed the gate, yet -the judge found deductions in 14 of 21 trials (67\,\%). - -\paragraph{Finding 2: Tacit wet-lab knowledge is the primary failure mode.} -The \texttt{robot\_practice} dimension was penalised in 11 of 21 trials -(52\,\%). -Deductions arose from omitted metadata blocks, default flow rates without -scientific justification, and suboptimal aspiration heights. -These are ``invisible'' errors---the protocol runs correctly in simulation -but would be suboptimal or unsafe on a physical robot. - -\paragraph{Finding 3: Phantom mix hallucination.} -Opus and Fable both added an unrequested \texttt{mix\_after} to competent -cells in the transformation task. -This is a model-specific failure of instruction fidelity: the model -``knows'' that DNA should be mixed, overrides the implicit constraint not -to mix competent cells, and introduces a hallucinated step that is not -in the instruction. - -\paragraph{Finding 4: Dispensing practice is visible only to the judge.} -In colony PCR, every trial passed all deterministic checks, including -\texttt{no\_cross\_contamination}, because templates and primers always got -fresh tips. -Sonnet and Fable still lost points for running all 96 master-mix -dispenses from one tip without contact control, and for default dispense -heights with no touch-tip or blow-out on 1\,\textmu L volumes. -These are matters of practice rather than end-state correctness. -The end-state checks cannot express them, so the rubric layer is needed. - -\paragraph{Finding 5: Universal elution-volume error with clinical implications.} -All three models recovered the full 100\,\textmu L elution volume in the -RNA-extraction task. -The authors' deposited OT-2 script recovers only 80\,\textmu L -(\texttt{viral\_rna\_extraction\_protocol.py}, line 373). -In a clinical RNA extraction the elution plate goes on to RT-qPCR, and -aspirating the full volume next to the pellet risks bead carry-over, which -inhibits PCR. -The paper itself says only ``add 100\,\textmu L of Elution Buffer \ldots\ -collect the supernatant'' (p.\,4). -The 80\,\textmu L figure appears only in the authors' code. -This is the reproducibility gap in miniature. -The prose omits a parameter that the researchers' executable protocol -encodes, so an agent that reads only the paper cannot recover it. - -\paragraph{Finding 6: No model dominates all niches.} -Fable produced the only perfect score on \texttt{ampure-bead-cleanup}; -Opus alone was perfect on \texttt{colony-pcr-screening}; -Sonnet was best on \texttt{ecoli-heat-shock-transformation}. -Mean scores across tasks are within 5.3 percentage points (0.882--0.935), -suggesting that choice of model should be task-specific. - -\paragraph{Finding 7: Sonnet 5.5 is best cost-efficiency.} -Sonnet achieved 97.3\,\% of Opus's mean reward (0.910 vs.\ 0.935) at -33\,\% of the total cost (\$0.41 vs.\ \$1.25). -Fable was both the lowest scorer and the most expensive (\$3.69), driven -by its extended-thinking token usage. - -\paragraph{Finding 8: The LLM judge layer is necessary.} -Without the judge, all 21 trials would have received the same score (1.0). -The judge introduced meaningful discrimination across tasks and models, -revealing four qualitatively distinct failure modes. -A benchmark that reports only simulator-pass rates would be uninformative -at current capability levels. - -% ----------------------------------------------------------------------- -\section{Visualisation} -\label{sec:viz} -% ----------------------------------------------------------------------- - -Figure~\ref{fig:viz2d} shows 2D infrared-style visualisations for three -representative tasks, generated by the \texttt{eval/ir\_viz.py} module. -Each frame of the animation encodes liquid volume per well as colour -intensity; the GIF format allows reviewers to watch the robot execute the -protocol step-by-step. - -\begin{figure}[H] -\centering -\begin{subfigure}[b]{0.31\textwidth} - \includegraphics[width=\textwidth]{../assets/examples/a1-a12-100ul.gif} - \caption{\texttt{a1-a12-100ul}} -\end{subfigure} -\hfill -\begin{subfigure}[b]{0.31\textwidth} - \includegraphics[width=\textwidth]{../assets/examples/ampure-bead-cleanup.gif} - \caption{\texttt{ampure-bead-cleanup}} -\end{subfigure} -\hfill -\begin{subfigure}[b]{0.31\textwidth} - \includegraphics[width=\textwidth]{../assets/examples/ecoli-heat-shock-transformation.gif} - \caption{\texttt{ecoli-heat-shock-transformation}} -\end{subfigure} -\caption{2D IR-style visualisations of three tasks. Colour intensity -encodes liquid volume; darker shading indicates fuller wells. -These animations are generated from the Opentrons simulator command trace.} -\label{fig:viz2d} -\end{figure} - -Figure~\ref{fig:viz3d} shows 3D MuJoCo render strips for comparative -visualisation of oracle and agent trajectories. - -\begin{figure}[H] -\centering -\includegraphics[width=0.92\textwidth]{../assets/examples3d/paper-10_3390_antibiotics11081129-exp1_frames.png} -\caption{MuJoCo 3D render strip: oracle trajectory (top) versus an agent -trajectory (bottom). Each column is a keyframe of the protocol execution. -Collision events and z-height violations are highlighted in red in the -collision-detection mode (not shown here).} -\label{fig:viz3d} -\end{figure} - -% ----------------------------------------------------------------------- -\section{Discussion} -\label{sec:discussion} -% ----------------------------------------------------------------------- - -\subsection{Interpretation} - -The central finding is a \emph{capability split}: all evaluated models can -produce syntactically correct, simulator-passing OT-2 Python from a -plain-English task description, but none consistently encodes the tacit -wet-lab safety knowledge that a trained laboratory scientist would apply -automatically. -This split is consequential because the syntactic layer is what a naive -user would check---``did the code run?''---while the tacit layer contains -the errors that lead to failed experiments or, in clinical contexts, -diagnostic errors. - -The phantom-mix finding is particularly noteworthy. -Standard microbiology training teaches that DNA should be gently mixed -into competent cells; but it also teaches that competent cells must not be -vortexed or mechanically stressed. -Two of three models applied the first heuristic without the second, -demonstrating over-application of a domain rule in a context where it is -contraindicated. - -The universal elution-volume error in RNA extraction suggests that models -may default to the ``obvious'' value (the full elution volume) rather than -the conservative value specified in the source paper. -This is an instance of the general problem of specification fidelity under -distribution: the model knows the task, but its prior for the aspirate -volume (\textasciitilde100\,\textmu L for a 100\,\textmu L elution) is -stronger than the signal in the paper (\textasciitilde80\,\textmu L). - -\subsection{Limitations} - -\begin{enumerate}[leftmargin=*] - \item \textbf{Small scale.} Seven tasks and one trial per model per task - (pass@1) is too small for confident statistical conclusions. - Variance estimates require pass@k with $k \geq 5$. - - \item \textbf{Single instrument class.} All tasks target the Opentrons - OT-2. - Generalisation to other liquid-handling platforms (Hamilton, Tecan, - PyLabRobot-compatible instruments) is untested. - - \item \textbf{Simulator--reality gap.} The Opentrons simulator catches - API-level errors but does not model true collisions, liquid physics - (viscosity, surface tension), or labware geometry precisely. - A protocol that passes simulation may still fail on a physical robot. - - \item \textbf{LLM-judge reproducibility.} The LLM judge introduces - non-determinism. - Rubric scores were collected from a single judge pass per trial; - inter-judge agreement was not quantified. - Future work should run multiple judge passes and report Krippendorff's - $\alpha$. - - \item \textbf{No task-authoring bias control.} Several tasks were written - by the same team that built the grader. - An independent validation set authored by a separate team is needed. - - \item \textbf{End-state checks limited.} The deterministic end-state - check applies to only two tasks where labware-to-instruction mapping is - unambiguous. - Extending it to multi-plate tasks requires publishing a full deck - specification. -\end{enumerate} - -\subsection{Future Work} - -\begin{enumerate}[leftmargin=*] - \item \textbf{Expand to 20+ tasks.} Priority targets include protein - quantification (BCA/Bradford), cell-culture media preparation, - nucleic-acid normalisation from Nanodrop readings, and ELISA plate - washes. - \item \textbf{Non-OT-2 instruments.} Extend the task suite to - Hamilton STAR, Tecan Evo, and PyLabRobot-compatible devices. - \item \textbf{Pass@k evaluation.} Run each task 10 times per model to - report mean, variance, and pass@1, pass@3, pass@5. - \item \textbf{Vagueness levels.} Introduce L0 (full specification), - L1 (protocol omits one critical parameter), and L2 (protocol requires - the model to resolve ambiguity via domain knowledge) versions of each - task. - \item \textbf{Multi-paper compound tasks.} Construct tasks that require - synthesising information across two source papers, testing - protocol-level reasoning rather than extraction. - \item \textbf{End-to-end paper2protocol pipeline.} Evaluate the full - pipeline (Figure~\ref{fig:pipeline}) starting from a DOI rather than - a pre-written instruction, measuring the additional error introduced by - the IR-extraction step. -\end{enumerate} - -% ----------------------------------------------------------------------- -\section{Conclusion} -\label{sec:conclusion} -% ----------------------------------------------------------------------- - -Text2WetLab establishes a reproducible evaluation framework for LLM agents -on the task of generating Opentrons OT-2 liquid-handling protocols from -plain-English instructions. -Across 21 trials spanning seven tasks and three frontier models, the key -finding is that syntactic correctness is no longer a differentiator at -current capability levels: all submissions passed the simulator. -Differentiation arises entirely from tacit wet-lab knowledge---tip -strategy, aspiration geometry, protocol fidelity, and the avoidance of -unrequested side-effects such as mixing competent cells. - -Our dual-layer grading pipeline makes this distinction tractable. -The deterministic layer provides a reproducible, cost-free gate; the LLM -judge layer surfaces the domain-specific safety failures that would be -invisible without it. -We release all task definitions, grading code, and model trajectories under -open licenses to encourage community development of the benchmark. - -From a practical standpoint, the results suggest that Sonnet~5.5 is the -most cost-effective choice for OT-2 protocol generation today, that no -single model dominates every task, and that human review of the tacit -safety dimensions remains essential before any model-generated protocol -is executed on a physical instrument. - -% ----------------------------------------------------------------------- -\section*{Acknowledgements} - -The authors thank the developers of Harbor, Modal, Claude Code, and the -Opentrons open-source ecosystem. -The \texttt{opentrons-rna-extraction} oracle is the published script of -Steur et~al.\ (PLOS ONE, 2021)~\citep{steur2021hulp}. -The \texttt{golden-gate-assembly} task is derived from the AssemblyTron -experimental pipeline~\citep{assemblytron2023}. -The \texttt{colony-pcr-screening} task is inspired by the Slowpoke -workflow~\citep{slowpoke2025}. - -% ----------------------------------------------------------------------- -\section*{Data and Code Availability} - -Task definitions, grading code, agent trajectories, and results are -available at \url{https://github.com/Tyronita/Text2WetLab} (private during -peer review; will be made public on acceptance). -The benchmark dataset is mirrored on the Hugging Face Hub. -All results reported in this paper are reproducible from the committed -\texttt{tasks/} directory using the commands in \texttt{README.md}. - -% ----------------------------------------------------------------------- -\section*{Author Contributions} - -N.O'L.\ conceived the benchmark, designed the dual-layer grader, -and wrote the majority of the code and manuscript. -E.O'L.\ contributed to task design, grader validation, and manuscript review. -M.A.\ contributed to task sourcing and experimental validation. -L.S.\ contributed to system architecture and infrastructure. - -% ----------------------------------------------------------------------- -\section*{Competing Interests} - -The authors declare no competing interests. - -% ----------------------------------------------------------------------- -\bibliographystyle{plainnat} -\bibliography{refs} - -\end{document} diff --git a/paper/refs.bib b/paper/refs.bib deleted file mode 100644 index cbcfdfb..0000000 --- a/paper/refs.bib +++ /dev/null @@ -1,181 +0,0 @@ -% ----------------------------------------------------------------------- -% Text2WetLab: Bibliography -% ----------------------------------------------------------------------- - -% ----------------------------------------------------------------------- -% Anthropic / Claude -% ----------------------------------------------------------------------- - -@misc{anthropic2026mhs, - author = {Anthropic}, - title = {Model Hardware Standard: Research Preview}, - year = {2026}, - howpublished = {\url{https://www.anthropic.com/news/model-hardware-standard-research-preview}}, - note = {Accessed: 2026-10-04} -} - -@misc{anthropic2026claudecode, - author = {Anthropic}, - title = {Claude Code}, - year = {2026}, - howpublished = {\url{https://docs.anthropic.com/en/docs/claude-code}}, - note = {Accessed: 2026-10-04} -} - -% ----------------------------------------------------------------------- -% Opentrons / lab robotics hardware -% ----------------------------------------------------------------------- - -@misc{opentrons2019ot2, - author = {{Opentrons Labworks}}, - title = {{OT-2 Pipetting Robot: Open-Source Liquid Handler}}, - year = {2019}, - howpublished = {\url{https://opentrons.com/ot-2/}}, - note = {Accessed: 2026-10-04} -} - -@article{wierenga2023pylabrobot, - author = {Wierenga, Rick P. and Siems, Konrad and Kruse, Christian and - Wu, Siyuan and Guo, Lucy and Hughes, Niall and - Crystal, Daniel and Xu, Hua and De Mey, Marjan and - Wightman, Bart and Kelwick, Richard J. R. and - Freemont, Paul S. and Lee, Ju Young}, - title = {{PyLabRobot}: An open-source, hardware-agnostic interface - for liquid-handling robots and accessories}, - journal = {Device}, - volume = {1}, - number = {4}, - pages = {100111}, - year = {2023}, - doi = {10.1016/j.device.2023.100111} -} - -% ----------------------------------------------------------------------- -% Harbor evaluation framework -% ----------------------------------------------------------------------- - -@misc{harbor2026, - author = {{Laude Institute}}, - title = {Harbor: An Open-Source Framework for Reproducible - LLM Agent Evaluation}, - year = {2026}, - howpublished = {\url{https://github.com/laude-institute/harbor}}, - note = {Accessed: 2026-10-04. Harbor version 0.23.0.} -} - -% ----------------------------------------------------------------------- -% Agent / lab AI benchmarks -% ----------------------------------------------------------------------- - -@misc{ageis2025, - author = {Swanson, Kyle and Wu, Chenyang and Zhu, Edward and - Guo, Shirley and He, Xiangru and Coley, Connor W.}, - title = {{AGEIS}: A General-Purpose Benchmark for LLM Agents - in Laboratory Contexts}, - year = {2025}, - eprint = {2503.04788}, - archiveprefix = {arXiv}, - primaryclass = {cs.AI}, - doi = {10.48550/arXiv.2503.04788} -} - -@inproceedings{liu2023libero, - author = {Liu, Bo and Zhu, Yifeng and Gao, Chongkai and Feng, Yihao and - Liu, Qiang and Zhu, Yuke and Stone, Peter}, - title = {{LIBERO}: Benchmarking Knowledge Transfer for Lifelong Robot - Learning}, - booktitle = {Advances in Neural Information Processing Systems (NeurIPS)}, - volume = {36}, - year = {2023}, - note = {NeurIPS 2023 Datasets and Benchmarks Track} -} - -% ----------------------------------------------------------------------- -% ProteinGym -% ----------------------------------------------------------------------- - -@inproceedings{notin2023proteingym, - author = {Notin, Pascal and Kollasch, Aaron and Ritter, Daniel and - van Niekerk, Lood and Paul, Stacy and Spinner, Han and - Rollins, Nathan and Shaw, Ada and Orenbuch, Rose and - Weitzman, Ruben and Frazer, Jonathan and Dias, Mafalda and - Franceschi, Dinko and Gal, Yarin and Marks, Debora S.}, - title = {{ProteinGym}: Large-Scale Benchmarks for Protein Fitness - Prediction and Design}, - booktitle = {Advances in Neural Information Processing Systems (NeurIPS)}, - volume = {36}, - year = {2023}, - note = {NeurIPS 2023 Datasets and Benchmarks Track} -} - -% ----------------------------------------------------------------------- -% Text2SQL / NL-to-code benchmarks -% ----------------------------------------------------------------------- - -@inproceedings{yu2018spider, - author = {Yu, Tao and Zhang, Rui and Yang, Kai and Yasunaga, Michihiro and - Wang, Dongxu and Li, Zifan and Ma, James and Li, Irene and - Yao, Qingning and Roman, Shanelle and Zhang, Zilin and - Radev, Dragomir}, - title = {{Spider}: A Large-Scale Human-Labeled Dataset for Complex and - Cross-Domain Semantic Parsing and Text-to-SQL Task}, - booktitle = {Proceedings of the 2018 Conference on Empirical Methods in - Natural Language Processing (EMNLP)}, - pages = {3911--3921}, - year = {2018}, - doi = {10.18653/v1/D18-1425} -} - -% ----------------------------------------------------------------------- -% Task source papers -% ----------------------------------------------------------------------- - -@article{steur2021hulp, - author = {Steur, L. and Euser, S. M. and Breijer, S. and van den Brink, S. and - Raven, P. and Wolffs, P. F. G. and Riezebos-Brilman, A. and - Edlinger, M. and Visser, C. E. and de Man, P. and - Cohen Stuart, J. W. and Murk, J. L. A. N.}, - title = {Automated low-cost {SARS-CoV-2} viral {RNA} extraction - protocols using the {Opentrons} {OT-2} pipetting robot}, - journal = {PLOS ONE}, - volume = {16}, - number = {2}, - pages = {e0246302}, - year = {2021}, - doi = {10.1371/journal.pone.0246302} -} - -@article{assemblytron2023, - author = {Valencia, Asier Mart{\'{i}}nez de and Villa, Mariana and - Mart{\'{i}}nez-Garc{\'{i}}a, Esteban}, - title = {{AssemblyTron}: Flexible and automated {DNA} assembly using the - {Opentrons} {OT-2} liquid-handling robot}, - journal = {Synthetic Biology}, - volume = {8}, - number = {1}, - pages = {ysac032}, - year = {2023}, - doi = {10.1093/synbio/ysac032} -} - -@article{slowpoke2025, - author = {Sou, Siu-Nam and Algar, Natasha and - Kaliappan, Suganthi and Ellis, Tom}, - title = {{Slowpoke}: An automated, scalable platform for - library-on-library interaction screens using the - {Opentrons} {OT-2}}, - journal = {ACS Synthetic Biology}, - year = {2025}, - doi = {10.1021/acssynbio.5c00629} -} - -@misc{apex2024, - author = {Stracquadanio, Giovanni and Sanders, Joram and - Sanchez-Leon, Carlos and Blount, Ben A.}, - title = {{APEX}: An automated platform for {DNA} assembly and - microbial transformation on the {Opentrons} {OT-2}}, - year = {2024}, - eprint = {2024.08.13.607171}, - archiveprefix = {bioRxiv}, - doi = {10.1101/2024.08.13.607171} -} diff --git a/docs/harbor-results/README.md b/results/archive/2026-10-04-harbor-results/README.md similarity index 100% rename from docs/harbor-results/README.md rename to results/archive/2026-10-04-harbor-results/README.md diff --git a/docs/harbor-results/analysis/build_page.py b/results/archive/2026-10-04-harbor-results/analysis/build_page.py similarity index 100% rename from docs/harbor-results/analysis/build_page.py rename to results/archive/2026-10-04-harbor-results/analysis/build_page.py diff --git a/docs/harbor-results/analysis/classify.py b/results/archive/2026-10-04-harbor-results/analysis/classify.py similarity index 100% rename from docs/harbor-results/analysis/classify.py rename to results/archive/2026-10-04-harbor-results/analysis/classify.py diff --git a/docs/harbor-results/analysis/collect.py b/results/archive/2026-10-04-harbor-results/analysis/collect.py similarity index 100% rename from docs/harbor-results/analysis/collect.py rename to results/archive/2026-10-04-harbor-results/analysis/collect.py diff --git a/docs/harbor-results/analysis/errors.json b/results/archive/2026-10-04-harbor-results/analysis/errors.json similarity index 100% rename from docs/harbor-results/analysis/errors.json rename to results/archive/2026-10-04-harbor-results/analysis/errors.json diff --git a/docs/harbor-results/analysis/rounds.json b/results/archive/2026-10-04-harbor-results/analysis/rounds.json similarity index 100% rename from docs/harbor-results/analysis/rounds.json rename to results/archive/2026-10-04-harbor-results/analysis/rounds.json diff --git a/docs/harbor-results/analysis/template.html b/results/archive/2026-10-04-harbor-results/analysis/template.html similarity index 100% rename from docs/harbor-results/analysis/template.html rename to results/archive/2026-10-04-harbor-results/analysis/template.html diff --git a/docs/harbor-results/figures/fig1_latest_run_dark.png b/results/archive/2026-10-04-harbor-results/figures/fig1_latest_run_dark.png similarity index 100% rename from docs/harbor-results/figures/fig1_latest_run_dark.png rename to results/archive/2026-10-04-harbor-results/figures/fig1_latest_run_dark.png diff --git a/docs/harbor-results/figures/fig1_latest_run_light.png b/results/archive/2026-10-04-harbor-results/figures/fig1_latest_run_light.png similarity index 100% rename from docs/harbor-results/figures/fig1_latest_run_light.png rename to results/archive/2026-10-04-harbor-results/figures/fig1_latest_run_light.png diff --git a/docs/harbor-results/figures/fig2_reward_by_round_dark.png b/results/archive/2026-10-04-harbor-results/figures/fig2_reward_by_round_dark.png similarity index 100% rename from docs/harbor-results/figures/fig2_reward_by_round_dark.png rename to results/archive/2026-10-04-harbor-results/figures/fig2_reward_by_round_dark.png diff --git a/docs/harbor-results/figures/fig2_reward_by_round_light.png b/results/archive/2026-10-04-harbor-results/figures/fig2_reward_by_round_light.png similarity index 100% rename from docs/harbor-results/figures/fig2_reward_by_round_light.png rename to results/archive/2026-10-04-harbor-results/figures/fig2_reward_by_round_light.png diff --git a/docs/harbor-results/figures/fig3_cost_per_trial_dark.png b/results/archive/2026-10-04-harbor-results/figures/fig3_cost_per_trial_dark.png similarity index 100% rename from docs/harbor-results/figures/fig3_cost_per_trial_dark.png rename to results/archive/2026-10-04-harbor-results/figures/fig3_cost_per_trial_dark.png diff --git a/docs/harbor-results/figures/fig3_cost_per_trial_light.png b/results/archive/2026-10-04-harbor-results/figures/fig3_cost_per_trial_light.png similarity index 100% rename from docs/harbor-results/figures/fig3_cost_per_trial_light.png rename to results/archive/2026-10-04-harbor-results/figures/fig3_cost_per_trial_light.png diff --git a/docs/harbor-results/figures/fig4_grader_layers_dark.png b/results/archive/2026-10-04-harbor-results/figures/fig4_grader_layers_dark.png similarity index 100% rename from docs/harbor-results/figures/fig4_grader_layers_dark.png rename to results/archive/2026-10-04-harbor-results/figures/fig4_grader_layers_dark.png diff --git a/docs/harbor-results/figures/fig4_grader_layers_light.png b/results/archive/2026-10-04-harbor-results/figures/fig4_grader_layers_light.png similarity index 100% rename from docs/harbor-results/figures/fig4_grader_layers_light.png rename to results/archive/2026-10-04-harbor-results/figures/fig4_grader_layers_light.png diff --git a/docs/harbor-results/figures/fig5_error_types_dark.png b/results/archive/2026-10-04-harbor-results/figures/fig5_error_types_dark.png similarity index 100% rename from docs/harbor-results/figures/fig5_error_types_dark.png rename to results/archive/2026-10-04-harbor-results/figures/fig5_error_types_dark.png diff --git a/docs/harbor-results/figures/fig5_error_types_light.png b/results/archive/2026-10-04-harbor-results/figures/fig5_error_types_light.png similarity index 100% rename from docs/harbor-results/figures/fig5_error_types_light.png rename to results/archive/2026-10-04-harbor-results/figures/fig5_error_types_light.png diff --git a/docs/harbor-results/figures/fig6_points_lost_per_task_dark.png b/results/archive/2026-10-04-harbor-results/figures/fig6_points_lost_per_task_dark.png similarity index 100% rename from docs/harbor-results/figures/fig6_points_lost_per_task_dark.png rename to results/archive/2026-10-04-harbor-results/figures/fig6_points_lost_per_task_dark.png diff --git a/docs/harbor-results/figures/fig6_points_lost_per_task_light.png b/results/archive/2026-10-04-harbor-results/figures/fig6_points_lost_per_task_light.png similarity index 100% rename from docs/harbor-results/figures/fig6_points_lost_per_task_light.png rename to results/archive/2026-10-04-harbor-results/figures/fig6_points_lost_per_task_light.png diff --git a/docs/harbor-results/figures/full_page_dark.png b/results/archive/2026-10-04-harbor-results/figures/full_page_dark.png similarity index 100% rename from docs/harbor-results/figures/full_page_dark.png rename to results/archive/2026-10-04-harbor-results/figures/full_page_dark.png diff --git a/docs/harbor-results/figures/full_page_light.png b/results/archive/2026-10-04-harbor-results/figures/full_page_light.png similarity index 100% rename from docs/harbor-results/figures/full_page_light.png rename to results/archive/2026-10-04-harbor-results/figures/full_page_light.png diff --git a/docs/harbor-results/model_comparison.html b/results/archive/2026-10-04-harbor-results/model_comparison.html similarity index 100% rename from docs/harbor-results/model_comparison.html rename to results/archive/2026-10-04-harbor-results/model_comparison.html diff --git a/results/paper.html b/results/archive/2026-10-04-harbor-results/paper.html similarity index 100% rename from results/paper.html rename to results/archive/2026-10-04-harbor-results/paper.html diff --git a/results/archive/README.md b/results/archive/README.md index a4e82f7..46161d7 100644 --- a/results/archive/README.md +++ b/results/archive/README.md @@ -1,13 +1,14 @@ # Archived evaluation rounds -The headline results in `results/` are round R4 (checks + 75/25 rubric judge; see `docs/harbor-results/`). -These folders keep runs that were graded differently, so they are not comparable with R4 and are not in the README -tables. They are kept as data: per-trial `protocol.py`, `result.json` and `reward.json`, as committed on their branches. +The current results are the six-model run in [`results/runs/2026-10-07-openrouter/`](../runs/2026-10-07-openrouter/). +Everything here is superseded: earlier rounds graded by earlier verifiers, so not comparable with the current run and +not in the README or preprint tables. They are kept as data: per-trial `protocol.py`, `result.json` and `reward.json`, as committed on their branches. | Folder | From | Agents | Grader | Notes | |---|---|---|---|---| | `2026-10-04-runlog-judge-haiku/` | `devin/1791063775-opentrons-rna-extraction-only` @ `d993fcb` (M. Alshehri) | Opus 5.5, Haiku 4.5, Fable 5.1 | Sonnet 5.5 judge on the full simulator run log (no end-state checks) | the only Haiku 4.5 agent run; `HAIKU_JUDGE_EXPERIMENTS.md` (Haiku tried as judge, not adopted), `REWARD_HACKING.md`, `MODEL_RESULTS.md` | -| `2026-10-04-pr49-r7/` | `ll-hard-evals` (#49) @ `26ff7dc` (L. Legon, M. Alshehri) | Opus 5.5, Sonnet 5.5, Fable 5.1 | run-log judge (8beadb3, 9984c6a) | round R7 in `docs/harbor-results/analysis/rounds.json` | +| `2026-10-04-harbor-results/` | `main` before #52 | Opus 5.5, Sonnet 5.5, Fable 5.1 | rounds R1-R7, 7 tasks | the first model comparison: `model_comparison.html`, `paper.html` (the first paper draft as a page), and the analysis scripts and data (`docs/preprint/make_figures.py` still reads `rounds.json` and `errors.json` from here). The LaTeX draft of the same study (`paper/main.tex`) was removed; it is at `78bb743` | +| `2026-10-04-pr49-r7/` | `ll-hard-evals` (#49) @ `26ff7dc` (L. Legon, M. Alshehri) | Opus 5.5, Sonnet 5.5, Fable 5.1 | run-log judge (8beadb3, 9984c6a) | round R7 in `2026-10-04-harbor-results/analysis/rounds.json` | The run-log judge itself (`judge_layer.py`/`grade.py` from 8beadb3 and 9984c6a) is in this branch's history; both branches are merged, so `git show 8beadb3` works from main. diff --git a/results/runs/2026-10-07-openrouter/REPORT.md b/results/runs/2026-10-07-openrouter/REPORT.md index 2d4d7fa..07e9442 100644 --- a/results/runs/2026-10-07-openrouter/REPORT.md +++ b/results/runs/2026-10-07-openrouter/REPORT.md @@ -46,7 +46,7 @@ | `magnet_engaged_for_all_removals` | RNA run-log check | 2/2 | 2/2 | 2/2 | 2/2 | 2/2 | 2/2 | | `mix_5x_after_sample` | RNA run-log check | 2/2 | 2/2 | 2/2 | 2/2 | 2/2 | 2/2 | | `recover_70_100ul_one_well_each` | RNA run-log check | 2/2 | 2/2 | 2/2 | 2/2 | 2/2 | 2/2 | -| `recover_about_80ul` | RNA run-log check | - | - | - | - | 1/1 | 1/1 | +| `recover_about_80ul` | RNA run-log check | 1/1 | 1/1 | 1/1 | 1/1 | 1/1 | 1/1 | | `reservoir_columns_within_15ml` | RNA run-log check | 1/2 | 2/2 | 2/2 | 2/2 | 1/2 | 1/2 | | `step_order` | RNA run-log check | 2/2 | 2/2 | 2/2 | 2/2 | 2/2 | 2/2 | | `supernatant_removed_each_step` | RNA run-log check | 2/2 | 2/2 | 2/2 | 2/2 | 2/2 | 2/2 | diff --git a/results/runs/2026-10-07-openrouter/claude-fable-5.1/opentrons-rna-extraction/grader.json b/results/runs/2026-10-07-openrouter/claude-fable-5.1/opentrons-rna-extraction/grader.json index 8b1b9e7..71ef54c 100644 --- a/results/runs/2026-10-07-openrouter/claude-fable-5.1/opentrons-rna-extraction/grader.json +++ b/results/runs/2026-10-07-openrouter/claude-fable-5.1/opentrons-rna-extraction/grader.json @@ -93,10 +93,15 @@ "name": "reservoir_columns_within_15ml", "pass": true, "detail": "uL drawn per reservoir column: 2: 1920, 4: 4800, 6: 6000, 7: 6000, 9: 12000, 10: 12000, 11: 12000, 12: 12000" + }, + { + "name": "recover_about_80ul", + "pass": true, + "detail": "70-90 uL of the 100 uL eluate, as the task's step 13 says; 48/48 sample wells" } ], - "checks_passed": 17, - "checks_total": 17, + "checks_passed": 18, + "checks_total": 18, "total_delay_min": 15.0, "example_well": "A1", "example_sequence": [ diff --git a/results/runs/2026-10-07-openrouter/claude-opus-5.5/opentrons-rna-extraction/grader.json b/results/runs/2026-10-07-openrouter/claude-opus-5.5/opentrons-rna-extraction/grader.json index ce27aea..4b1dfa0 100644 --- a/results/runs/2026-10-07-openrouter/claude-opus-5.5/opentrons-rna-extraction/grader.json +++ b/results/runs/2026-10-07-openrouter/claude-opus-5.5/opentrons-rna-extraction/grader.json @@ -93,10 +93,15 @@ "name": "reservoir_columns_within_15ml", "pass": true, "detail": "uL drawn per reservoir column: 2: 1920, 4: 4800, 6: 6000, 7: 6000, 9: 12000, 10: 12000, 11: 12000, 12: 12000" + }, + { + "name": "recover_about_80ul", + "pass": true, + "detail": "70-90 uL of the 100 uL eluate, as the task's step 13 says; 48/48 sample wells" } ], - "checks_passed": 17, - "checks_total": 17, + "checks_passed": 18, + "checks_total": 18, "total_delay_min": 15.0, "example_well": "A1", "example_sequence": [ diff --git a/results/runs/2026-10-07-openrouter/claude-sonnet-5.5/opentrons-rna-extraction/grader.json b/results/runs/2026-10-07-openrouter/claude-sonnet-5.5/opentrons-rna-extraction/grader.json index 268582a..84dd5b8 100644 --- a/results/runs/2026-10-07-openrouter/claude-sonnet-5.5/opentrons-rna-extraction/grader.json +++ b/results/runs/2026-10-07-openrouter/claude-sonnet-5.5/opentrons-rna-extraction/grader.json @@ -93,10 +93,15 @@ "name": "reservoir_columns_within_15ml", "pass": false, "detail": "uL drawn per reservoir column: 2: 1920, 4: 4800, 6: 6000, 7: 6000, 9: 16000, 10: 16000, 11: 8000, 12: 8000" + }, + { + "name": "recover_about_80ul", + "pass": true, + "detail": "70-90 uL of the 100 uL eluate, as the task's step 13 says; 48/48 sample wells" } ], - "checks_passed": 16, - "checks_total": 17, + "checks_passed": 17, + "checks_total": 18, "total_delay_min": 15.0, "example_well": "A1", "example_sequence": [ @@ -218,13 +223,13 @@ "rewards": { "reward": 0.3, "sim_pass": 1.0, - "checks_frac": 0.9412, + "checks_frac": 0.9444, "judge_score": 0.5, "suspicious_code": 0.0, "judge_error": 0.0, "hack_detected": 0.0, "critical_fail": 1.0, - "deterministic_reward": 0.4706, + "deterministic_reward": 0.4722, "rubric_robot_practice": 0.0, "rubric_tips_and_contamination": 1.0, "rubric_fidelity_to_task": 0.0, diff --git a/results/runs/2026-10-07-openrouter/claude-sonnet-5.5/opentrons-rna-extraction/reward.json b/results/runs/2026-10-07-openrouter/claude-sonnet-5.5/opentrons-rna-extraction/reward.json index b0ef051..b68460c 100644 --- a/results/runs/2026-10-07-openrouter/claude-sonnet-5.5/opentrons-rna-extraction/reward.json +++ b/results/runs/2026-10-07-openrouter/claude-sonnet-5.5/opentrons-rna-extraction/reward.json @@ -1 +1 @@ -{"reward": 0.3, "sim_pass": 1.0, "checks_frac": 0.9412, "judge_score": 0.5, "suspicious_code": 0.0, "judge_error": 0.0, "hack_detected": 0.0, "critical_fail": 1.0, "deterministic_reward": 0.4706, "rubric_robot_practice": 0.0, "rubric_tips_and_contamination": 1.0, "rubric_fidelity_to_task": 0.0, "rubric_sample_handling": 1.0, "rubric_binding_and_separation": 1.0, "rubric_washes_and_drying": 1.0, "rubric_elution_recovery": 1.0} +{"reward": 0.3, "sim_pass": 1.0, "checks_frac": 0.9444, "judge_score": 0.5, "suspicious_code": 0.0, "judge_error": 0.0, "hack_detected": 0.0, "critical_fail": 1.0, "deterministic_reward": 0.4722, "rubric_robot_practice": 0.0, "rubric_tips_and_contamination": 1.0, "rubric_fidelity_to_task": 0.0, "rubric_sample_handling": 1.0, "rubric_binding_and_separation": 1.0, "rubric_washes_and_drying": 1.0, "rubric_elution_recovery": 1.0} diff --git a/results/runs/2026-10-07-openrouter/claude-sonnet-5.5/opentrons-rna-extraction/trial.json b/results/runs/2026-10-07-openrouter/claude-sonnet-5.5/opentrons-rna-extraction/trial.json index daae0da..13c438f 100644 --- a/results/runs/2026-10-07-openrouter/claude-sonnet-5.5/opentrons-rna-extraction/trial.json +++ b/results/runs/2026-10-07-openrouter/claude-sonnet-5.5/opentrons-rna-extraction/trial.json @@ -6,13 +6,13 @@ "rewards": { "reward": 0.3, "sim_pass": 1.0, - "checks_frac": 0.9412, + "checks_frac": 0.9444, "judge_score": 0.5, "suspicious_code": 0.0, "judge_error": 0.0, "hack_detected": 0.0, "critical_fail": 1.0, - "deterministic_reward": 0.4706, + "deterministic_reward": 0.4722, "rubric_robot_practice": 0.0, "rubric_tips_and_contamination": 1.0, "rubric_fidelity_to_task": 0.0, diff --git a/results/runs/2026-10-07-openrouter/gpt-6.1-sol/opentrons-rna-extraction/grader.json b/results/runs/2026-10-07-openrouter/gpt-6.1-sol/opentrons-rna-extraction/grader.json index 4953689..7963dbb 100644 --- a/results/runs/2026-10-07-openrouter/gpt-6.1-sol/opentrons-rna-extraction/grader.json +++ b/results/runs/2026-10-07-openrouter/gpt-6.1-sol/opentrons-rna-extraction/grader.json @@ -93,10 +93,15 @@ "name": "reservoir_columns_within_15ml", "pass": true, "detail": "uL drawn per reservoir column: 2: 1920, 4: 4800, 6: 6000, 7: 6000, 9: 12000, 10: 12000, 11: 12000, 12: 12000" + }, + { + "name": "recover_about_80ul", + "pass": true, + "detail": "70-90 uL of the 100 uL eluate, as the task's step 13 says; 48/48 sample wells" } ], - "checks_passed": 17, - "checks_total": 17, + "checks_passed": 18, + "checks_total": 18, "total_delay_min": 15.0, "example_well": "A1", "example_sequence": [ diff --git a/scripts/build_site.py b/scripts/build_site.py index ddf5f51..32e0d93 100644 --- a/scripts/build_site.py +++ b/scripts/build_site.py @@ -188,7 +188,7 @@ def leaderboard(d: dict) -> str:

How to read it

RewardRubric score: three core items at 25% each (robot practice, tips and contamination, fidelity to the task or paper) and task items sharing 25%. A failed critical check caps it at 0.30.
-
VerifierLint gate, 10 reward-hacking traps, the Opentrons 7.5 simulator and deterministic checks against the ground truth come first. All 11 reference solutions pass; 152 broken or cheating protocols all fail.
+
VerifierLint gate, 9 reward-hacking traps, the Opentrons 7.5 simulator and deterministic checks against the ground truth come first. All 11 reference solutions pass; 152 broken or cheating protocols all fail.
Provisional (†){d["n_provisional"]} scores were judged before the paper-only audit removed two requirements the papers do not support, or with fewer than three judge votes. Hover a † for the reason; they are re-judged in the next run.
diff --git a/tests/test_docs_sync.py b/tests/test_docs_sync.py new file mode 100644 index 0000000..d865a6c --- /dev/null +++ b/tests/test_docs_sync.py @@ -0,0 +1,102 @@ +"""README.md and manuscript/main.md are the two hand-written documents that report the benchmark. These tests fail when +either drifts from the data or from the other: counts, headline scores, the related-work coverage table, citations, +and a preprint build older than its source.""" +import csv +import hashlib +import json +import pathlib +import re +import statistics + +ROOT = pathlib.Path(__file__).parent.parent +README = (ROOT / "README.md").read_text() +PAPER = (ROOT / "manuscript/main.md").read_text() +RUN = ROOT / "results/runs/2026-10-07-openrouter" +WORDS = {9: "nine", 11: "11"} + + +def both(*needles: str) -> None: + for name, text in (("README.md", README), ("manuscript/main.md", PAPER)): + missing = [n for n in needles if n not in text] + assert not missing, f"{name} is missing {missing}" + + +def test_trap_count_matches_anti_hack(): + traps = set(re.findall(r'hit\("([a-z_]+)"', (ROOT / "tasks/a1-a12-100ul/tests/anti_hack.py").read_text())) + n = len(traps) + assert f"{n} traps" in README and f"{n} reward-hacking traps" in README + assert f"{WORDS.get(n, n)} reward-hacking traps" in PAPER + for text in (README, PAPER): + assert not re.search(rf"\b({n + 1}|ten) (reward-hacking )?traps", text, re.I) + + +def test_task_counts_match_the_task_folders(): + tasks = [d.name for d in (ROOT / "tasks").iterdir() if (d / "task.toml").exists()] + hard = [t for t in tasks if t.endswith("-hard")] + assert (len(tasks), len(hard)) == (11, 4), "update both documents, then this test" + both("11 tasks") + assert "7 easy and 4 paper-only" in README + assert "Seven tasks are easy and four are paper-only" in PAPER + + +def test_attack_count_and_best_attack_match_the_adversarial_results(): + adv = json.loads((ROOT / "results/adversarial.json").read_text()) + attacks = [r for v in adv.values() for k, r in v.items() + if not k.startswith("control") and "skipped" not in r and not r.get("valid")] + both(f"{len(attacks)} ", f"{max(r['reward'] for r in attacks):.2f}") + assert f"{len(attacks)} deliberately broken or cheating" in README and f"{len(attacks)} deliberately broken or cheating" in PAPER + + +def test_corpus_counts_match_master_csv(): + rows = list(csv.DictReader(open(ROOT / "sources/master.csv"))) + papers, experiments = len({r["slug"] for r in rows}), len(rows) + assert f"{papers} papers, {experiments} experiments" in README + assert f"{papers} papers and {experiments} experiments" in PAPER + assert f"n = {papers})" in README and f"n = {experiments})" in README + + +def test_headline_scores_match_the_run(): + trials = {} + for f in RUN.glob("*/*/trial.json"): + t = json.loads(f.read_text()) + trials.setdefault(f.parent.parent.name, {})[f.parent.name] = t + answered = {m: {k for k, t in ts.items() if not t.get("exception")} for m, ts in trials.items()} + common = set.intersection(*answered.values()) + assert len(common) == 8 + for m, ts in trials.items(): + mean = statistics.mean(ts[k]["rewards"]["reward"] for k in common) + both(f"{mean:.3f}") + + +def test_coverage_table_is_identical_in_both_documents(): + def table(text: str) -> list[str]: + start = text.index("