skills/pylabrobot/SKILL.md
Use PyLabRobot's hardware-agnostic frontends, resource tree, trackers, and device-specific backends to develop laboratory automation. Default to local manifest validation, bookkeeping, and the software-only chatterbox backend.
PyLabRobot==0.2.1, released 2026-03-23./stable/ documentation identifies itself as 0.2.1. /dev/ and repository
main describe unreleased work and must not be assumed available in 0.2.1.STARBackend, VantageBackend,
EVOBackend, OpentronsOT2Backend, and the offline
LiquidHandlerChatterboxBackend.v0.2.1 tag, and changelog as release evidence.Never connect to, initialize, home, move, heat, shake, spin, pump, open/close, or otherwise command physical equipment automatically. Do not turn a simulation plan into a live backend merely by changing an environment variable, config value, or import.
Before any separately authorized live run, require a trained human to:
Tracker state is bookkeeping, not sensing. It cannot prove that liquid or a tip is physically present. The Visualizer renders resource/tracker events; it does not model physics. Chatterbox prints planned operations; it does not prove calibration, reachability, collision freedom, liquid behavior, or device state.
Do not guess any of these:
uL, mm, uL/s, s), heights, rates, mixing, air gaps,
blowout, liquid properties, and validated vendor liquid class.If information is missing, produce an assumptions/blockers list and an offline draft only.
For offline API inspection and chatterbox simulation:
uv venv --python 3.11 .venv-pylabrobot
uv pip install --python .venv-pylabrobot/bin/python "PyLabRobot==0.2.1"
On Windows, use .venv-pylabrobot\Scripts\python.exe. Do not install hardware
extras until the user names the device and explicitly approves its transport
dependencies. Then inspect the matching stable device page before considering a
pin such as "PyLabRobot[serial]==0.2.1" or "PyLabRobot[usb]==0.2.1".
Run from the repository root. Every bundled CLI uses strict, bounded UTF-8 JSON/CSV, local non-symlink paths, fixed allowlists, and JSON output. None can select a live backend.
python3 skills/pylabrobot/scripts/validate_manifest.py \
--input skills/pylabrobot/tests/fixtures/protocol_manifest.json
python3 skills/pylabrobot/scripts/check_deck_geometry.py \
--input skills/pylabrobot/tests/fixtures/protocol_manifest.json
python3 skills/pylabrobot/scripts/plan_transfers.py \
--manifest skills/pylabrobot/tests/fixtures/protocol_manifest.json \
--transfers skills/pylabrobot/tests/fixtures/transfers.csv
python3 skills/pylabrobot/scripts/generate_simulation_plan.py \
--manifest skills/pylabrobot/tests/fixtures/protocol_manifest.json \
--transfers skills/pylabrobot/tests/fixtures/transfers.csv
python3 skills/pylabrobot/scripts/inspect_backends.py \
--expected-version 0.2.1 --strict
The geometry checker uses conservative static axis-aligned boxes; it is not a
motion planner. The transfer planner requires one new tip per row and checks
source/dead/destination volumes, tip capacity, wells, channels, heights, rates,
units, and allowlists. Review
assets/protocol-manifest.schema.json and the synthetic fixtures before making
a project-specific manifest.
The exact backend below is software-only. Do not substitute a hardware backend.
from pylabrobot.liquid_handling import LiquidHandler
from pylabrobot.liquid_handling.backends import LiquidHandlerChatterboxBackend
from pylabrobot.resources import (
Cor_96_wellplate_360ul_Fb,
PLT_CAR_L5AC_A00,
TIP_CAR_480_A00,
hamilton_96_tiprack_1000uL_filter,
set_tip_tracking,
set_volume_tracking,
)
from pylabrobot.resources.hamilton import STARLetDeck
set_tip_tracking(True)
set_volume_tracking(True)
deck = STARLetDeck()
tip_carrier = TIP_CAR_480_A00(name="tip_carrier")
tips = hamilton_96_tiprack_1000uL_filter(name="tips")
tip_carrier[0] = tips
plate_carrier = PLT_CAR_L5AC_A00(name="plate_carrier")
source = Cor_96_wellplate_360ul_Fb(name="source")
destination = Cor_96_wellplate_360ul_Fb(name="destination")
plate_carrier[0] = source
plate_carrier[1] = destination
deck.assign_child_resource(tip_carrier, rails=3)
deck.assign_child_resource(plate_carrier, rails=15)
source.get_well("A1").tracker.set_volume(100.0) # planned state, not sensing
lh = LiquidHandler(backend=LiquidHandlerChatterboxBackend(), deck=deck)
await lh.setup() # safe here only because the backend above is software-only
try:
await lh.pick_up_tips(tips["A1"])
await lh.aspirate(source["A1"], vols=[10.0])
await lh.dispense(destination["A1"], vols=[10.0])
await lh.return_tips()
finally:
await lh.stop()
STARBackend, VantageBackend, EVOBackend, and
OpentronsOT2Backend; do not use stale STAR, TecanBackend,
OpentronsBackend, or ChatterboxBackend imports.LiquidHandlerChatterboxBackend for generic offline liquid-handler
testing. ChatterBoxBackend is a separate legacy-named export; do not
conflate the two.Visualizer(resource=...) is valid, followed by await vis.setup() and
await vis.stop(); it starts localhost HTTP/WebSocket servers and may open a
browser.from pylabrobot.liquid_handling import LiquidClass in
0.2.1. Stable liquid classes are vendor-specific, for example
pylabrobot.liquid_handling.liquid_classes.hamilton.HamiltonLiquidClass.Checked 2026-07-23:
v0.2.1 source tag
and changelog
— tag dated 2026-03-23; Unreleased is development-only.