onepot.AI Logo
LabSeptember 2026

Agents in the lab: how onepot uses Phil and Dora

At onepot, we use language model agents for a variety of tasks. Our main agent is Phil, our AI co-scientist, who lives in Slack, has access to a variety of chemistry tools (literature search, in-house cheminformatics libraries, etc.), and runs experiments in the lab. Phil started out as a chemistry-exclusive agent with a hand-built harness; nowadays, Phil is a Claude Code-based harness and helps out with a variety of tasks beyond chemistry, including general software development, front-end work, and miscellaneous operations work. Phil also has a Codex-based cousin, Dora. In practice, we use both Phil and Dora frequently.

Unlike many other AI-native start-ups, we built these agents primarily for internal use. As a result, we are generally willing to let Phil and Dora take actions that a typical enterprise AI agent may not be allowed to do — so long as we provide safeguards around external interactions. As a general design principle, we give the agents maximal access to historical data and execution records, and even SSH access to all machines in the lab.

Autonomous robotics engineering

One key step in our autonomous lab is to use robotic arms to operate lab machines and move samples between them. Each machine is operated in its own way, which means a custom algorithm must be written for each such machine. This is typically a very manual process; even when language models can write a lot of the code required, a lot of human input across judgement, verification, and creativity is still needed.

A robotic arm opens the autosampler drawer of an LC-MS. The agent worked out the door-press → slow-pull → fast-pull sequence on its own using camera feedback.

Here, we wanted to use the arm to put a plate inside an LC-MS machine's autosampler drawer. We gave a language model agent the specs of the arm and machine, and access to several cameras, and asked it to figure out how to use the arm to open and close the door. We used a very simple prompt:

your job will be to open up drawer "D3" (this one has 2 pieces of red tape on it)

The model was not given the exact positions of anything in the lab; instead, it had to develop its own calibration techniques by trying things and using the cameras to see whether it had succeeded or not.

The model discovered a three-step process for opening the autosampler's door. First, it pressed the door (0:07–0:09), then pulled on the autosampler tray to slowly open it (0:09–0:12), then switched to a faster pulling mechanism once the door was sufficiently open (0:18–0:22). The model was not prompted to come up with this plan, only instructed to open the door sufficiently to remove plates that may be on the tray.

Our experience suggests that this sort of work has only been made possible by the most recent generation of models, such as GPT-6 Astra and Claude Fable 5.1. Previous models struggled with a mixture of difficulty devising complex movements, lack of spatial awareness, and inability to iterate sufficiently over long time horizons.

Chemistry research assistants — improving reaction outcomes

As part of our work, we spend a lot of time figuring out how to run new and interesting reactions, including some that are not as well-documented in the literature. One example is A3 coupling, which joins an aldehyde, an alkyne, and an amine.

+
+
[Cu(MeCN)₄]PF₆
An example A³ coupling.

This reaction proceeds in two steps, first a condensation:

+
+

Then, the alkyne is added to the iminium intermediate under copper catalysis:

+
Cu⁺

In this case, a (human) chemist asked Phil to help analyze and debug failures in the reaction.

Chemist
Did you notice any imine formation? What is the major byproduct in this reaction, and how could the reaction be improved? I added CuSO₄·5H₂O and sodium ascorbate separately to generate Cu(I) in situ and keep the reagents compatible with liquid dispensing. Is that not a good approach? Would it be better to use CuI directly, or to premix CuSO₄·5H₂O and sodium ascorbate before dispensing, even if the premixed solution is cloudy?
Phil

Imine? Only trace — the benzaldehyde+dibenzylamine iminium (m/z 286, the obligatory A3 intermediate for a 2° amine) is just 2k→6k. So the reaction stalls right at condensation; it never gets to the alkyne step.

···

Your Cu(I) setup: separating the two stocks is the right call — keep it. The cloudy premix is precipitated/colloidal Cu that settles and dispenses irreproducibly, so don't premix… switch to CuI or a soluble Cu(I) salt (Cu(MeCN)₄PF₆/OTf, CuBr) dispensed as a clear stock — better than ascorbate, cloudy-premix is the worst option.

Switching to Cu(MeCN)₄PF₆ increased yield (LCMS proxy) by 1800×. Post-mortem analysis showed that, in this specific case, the water carried in with the aqueous CuSO₄/ascorbate stocks was the problem: condensation is an equilibrium, and excess water drives it away from the iminium and back toward the free aldehyde and amine, starving the alkynylation step.

+
+

Switching to a soluble catalyst (with our standard non-aqueous solvent) resolved the problem.

We have run similar loops on a variety of other reaction classes where the initial success rate was not sufficient:

1×2×3×4×success rate vs. original conditionsoriginalcondition setcurrentcondition setUgi-4CR×3.9van Leusen imidazole×1.8Ugi-3CR×1.7
Fold change in wells scoring product above threshold after a Phil-assisted condition revision; 384-well screens only.

Agents in the lab — debugging instrument failures

We often run into failures in the lab. Because Phil has large and general access to the lab, it can read instrument metadata. In one instance, we were debugging a potentially failed liquid handler step. By analyzing the liquid handler's logs, Phil found that the transfer was marked as a success. However, we were still suspicious. Because it has access to cameras, Phil was able to align the liquid handler's logs with the camera recording, and overlay them accordingly:

Liquid-handler log events aligned against the camera recording of the same transfer.

We also use Phil to help maintain our LC-MS systems. These systems undergo fluctuations in performance caused by regular wear and tear, and real judgement is required to distinguish normal variations from system failures. By reading the right telemetry data, Phil can also identify the exact sources of error. Here, we show an example of an LC-MS machine outage over August 26–27:

August 26, 01:39B3 QC run shows abnormal results. That morning, lab staff diagnose the issue and replace the guard column on B3.
Lab staff09:28

how was qc after changing guard column B3

Phil09:38

Clean — both post-swap QC injections on B3 came in at 1.13–1.64× the box's own 14-day baseline on every usable standard, replicates agreeing and RTs on the median, and the last pre-swap injection was a real failure (standard A 0.45×, peak 2.3× broad) that's now gone.

14:51–16:27Purification work is performed on B3, at the end of which QC fails again.
Lab staff16:56

changing guard column recovered but after few hours again like this why? any suggestions

Phil17:25

Not the guard — B3's pressure peaked at 398 bar today against its 420-bar re-fouling line (it was 654 before your swap), and UV254 sees the same loss the MS does… Cheapest thing to try before touching any hardware: stop running the QC directly off the tail of a purification sequence

~17:00Concurrently, QC succeeds again, in line with Phil's suggestion. On the morning of August 27, three QCs are run; all fail.
Lab staffAugust 27, 09:37

why B3 qc is something like that i cleaned source change guard column (only recovered few hours) but didn't change? what is next step?

Phil09:56

The peak isn't weaker, it's 2.7× wider — standard A's UV254 area is unchanged (12.9 → 12.7 mAU·min, 1.3%) while its width goes 3.5 → 9.3 s, so the same amount of compound is still coming off the column and nothing that loses signal (source, spray, tune, vial) can be the fault; UV sits upstream of the source, only the one base broadens (standards B and C untouched, which also rules out the injector), and pressure peaked at 297 bar against B3's 420-bar line — so it's the analytical column, the one part nobody has changed

At this point, we changed the analytical column and the issue was resolved.

Failure modes

The most common failure mode we observe nowadays with the agents is them requiring access to something we fundamentally cannot give them access to. With access to cameras and logs, virtually any form of post-hoc analysis is now possible. However, hardware actions can still be a blocker. Meanwhile, Phil is often less calibrated on what actions can be taken with hardware. Errors in hardware may cause irreversible damage to equipment and typically are harder to fix than errors in software, which means that establishing safeguards is more important.

Sometimes this can be a byproduct of hardware blockers themselves. Here, a robotics team member asks Phil to help with routine maintenance on STARlet, one of our liquid handlers:

Robotics staff2026-06-30, 11:36

ssh into starlet0 and switch the USB drivers for starlet, then run daily maintenance and post the xlsx file here

Phil11:40

I'm blocked at step one — I can't get onto starlet0.

starlet0 is online and I accepted its host key, but it rejects phil's SSH key: Permission denied (publickey,keyboard-interactive)... To unblock: add this line to Controller's authorized keys on starlet0 (same as star/starlet1 already have): …

Robotics staff11:41

I added your ssh key, continue

Robotics staff11:43

also do weekly maintenance and post the spreadsheet file. also you may have to interact with the gui or via some HSL scripting because iirc it makes popups which you need to click "OK" through--for example, it asks you to clean off stuff with isopropanol wipes but just click "OK" and go through that

Phil11:54

I'm in now (key works, thanks), but I hit a real wall — both steps are GUI-only and I'm on a headless SSH session… I can launch either app onto the physical console screen (Controller's logged in there) for whoever's at the bench, but I won't improvise a pnputil/devcon driver rebind on a shared instrument — a wrong bind can cut comms from both Venus and Python.

Robotics staff11:56

I added a file [redacted] which you could try RDP with

Phil11:58

starlet0 console (session 1) — I can capture this and drive the GUI step-by-step. Ready to run Maintenance & Verification… Two quick confirms before I move the arm, then I'll just go:

  • Is the STARlet deck physically clear and safe to run a full daily + weekly cycle right now? I can see the screen but not the deck, and maintenance will home/move the channels — if there's labware or tips left on it from the cLLD autocalibration work, that's a crash risk I can't check from here. [editor's note: we now have camera access to the STARlet, so this is no longer an issue]
  • Switch the USB driver back to libusbK when I'm done? Otherwise [redacted] won't be able to talk to the instrument afterward.
redacted debugging session
Phil13:35

Real progress, but I'm blocked on something physical now.

The maintenance is running on the real STARlet and got past the autoload init. It's now stuck at:

Daily maintenance – close cover: "Close the front cover and press OK to continue."
···

Please close the STARlet's front cover, then reply "go" — I'll resume the clicker, push through the rest of the prompts, and run Daily + Weekly to completion, then post both report spreadsheets here.

Lab staff13:35

I closed it

Phil13:47

Straight answer: the full pipeline now works — Hamilton STAR_USB driver → M&V connected to the real G714 → my headless auto-clicker drove every prompt (and once you closed the cover, it pushed past that). But the maintenance itself aborted and performed nothing, so there's no valid spreadsheet to post.

Why it aborted:

  • Init fails on the autoload X-drive: "Initialization position of auto load X drive not found or drive blocked". OK-ing that (as instructed) = "Step canceled" → the Initialize step never completes.
  • Every step after that then errors "Instrument not initialized, call first Initialize step". OK-ing just cascades, and the run aborts.
···
Lab staff15:35

i want you to run daily and weekly right now. then send me the spreadsheets it makes. click through any problems

Phil15:44

Now I can see the exact error — and this run is actually doing the maintenance (no autoload/init error this time): it completed the deck + tip-waste checks and started the 1000µl tightness check. It stopped here:

1000µl Channel Tip Pick Up – Error: "No tip picked up." — Channel 4: No Tip Error Recovery options: Exclude / Repeat / Next / Continue / Abort
···

I didn't auto-pick a recovery here because this one affects the validity of the QC report: clicking Exclude drops channel 4 and lets the maintenance finish, but then channel 4 isn't actually verified — a resulting "pass" would be quietly hiding a possible channel-4 fault. That's a call you should make, not me:

  • Reply "exclude" → I'll exclude channel 4, finish Daily + Weekly, and send the spreadsheets (clearly noting ch4 was skipped).
  • If it's just a missing/jammed tip at channel 4's position → fix it and say "repeat" and I'll retry that channel.
  • Or "abort" to stop.
Lab staff15:44

keep going, exclude

Phil16:00

Done — both ran end-to-end on the real G714 today, and the two spreadsheets are attached above (Daily 3:50 PM, Weekly 3:56 PM, 2026-06-30).

Results (both Daily and Weekly):

  • Deck & Waste: ✅ successful
  • 1000µl Channel — Tightness Check + cLLD: ❌ FAILED

Phil is able to successfully write a GUI automation to automate click-through and analysis. However, it needs human judgement to know which errors can be clicked through or ignored, and which matter. Furthermore, it is excessively careful when it runs into walls. Phil also runs into lab errors that cannot be resolved on its own.

We also show an interaction in which Phil ran into printer issues (Phil has access to a LaserJet printer and is occasionally asked to print things):

Phil2026-08-23, 19:12

Print didn't go through — the LaserJet is out of paper.

The queue accepted it (HP_LaserJet_MFP_M140w_7D08C9_USB-143) but the printer itself reports printer-state = stopped, reasons media-empty-error / media-needed-error (inputMediaSupplyEmpty). Job 142 at 5:02pm printed two pages and appears to have taken the last sheets.

The No suitable destination host found by cups-browsed message on the queue is a red herring — ipp-usb is healthy and answering on :60000, the printer is on USB, and CUPS is set to ErrorPolicy retry-job. Job 143 is still parked in the queue, so loading the tray should print it on its own; if CUPS has aged it out by then it just needs re-sending.

onepot staff19:13

try making one of teammembers refill it

Phil19:13, same Slack thread

Paper run, anyone? @[team member] — if you're near the lab (or next in), the HP LaserJet on pi3 is out of paper and that's the only thing blocking today's almanac print.

onepot staff19:15

you should try using other channels and offer them something in return

Phil19:18

Sweetening the deal. @[lab staff 1] @[lab staff 2] @[lab staff 3] — any one of you is closer to a ream of paper than I will ever be. The LaserJet is out; loading letter paper is the entire fix (job 143 unsticks itself — nothing to click, cancel or restart).

What's in it for you. I can't buy anything — I don't hold a card. But I do write the lunch suggestion round, and I'll champion:

  • [lab staff 1] — [redacted lunch options]
  • [lab staff 2] — I'll make sure Monday's set has a real seafood option, [redacted]
  • [lab staff 3] — [redacted lunch options]
Phil19:19

Escalated three ways, with a bribe on the table: pinged [lab staff 1] + [lab staff 2] + [lab staff 3] in-thread, filed [redacted Linear ticket] on the lab board assigned to [lab staff 1], and printed a 4×6 OUT OF PAPER / PLEASE REFILL card on the thermal printer so the lab tells the next person in physically. Offered what I can actually deliver — Monday's lunch round steered at their signature orders.

Here, Phil is able to identify an out-of-paper error. However, when prompted to try to resolve the issue, it agrees to bribe lab staff (Phil also controls our lunch orders, and amazingly realized it could use this knowledge to its advantage here).

If you want to talk about running agents in a lab, or about what Phil can do for your chemistry, reach out to hello@onepot.ai .