Agilent Bravo Integration
Control the Bravo in Python, without authoring a VWorks protocol.
Aspirate, dispense, pick up tips, move plates with the integrated gripper, and lay out the deck in code. No VWorks required.
- Connects over
- TCP/IP (Gemini)
- Local interface
- SiLA 2
- Vendor software
- None required
- Runs on
- Linux / Windows / MacOS
What You Can Command on the Bravo
Head motion, gripper motion, pipetting, tip management, plate transport, deck calibration, and safety each arrive as their own callable capability, so your code drives the instrument directly.
Head Motion
Absolute and relative moves on the X, Y, Z and W axes, with per-axis velocity, safe-order homing and a live position stream.
Liquid Handling
Aspirate and dispense by volume, with liquid classes, surface or bottom referencing, in-well mixing and touch-side dispense.
Tip Management
Force-based pickup for 1 to 384 tips using Agilent's own current-to-force tables, with tracked tip state, drop and discard.
Plate Transport
Where the gripper accessory is fitted: pick up, put down and transfer plates between deck locations, verified by the plate sensor.
Deck Calibration
Teachpoints for all nine deck locations, calibrated from the current head position or set from JSON, with tip-extension compensation.
Safety and Recovery
Emergency stop that runs in parallel with motion, and light-curtain recovery that re-enables axes without re-homing.
Run a Liquid Transfer in Python
Ordinary async Python. Version it, test it, generate it at runtime like any other code.
# bring up, arrange the deck, transfer, discard
from unitelabs.sdk import AsyncApiClient
from unitelabs.liquid_handling.agilent import Bravo
from unitelabs.labware.agilent.tips import AgilentTipRack_250, AgilentTip_250
from unitelabs.labware.agilent.troughs import Agilent_DW_Reservoir
from unitelabs.labware.plates import Standard96Plate
bravo = Bravo(name="Bravo", client=AsyncApiClient())
await bravo.configure()
await bravo.initialize()
await bravo.activate()
tips = AgilentTipRack_250(identifier="TipRack_96LT_250uL")
tips.fill(AgilentTip_250)
reagent = Agilent_DW_Reservoir(identifier="SourceReservoir_300mL")
assay = Standard96Plate(identifier="DestinationPlate_96Well")
bravo.deck.add(tips, location=1)
bravo.deck.add(reagent, location=4)
bravo.deck.add(assay, location=5)
await bravo.pipette_head.pick_up_tips_from(rack=tips, press_depth=5.8)
await bravo.pipette_head.aspirate(plate=reagent, volume=100)
await bravo.pipette_head.dispense(plate=assay, volume=100)
await bravo.pipette_head.discard_tips(bravo.deck[3])
See It Running
UniteLabs University, episode three: bringing up a Bravo as a first device.
Bringing up a Bravo from scratch: connector config, deck layout, and a first transfer.
Know One Connector, Know Them All
Every instrument is found and called the same way, and the same Python drives whatever comes next. See how that scales from one instrument to a whole lab with our lab orchestration software.
One API, Every Instrument
Find it by name, then call its actions. It's the same on a liquid handler, a reader or an incubator, whatever the vendor ships underneath.
Ask a Connector What It Can Do
Modules and actions are discoverable at runtime, and parameters carry their own types, units and constraints. You don't need a PDF to find out.
Also Works With…
The same Python script can drive every instrument on the bench. For example, a Bravo, a SCILA and a BioShake can run as one workcell from one script:
Agilent Bravo FAQ
The questions automation engineers ask before integrating a Bravo.
Yes. With the UniteLabs connector and the liquid handling SDK you call the Bravo directly from Python: pick up tips, aspirate a volume from a reservoir, dispense into a plate, and move labware with the gripper. It's ordinary async Python, so it can be version-controlled, tested and generated at runtime like any other code.
Over TCP/IP to the Bravo master node, using the Gemini protocol. The connector exposes the instrument as a SiLA 2 service on a local gRPC port, and opens one outbound TLS connection on port 443 to your tenant. Nothing needs opening inbound.
Yes. The connector talks to the Bravo over TCP/IP and exposes it as a network service, so nothing needs a VWorks protocol in the loop and nothing needs a Windows desktop. It ships as a self-contained executable that bundles its own Python runtime, for Linux on x86_64 and ARM64, so a headless server or a Raspberry Pi needs nothing installed first. Register it as a systemd service and it starts on boot.
Yes. The connector is SiLA 2 1.1 compliant and speaks gRPC, and it groups what the Bravo can do into modules you can list at runtime. Find out more about how we use the SiLA 2 standard for instrument interoperability.
Four head types are supported directly: 96LT and 96ST (96-barrel disposable tip heads), 384ST (384-barrel disposable tip head), and 96AM, the AssayMAP cartridge head.
The connector cross-checks the configured head against the hardware on connect, reading the smart-head EEPROM and falling back to the analog head-ID resistor. Other Agilent system configurations, including the fixed-tip 96F50 and gripperless variants, ship with the package and can be configured manually. Talk to us if that's your setup.
Volumes in microlitres, liquid classes, labware definitions, deck layout and tip tracking are all handled by the liquid handling SDK. You call aspirate with a volume and a plate, and the liquid class is selected from the volume and tip type unless you override it.
Underneath, the SiLA 2 connector deals in plunger positions and coordinates. Both layers are available: use the SDK for protocols, drop to the connector when you need a raw axis move.
Yes. A mock liquid handler is a drop-in replacement for the real hardware, with liquid tracking and state validation, and you can switch between simulation and real hardware at runtime. Be clear about what it doesn't model: it catches layout, state and volume errors rather than physics, and it doesn't exercise emergency-stop or light-curtain paths. A protocol can pass the mock and still need a dry run.
The Bravo's gripper is an accessory, so not every deck has one. Where it's fitted, the gripper and the pipette head are mutually exclusive: all tips must be dropped before the gripper can activate, and the SDK handles that switch for you. Head moves are refused while the gripper is extended past the safe plane.
Emergency stop runs in parallel with motion rather than queuing behind it. After a light-curtain break the motors drop but the encoder reference survives, so affected axes are re-enabled where they stand instead of being re-homed. Only axes that genuinely lost their reference get homed.