| 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):
source_plate = protocol.load_labware("corning_96_wellplate_360ul_flat", "C1")
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
temp_mod = protocol.load_module("temperature module gen2", "D1")
plate = protocol.load_labware("corning_96_wellplate_360ul_flat", "C2")
protocol.move_labware(
labware=plate,
new_location=temp_mod,
use_gripper=True
)
Moving to Waste Chute
waste_chute = protocol.load_waste_chute()
protocol.move_labware(
labware=used_plate,
new_location=waste_chute,
use_gripper=True
)
Moving Off-Deck
from opentrons.protocol_api import OFF_DECK
protocol.move_labware(
labware=archive_plate,
new_location=OFF_DECK,
use_gripper=True
)
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},
drop_offset={"x": 0, "y": 0, "z": 1}
)
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_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},
drop_offset={"x": 0, "y": 0, "z": 0}
)
Manual Movement Alternative
Set use_gripper=False to pause protocol for user to manually move labware:
protocol.move_labware(
labware=delicate_plate,
new_location="D3",
use_gripper=False
)
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")
protocol.move_labware(plate, temp_mod, use_gripper=True)
temp_mod.set_temperature(4)
protocol.delay(minutes=5)
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")
hs_mod.open_labware_latch()
protocol.move_labware(plate, hs_mod, use_gripper=True)
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()
hs_mod.open_labware_latch()
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")
tc_mod.open_lid()
protocol.move_labware(plate, tc_mod, use_gripper=True)
tc_mod.close_lid()
tc_mod.set_lid_temperature(105)
tc_mod.open_lid()
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")
protocol.move_labware(mag_plate, mag_block, use_gripper=True)
protocol.delay(minutes=3)
pipette.transfer(150, mag_plate.wells(), waste.wells())
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")
reader.close_lid()
reader.initialize(mode="single", wavelengths=[450])
reader.open_lid()
protocol.move_labware(assay_plate, reader, use_gripper=True)
reader.close_lid()
data = reader.read()
reader.open_lid()
protocol.move_labware(assay_plate, "C2", use_gripper=True)
Common Patterns
Multi-Module Workflow
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")
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()
protocol.move_labware(sample_plate, mag_block, use_gripper=True)
protocol.delay(minutes=3)
pipette.transfer(150, sample_plate.wells(), waste.wells())
protocol.move_labware(sample_plate, temp_mod, use_gripper=True)
temp_mod.set_temperature(4)
pipette.transfer(50, elution_buffer, sample_plate.wells())
protocol.move_labware(sample_plate, "C1", use_gripper=True)
temp_mod.deactivate()
Plate Stacking Workflow
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):
protocol.move_labware(plate, reader, use_gripper=True)
reader.close_lid()
data = reader.read(export_filename=f"plate_{i+1}_od600")
reader.open_lid()
protocol.move_labware(plate, OFF_DECK, use_gripper=True)
Waste Management
waste_chute = protocol.load_waste_chute()
protocol.move_labware(empty_tips, waste_chute, use_gripper=True)
protocol.move_labware(used_plate, waste_chute, use_gripper=True)
Dynamic Deck Space Management
storage = OFF_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")
protocol.move_labware(plate_1, storage, use_gripper=True)
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=False backup 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)
✅ 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)
✅ Correct:
tc_mod.open_lid()
protocol.move_labware(plate, tc_mod, use_gripper=True)
❌ Moving non-grippable labware:
protocol.move_labware(custom_tubes, "D2", use_gripper=True)
✅ Correct:
protocol.move_labware(custom_tubes, "D2", use_gripper=False)
❌ Forgetting to specify use_gripper:
protocol.move_labware(plate, "D2")
✅ Correct:
protocol.move_labware(plate, "D2", use_gripper=True)
❌ 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)
✅ Correct:
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=False for 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=True is 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
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
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.")
protocol.move_labware(labware, "C1", use_gripper=True)
test_gripper_offset(protocol, test_plate, "D2", z_offset_range=[0, 1, 2, 3])
Plate Carousel Pattern
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)}")
protocol.move_labware(plate, processing_station, use_gripper=True)
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
Related Skills
opentrons - Main Opentrons Python API skill
opentrons-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)