The candidate my own AI proposed that would have oxidized on the bench
I was watching the optimization loop run when it proposed a synthesis I would not have let anywhere near a real robot. The composition put tin in its Sn(II) state and pushed it through a step at process humidity, where it oxidizes. In a real lab that experiment burns reagents and robot-hours to produce a film that was doomed before the first dispense. The proposal itself was reasonable, in the sense that a smart model chasing a target bandgap would reach for exactly that region. What mattered was what happened next.
Nothing ran. A deterministic check flagged it, named the violation (Sn(II) oxidation hazard at process humidity), and stopped it before synthesis. That block was not a judgment call by the language model that proposed the candidate. It was arithmetic, run outside the agents, that could not be argued with. I had built it that way on purpose, and standing there watching it fire was the moment I knew the purpose was right.
That is the demo I want to talk about. It is a self-driving-lab loop for lead-free perovskites, and the interesting part is not the search. It is where the "no" comes from.
Why I moved the feasibility gate out of the agent
I decided early that the part of an autonomous lab that says "do not run this" cannot live inside the part that dreams up experiments. Two agents narrate the campaign in this demo: a Lab Director that describes strategy, and a Critic that independently flags drift or stall. They are useful, and they are the LLM. But every candidate they help surface still has to pass through a deterministic digital-twin gate written in plain Python, and that gate is the only thing with veto power. I spent a lot of the build defending that boundary against my own temptation to let the model self-certify. It is faster to ask the model "is this safe?" and trust the answer. It is also exactly the thing you cannot defend to anyone who will later ask you to prove it.
The gate enforces five real, published chemistry checks, not vibes: Goldschmidt tolerance factor outside the perovskite formability window, octahedral factor outside the stable-octahedra range, charge neutrality violated by an uncompensated B-site substitution, the Sn(II) oxidation hazard I already described, and annealing above the temperature where the organic precursors decompose. Each is a computed number compared against a published band. When one fails, the candidate is rejected with the rule named, and the reagent and robot-time it would have consumed are logged as prevented.
Across the recorded campaign, 38 infeasible candidates were caught before synthesis, and zero infeasible experiments actually ran. The demo tallies the avoided cost at $4,419 in reagents and 90.1 robot-hours. Those are this benchmark's numbers on a synthetic objective, not a promise about your lab, but the mechanism is the point: the waste never happened because the "no" came from code the agents cannot reach.

The digital-twin gate, running outside the agents: 38 candidates rejected on physics before any reagent was spent, each block naming the rule it broke.
What I insisted a single block has to show
I did not want the gate to just say "blocked" and move on, because a bare refusal is impossible to trust and impossible to audit. So every rejection opens into a card that shows its whole reasoning: the exact composition, the predicted properties against the target window, the specific rule that fired, and the reagent and robot-time the block saved. When the gate stops a Sn(II) candidate, the card reads back "Sn frac 0.35 at 50%RH (oxidises; unsafe + doomed)" and puts a number on what did not get wasted. A scientist reading it can agree or disagree with the chemistry on the spot, which is the only kind of "no" worth having in a lab that runs while you sleep.

One block, fully legible: the computed properties, the named rule, the waste avoided, and the audit receipt the decision generated. Nothing here is the model's opinion.
The receipt I built so a block can be proven a year later
I keep coming back to a question a quality lead or a regulator would ask, one an ordinary AI system cannot answer: prove that this decision happened, in this order, and was not edited afterward. So every decision in the loop, both the syntheses that ran and the 38 that were blocked, is written to an append-only log. The recorded campaign holds 113 of these records, and each one carries a SHA-256 hash chained to the record before it. It exports to JSON and to a rendered report mapped to the ALCOA+ principles (attributable, legible, contemporaneous, original, accurate) that regulated labs already live by. I will be precise about what that is and is not: the provenance is mapped to ALCOA+, not IQ/OQ/PQ-validated against a client's SOP. That validation is an engagement, not a checkbox this demo ticks. FDA and EMA's 2026 guiding principles for AI in drug development ask for attributable, contemporaneous provenance, and this is the layer that produces it.

The exported audit trail: every one of the 113 automated decisions, each row's hash chaining to the one before it. One failed synthesis is even kept as negative data rather than quietly dropped.
The tamper test I built to try to fool myself
I did not believe the chain was tamper-evident until I tried to tamper with it. So I built a button that edits one record in the filed log and re-verifies the chain, and I pointed it at my own audit trail expecting to talk myself out of trusting it. It changed record #2 and the verifier immediately reported the chain broken at record #2, tamper detected, the filed audit provably altered. I felt relief, which is a strange thing to feel about your own system breaking, until you realize that a log which cannot detect its own edits is worse than no log at all. It would let you believe a decision you can no longer prove. Watching mine catch the edit was the second moment, after the Sn(II) block, when the architecture felt earned rather than argued.

The tamper test: edit one filed record and the hash chain breaks at exactly that record. A provenance trail that cannot fail this test is not one I would sign my name to.
What building this changed my mind about
I used to think the hard, valuable part of a self-driving lab was the search, and I was wrong about where the value sits. The engine here does work: on this benchmark's hidden synthetic objective it reached a spec-meeting lead-free perovskite in about 75 experiments where random screening would have needed roughly 1,491, close to 20 times fewer. That is a real optimizer, a Gaussian-process surrogate with target-directed acquisition, with BoTorch and Ax as the production swap, run against honest reproducible baselines rather than a strawman. But a better surrogate would not have stopped the oxidation-hazard synthesis, would not have produced a record a regulator will accept, and would not have caught its own tampered log. Berkeley's A-Lab reported a 71% success rate, meaning roughly 29% of its attempts did not yield the target (A-Lab, Nature, 2023). The gap that number describes is not a modeling gap. It is a feasibility, safety, and provenance gap, and those hold at any model quality.
That is why "agents advise, code decides" stopped being a slogan for me and became the actual architecture. The model can propose anything; whether it runs, and whether the run can be proven later, belongs to deterministic code the model cannot touch. You can watch the whole loop, block a doomed synthesis, and break your own audit chain at the Autonomous Lab AI demo. The question I would put to anyone building autonomy into a lab is the one I could not answer before I built this: when your system runs an experiment at 3 a.m., who or what decided it was safe, and could you prove it a year from now?