Supported today Liquid Handling

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.

How it works

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.

One Outbound Connection

One outbound TLS connection on port 443 to your tenant, so nothing needs opening inbound. Ports, hostnames and setup are in the docs.

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:

FAQ

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.

Tell us what you want to automate

Put Your Bravo to Work