| name | opentrons-gripper |
| description | Opentrons Flex Gripper - automated labware movement between deck locations, modules, waste chute, and off-deck storage with precise positioning and offset control for hands-free plate transfers |
| allowed-tools | * |
Opentrons Flex Gripper
Overview
The Opentrons Flex Gripper enables fully automated labware movement without manual intervention. It moves plates, reservoirs, and tip racks between deck slots, hardware modules, trash/waste chute, and off-deck storage with precise positioning and optional offset adjustments.
Core value: Eliminate manual plate transfers during protocols. Automatically move labware between modules, enabling complex multi-step workflows without pausing for user intervention.
Platform: Opentrons Flex only (not available on OT-2)
When to Use
Use the Gripper skill when:
- Moving labware between deck locations automatically
- Transferring plates between hardware modules (Temperature, Heater-Shaker, Magnetic Block, etc.)
- Loading plates onto Absorbance Reader or Thermocycler
- Disposing labware in waste chute
- Moving labware to/from off-deck storage
- Automating workflows that would otherwise require manual intervention
Don't use when:
- Working with OT-2 robot (gripper is Flex-only)
- Labware is not grippable (lacks compatible geometry/features)
- Manual control is preferred for delicate operations
- Pipette can accomplish the task without moving entire labware
Quick Reference
| Operation | Method | Key Parameters |
|---|---|---|
| Move labware | protocol.move_labware() |
labware, new_location, use_gripper=True |
| Move with offsets | protocol.move_labware() |
pick_up_offset, drop_offset |
| Move to module | protocol.move_labware() |
labware, module_object, use_gripper=True |
| Dispose in waste | protocol.move_labware() |
labware, waste_chute, use_gripper=True |
| Move off-deck | protocol.move_labware() |
labware, OFF_DECK, use_gripper=True |
| Manual movement | protocol.move_labware() |
use_gripper=False (pauses for user) |
Platform Requirements
Opentrons Flex only
- API version: 2.15+ (gripper support)
- Robot type: Must specify
"robotType": "Flex"
Basic Usage
Moving Between Deck Slots
from opentrons import protocol_api
metadata = {'apiLevel': '2.19'}
requirements = {"robotType": "Flex", "apiLevel": "2.19"}
def run(protocol: protocol_api.ProtocolContext):
# Load labware
source_plate = protocol.load_labware("corning_96_wellplate_360ul_flat", "C1")
# Move labware to new deck slot
protocol.move_labware(
labware=source_plate,
new_location="D2",
use_gripper=True
)
Deck slot formats (both work):
- Coordinate format: "A1", "B2", "C3", "D1" (preferred for Flex)
- Numeric format: "1", "2", "3", etc. (OT-2 legacy, still compatible)
Moving to Hardware Module
# Load module and labware
temp_mod = protocol.load_module("temperature module gen2", "D1")
plate = protocol.load_labware("corning_96_wellplate_360ul_flat", "C2")
# Move plate to temperature module
protocol.move_labware(
labware=plate,
new_location=temp_mod,
use_gripper=True
)
Moving to Waste Chute
# Load waste chute
waste_chute = protocol.load_waste_chute()
# Dispose of used plate
protocol.move_labware(
labware=used_plate,
new_location=waste_chute,
use_gripper=True
)
Moving Off-Deck
from opentrons.protocol_api import OFF_DECK
# Move labware off the deck (to storage)
protocol.move_labware(
labware=archive_plate,
new_location=OFF_DECK,
use_gripper=True
)
# Later: bring back from off-deck storage
protocol.move_labware(
labware=archive_plate,
new_location="B3",
use_gripper=True
)
Use case: Free up deck space by temporarily storing labware off-deck
Position Offsets
Fine-tune pickup and drop positions with offset vectors:
Basic Offset Syntax
protocol.move_labware(
labware=plate,
new_location="D2",
use_gripper=True,
pick_up_offset={"x": 0, "y": 0, "z": 2}, # Lift 2mm higher when picking up
drop_offset={"x": 0, "y": 0, "z": 1} # Place 1mm higher when dropping
)
Offset units: Millimeters Coordinates:
- x: Left (-) / Right (+)
- y: Back (-) / Front (+)
- z: Down (-) / Up (+)
When to Use Offsets
Pick-up offset:
- Labware sits higher/lower than expected
- Adapters or custom labware with non-standard height
- Ensure proper gripper engagement
Drop-off offset:
- Ensure proper seating on module or adapter
- Accommodate non-standard landing surfaces
- Avoid collision with deck features
Example with Custom Labware
# Custom deep-well plate requires higher pickup
custom_plate = protocol.load_labware("custom_deepwell_96", "C1")
protocol.move_labware(
labware=custom_plate,
new_location="D1",
use_gripper=True,
pick_up_offset={"x": 0, "y": 0, "z": 3}, # Pickup 3mm higher
drop_offset={"x": 0, "y": 0, "z": 0} # Standard drop
)
Manual Movement Alternative
Set use_gripper=False to pause protocol for user to manually move labware:
# Pause for manual movement
protocol.move_labware(
labware=delicate_plate,
new_location="D3",
use_gripper=False # Protocol pauses, user moves plate manually
)
Use case: Delicate labware, non-grippable items, or troubleshooting
Module Integration
Temperature Module
temp_mod = protocol.load_module("temperature module gen2", "D1")
plate = protocol.load_labware("corning_96_wellplate_360ul_flat", "C2")
# Move to temperature module
protocol.move_labware(plate, temp_mod, use_gripper=True)
# Set temperature
temp_mod.set_temperature(4)
protocol.delay(minutes=5)
# Move off module
protocol.move_labware(plate, "C2", use_gripper=True)
temp_mod.deactivate()
Heater-Shaker Module
Critical: Open labware latch before gripper operations
hs_mod = protocol.load_module("heaterShakerModuleV1", "D1")
adapter = hs_mod.load_adapter("opentrons_96_flat_bottom_adapter")
plate = protocol.load_labware("corning_96_wellplate_360ul_flat", "C2")
# Open latch BEFORE moving plate to module
hs_mod.open_labware_latch()
# Move plate to heater-shaker
protocol.move_labware(plate, hs_mod, use_gripper=True)
# Close latch for shaking
hs_mod.close_labware_latch()
hs_mod.set_and_wait_for_temperature(37)
hs_mod.set_and_wait_for_shake_speed(500)
protocol.delay(minutes=10)
hs_mod.deactivate_shaker()
hs_mod.deactivate_heater()
# Open latch BEFORE removing plate
hs_mod.open_labware_latch()
# Move plate off module
protocol.move_labware(plate, "C2", use_gripper=True)
Thermocycler Module
Critical: Open lid before gripper operations
tc_mod = protocol.load_module("thermocyclerModuleV2")
plate = protocol.load_labware("opentrons_96_wellplate_200ul_pcr_full_skirt", "C2")
# Open lid BEFORE moving plate to thermocycler
tc_mod.open_lid()
# Move plate to thermocycler
protocol.move_labware(plate, tc_mod, use_gripper=True)
# Close lid and run PCR
tc_mod.close_lid()
tc_mod.set_lid_temperature(105)
# ... PCR cycling ...
# Open lid BEFORE removing plate
tc_mod.open_lid()
# Move plate off thermocycler
protocol.move_labware(plate, "C2", use_gripper=True)
Magnetic Block (Flex)
mag_block = protocol.load_module("magneticBlockV1", "D1")
mag_plate = protocol.load_labware("biorad_96_wellplate_200ul_pcr", "C2")
# Move plate to magnetic block for bead separation
protocol.move_labware(mag_plate, mag_block, use_gripper=True)
# Wait for beads to collect
protocol.delay(minutes=3)
# Pipette supernatant (beads held by magnets)
pipette.transfer(150, mag_plate.wells(), waste.wells())
# Move plate off magnets for resuspension
protocol.move_labware(mag_plate, "C2", use_gripper=True)
Absorbance Plate Reader
Critical: Reader lid must be open before gripper operations
reader = protocol.load_module("absorbanceReaderV1", "D3")
assay_plate = protocol.load_labware("corning_96_wellplate_360ul_flat", "C2")
# Initialize reader
reader.close_lid()
reader.initialize(mode="single", wavelengths=[450])
# Open lid BEFORE moving plate to reader
reader.open_lid()
# Move plate to reader
protocol.move_labware(assay_plate, reader, use_gripper=True)
# Close lid and read
reader.close_lid()
data = reader.read()
# Open lid BEFORE removing plate
reader.open_lid()
# Move plate off reader
protocol.move_labware(assay_plate, "C2", use_gripper=True)
Common Patterns
Multi-Module Workflow
# DNA extraction with module transfers
sample_plate = protocol.load_labware("biorad_96_wellplate_200ul_pcr", "C1")
hs_mod = protocol.load_module("heaterShakerModuleV1", "D1")
mag_block = protocol.load_module("magneticBlockV1", "D2")
temp_mod = protocol.load_module("temperature module gen2", "D3")
# 1. Lysis on heater-shaker
hs_mod.open_labware_latch()
protocol.move_labware(sample_plate, hs_mod, use_gripper=True)
hs_mod.close_labware_latch()
hs_mod.set_and_wait_for_temperature(56)
hs_mod.set_and_wait_for_shake_speed(1000)
protocol.delay(minutes=15)
hs_mod.deactivate_shaker()
hs_mod.deactivate_heater()
hs_mod.open_labware_latch()
# 2. Bead binding on magnetic block
protocol.move_labware(sample_plate, mag_block, use_gripper=True)
protocol.delay(minutes=3)
pipette.transfer(150, sample_plate.wells(), waste.wells())
# 3. Elution on temperature module (cold)
protocol.move_labware(sample_plate, temp_mod, use_gripper=True)
temp_mod.set_temperature(4)
pipette.transfer(50, elution_buffer, sample_plate.wells())
# 4. Return to deck
protocol.move_labware(sample_plate, "C1", use_gripper=True)
temp_mod.deactivate()
Plate Stacking Workflow
# Process multiple plates sequentially
plates = [
protocol.load_labware("corning_96_wellplate_360ul_flat", "C1"),
protocol.load_labware("corning_96_wellplate_360ul_flat", "C2"),
protocol.load_labware("corning_96_wellplate_360ul_flat", "C3")
]
reader = protocol.load_module("absorbanceReaderV1", "D3")
reader.close_lid()
reader.initialize(mode="single", wavelengths=[600])
reader.open_lid()
for i, plate in enumerate(plates):
# Read each plate
protocol.move_labware(plate, reader, use_gripper=True)
reader.close_lid()
data = reader.read(export_filename=f"plate_{i+1}_od600")
reader.open_lid()
# Move to off-deck storage
protocol.move_labware(plate, OFF_DECK, use_gripper=True)
Waste Management
# Dispose of used consumables
waste_chute = protocol.load_waste_chute()
# After using tip rack
protocol.move_labware(empty_tips, waste_chute, use_gripper=True)
# After processing sample plate
protocol.move_labware(used_plate, waste_chute, use_gripper=True)
Dynamic Deck Space Management
# Free up deck space by moving inactive labware off-deck
storage = OFF_DECK
# Initial setup - plates start on deck
plate_1 = protocol.load_labware("corning_96_wellplate_360ul_flat", "B1")
plate_2 = protocol.load_labware("corning_96_wellplate_360ul_flat", "B2")
plate_3 = protocol.load_labware("corning_96_wellplate_360ul_flat", "B3")
# Process plate 1
# ... operations on plate_1 ...
# Move plate 1 off-deck to free space
protocol.move_labware(plate_1, storage, use_gripper=True)
# Process plate 2
# ... operations on plate_2 ...
# Retrieve plate 1 when needed again
protocol.move_labware(plate_1, "B1", use_gripper=True)
Grippable Labware
The gripper can only move labware with compatible geometry.
Compatible Features
Labware must have one of:
- Gripper-compatible rim - Extended lip or ridge for gripper jaws
- Side grips - Indentations or features on sides
- Opentrons-certified labware - Verified gripper compatibility
Checking Compatibility
Most Opentrons labware and major brands (Corning, NEST, Axygen, Bio-Rad) are gripper-compatible. Check labware definition or test before protocol deployment.
Non-Grippable Labware
Examples of labware that may NOT be grippable:
- Very small tubes or vials without grip features
- Irregularly shaped containers
- Custom labware without gripper considerations
- Delicate or fragile items
Solution: Use use_gripper=False to prompt manual movement, or use adapters.
Best Practices
- Open module lids/latches before gripper movement - Required for Heater-Shaker, Thermocycler, Absorbance Reader
- Use descriptive variable names - Track labware clearly through movements
- Test with simulation first - Verify gripper movements before running on hardware
- Add protocol comments - Document why labware is being moved
- Plan deck layout - Minimize unnecessary movements, optimize for efficiency
- Use OFF_DECK strategically - Free up deck space for complex protocols
- Check labware compatibility - Ensure labware is grippable before deploying
- Use offsets judiciously - Only when necessary for proper positioning
- Consider manual fallback - Have
use_gripper=Falsebackup for troubleshooting - Dispose properly - Use waste chute for used consumables to maintain workspace
Common Mistakes
❌ Moving to Heater-Shaker with closed latch:
protocol.move_labware(plate, hs_mod, use_gripper=True) # Error: latch closed
✅ Correct:
hs_mod.open_labware_latch()
protocol.move_labware(plate, hs_mod, use_gripper=True)
❌ Moving to Thermocycler with closed lid:
protocol.move_labware(plate, tc_mod, use_gripper=True) # Error: lid closed
✅ Correct:
tc_mod.open_lid()
protocol.move_labware(plate, tc_mod, use_gripper=True)
❌ Moving non-grippable labware:
# Custom labware without gripper features
protocol.move_labware(custom_tubes, "D2", use_gripper=True) # Error: cannot grip
✅ Correct:
# Use manual movement for non-grippable labware
protocol.move_labware(custom_tubes, "D2", use_gripper=False)
❌ Forgetting to specify use_gripper:
protocol.move_labware(plate, "D2") # Defaults to use_gripper=False, pauses protocol
✅ Correct:
protocol.move_labware(plate, "D2", use_gripper=True) # Explicit gripper use
❌ Moving to occupied location:
plate_1 = protocol.load_labware("corning_96_wellplate_360ul_flat", "C1")
plate_2 = protocol.load_labware("corning_96_wellplate_360ul_flat", "C2")
protocol.move_labware(plate_1, "C2", use_gripper=True) # Error: C2 occupied by plate_2
✅ Correct:
# Move plate_2 first, then plate_1
protocol.move_labware(plate_2, OFF_DECK, use_gripper=True)
protocol.move_labware(plate_1, "C2", use_gripper=True)
Troubleshooting
Gripper cannot grip labware:
- Verify labware has gripper-compatible features
- Check labware is properly seated on deck/module
- Try adjusting pick_up_offset (increase z)
- Use
use_gripper=Falsefor non-compatible labware
Gripper collision errors:
- Ensure module lids are open (Thermocycler, Absorbance Reader)
- Verify Heater-Shaker latch is open
- Check deck layout for obstructions
- Confirm destination location is clear
Labware not properly seated after movement:
- Adjust drop_offset to ensure proper placement
- Check module/adapter compatibility with labware
- Verify destination surface is level and clear
Protocol pauses unexpectedly:
- Check that
use_gripper=Trueis specified - Verify gripper is enabled for protocol
- Ensure labware is grippable
OFF_DECK movement errors:
- Import OFF_DECK constant:
from opentrons.protocol_api import OFF_DECK - Track labware location - cannot move from OFF_DECK if not there
- Ensure sufficient off-deck storage slots
Advanced Techniques
Conditional Gripper Use
# Use gripper for standard labware, manual for custom
def move_smart(protocol, labware, destination, is_grippable=True):
if is_grippable:
protocol.move_labware(labware, destination, use_gripper=True)
else:
protocol.comment(f"Please manually move {labware} to {destination}")
protocol.move_labware(labware, destination, use_gripper=False)
move_smart(protocol, standard_plate, "D2", is_grippable=True)
move_smart(protocol, custom_tubes, "D3", is_grippable=False)
Offset Calibration Helper
# Test offsets to find optimal values
def test_gripper_offset(protocol, labware, destination, z_offset_range):
for z in z_offset_range:
protocol.comment(f"Testing pickup offset z={z}")
protocol.move_labware(
labware,
destination,
use_gripper=True,
pick_up_offset={"x": 0, "y": 0, "z": z}
)
protocol.pause("Check if pickup was successful. Resume to continue.")
# Move back
protocol.move_labware(labware, "C1", use_gripper=True)
# Run test
test_gripper_offset(protocol, test_plate, "D2", z_offset_range=[0, 1, 2, 3])
Plate Carousel Pattern
# Rotate plates through processing stations
def process_plate_carousel(protocol, plates, processing_station):
"""Process multiple plates through single module."""
for i, plate in enumerate(plates):
protocol.comment(f"Processing plate {i+1}/{len(plates)}")
# Move to processing station
protocol.move_labware(plate, processing_station, use_gripper=True)
# Process (example: read absorbance)
# ... processing steps ...
# Move to archive
protocol.move_labware(plate, OFF_DECK, use_gripper=True)
process_plate_carousel(protocol, [plate1, plate2, plate3], reader_module)
Deck Layout Planning
Tips for efficient gripper workflows:
- Keep high-traffic locations accessible - Place frequently moved labware in central deck positions
- Group modules logically - Arrange modules in workflow order to minimize travel distance
- Reserve column 4 for Absorbance Reader - If using reader, entire column 4 is staging area
- Use OFF_DECK for storage - Free up deck space for active labware
- Plan waste chute access - Ensure gripper can reach waste chute without obstacles
Example efficient layout:
1 2 3 4
A [Plates] [Module1] [Reader] [Reserved]
B [Plates] [Module2] [Reader] [Reserved]
C [Tips] [Reagent] [Reader] [Reserved]
D [Tips] [Waste] [Reader] [Reserved]
Integration with Staging Area Slots
Flex staging area slots (column 4: A4, B4, C4, D4) are used for:
- Absorbance Reader lid storage (automatic)
- Temporary labware holding
- Gripper intermediate positions
Important: When Absorbance Reader is loaded, column 4 cannot be used for labware.
API Version Requirements
- Minimum API version: 2.15 (gripper support introduced)
- Recommended: 2.19+ for full feature support
- Robot type: Must be Opentrons Flex
Additional Resources
- Gripper Documentation: https://docs.opentrons.com/v2/new_protocol_api.html#protocol_api.ProtocolContext.move_labware
- Labware Library: https://labware.opentrons.com/ (check gripper compatibility)
- Opentrons Support: https://support.opentrons.com/
Related Skills
opentrons- Main Opentrons Python API skillopentrons-heater-shaker- Heater-Shaker Module (requires gripper integration)opentrons-absorbance-reader- Absorbance Plate Reader (requires gripper)opentrons-magnetic-block- Magnetic Block (designed for gripper workflow)opentrons-thermocycler- Thermocycler Module (gripper-compatible)opentrons-temperature-module- Temperature Module (gripper-compatible)