| name | opentrons-magnetic-block |
| description | Opentrons Magnetic Block for Flex - unpowered magnetic bead separation using gripper-based labware movement with high-strength neodymium magnets for DNA/RNA purification, immunoprecipitation, and bead-based workflows |
| allowed-tools | ["*"] |
Opentrons Magnetic Block
Overview
The Opentrons Magnetic Block is an unpowered, 96-well magnetic separator exclusively for Opentrons Flex. It uses high-strength neodymium magnets to pull magnetic beads to the side of wells, enabling supernatant removal for DNA/RNA purification, protein cleanup, immunoprecipitation, and other bead-based separation protocols.
Core value: Automate magnetic bead-based purification workflows without manual plate transfers. Combine gripper-based plate movement with magnetic separation for fully automated DNA extraction, PCR cleanup, and bead-based assays.
Platform: Opentrons Flex only (not compatible with OT-2)
When to Use
Use the Magnetic Block skill when:
- Performing DNA/RNA extraction with magnetic beads
- PCR product cleanup (AMPure, SPRIselect beads)
- Magnetic bead-based library preparation (NGS)
- Protein purification or immunoprecipitation with magnetic beads
- Cell sorting or enrichment with magnetic particles
- Any protocol requiring magnetic bead separation
Don't use when:
- Working with OT-2 robot (Magnetic Block is Flex-only)
- Need vertical bead movement within solution (block only pulls to side)
- Require heated magnetic separation
- Working without Opentrons Flex gripper
Quick Reference
| Operation | Method | Key Parameters |
|---|
| Load module | protocol.load_module() | "magneticBlockV1", location |
| Move plate to block | protocol.move_labware() | labware, mag_block, use_gripper=True |
| Wait for separation | protocol.delay() | minutes (typically 2-5) |
| Pipette supernatant | pipette.transfer() | source, dest |
| Move plate off block | protocol.move_labware() | labware, new_location, use_gripper=True |
Platform Requirements
Opentrons Flex only
- API version: 2.15 or later (Magnetic Block introduced)
- Gripper required: All plate movement uses gripper
- Robot type: Must specify
"robotType": "Flex"
Key Characteristics
Unpowered Design
Important: The Magnetic Block is completely unpowered:
- No electronic control
- No on/off switching
- Always magnetic when plate is present
- Robot and Opentrons App are not aware of magnetic state
Implication: All control is manual through:
- Physical plate positioning (gripper movement)
- Timed delays for bead separation
- Pipetting operations
Loading the Module
from opentrons import protocol_api
metadata = {'apiLevel': '2.19'}
requirements = {"robotType": "Flex", "apiLevel": "2.19"}
def run(protocol: protocol_api.ProtocolContext):
mag_block = protocol.load_module(
module_name="magneticBlockV1",
location="D1"
)
mag_plate = mag_block.load_labware(
name="biorad_96_wellplate_200ul_pcr"
)
Compatible deck slots: Any Flex slot (A1-D3)
Recommended: D1, D2, or D3 (bottom row for workflow efficiency)
Compatible Labware
The Magnetic Block works with 96-well plates that fit the magnetic footprint:
Common compatible labware:
biorad_96_wellplate_200ul_pcr
nest_96_wellplate_100ul_pcr_full_skirt
opentrons_96_wellplate_200ul_pcr_full_skirt
- Other 96-well PCR plates with standard footprint
Important:
- Labware must be grippable (compatible with Flex gripper)
- Wells must align with magnet positions
- Standard 96-well footprint required
Basic Magnetic Separation Workflow
Step 1: Load Sample Plate
sample_plate = protocol.load_labware("biorad_96_wellplate_200ul_pcr", "C1")
pipette.transfer(10, bead_stock, sample_plate.wells())
pipette.transfer(100, binding_buffer, sample_plate.wells(), mix_after=(5, 80))
Step 2: Incubate for Binding
protocol.delay(minutes=5)
Step 3: Move to Magnetic Block
protocol.move_labware(
labware=sample_plate,
new_location=mag_block,
use_gripper=True
)
Step 4: Wait for Bead Separation
protocol.delay(minutes=3)
Step 5: Remove Supernatant
pipette.transfer(
volume=110,
source=sample_plate.wells(),
dest=waste.wells(),
new_tip="always"
)
Step 6: Move Off Magnetic Block
protocol.move_labware(
labware=sample_plate,
new_location="C2",
use_gripper=True
)
Step 7: Wash and Repeat
pipette.transfer(150, wash_buffer, sample_plate.wells())
pipette.mix(repetitions=5, volume=100, location=sample_plate.wells())
protocol.move_labware(sample_plate, mag_block, use_gripper=True)
protocol.delay(minutes=2)
pipette.transfer(150, sample_plate.wells(), waste.wells(), new_tip="always")
Step 8: Elute
protocol.move_labware(sample_plate, "C2", use_gripper=True)
pipette.transfer(50, elution_buffer, sample_plate.wells(), mix_after=(5, 30))
protocol.delay(minutes=2)
protocol.move_labware(sample_plate, mag_block, use_gripper=True)
protocol.delay(minutes=2)
pipette.transfer(45, sample_plate.wells(), elution_plate.wells(), new_tip="always")
Complete DNA Extraction Protocol
def run(protocol: protocol_api.ProtocolContext):
mag_block = protocol.load_module("magneticBlockV1", "D1")
sample_plate = mag_block.load_labware("biorad_96_wellplate_200ul_pcr")
tips = protocol.load_labware("opentrons_flex_96_tiprack_1000ul", "A1")
waste = protocol.load_trash_bin("A3")
reagents = protocol.load_labware("nest_12_reservoir_15ml", "C2")
pipette = protocol.load_instrument("flex_8channel_1000", "left", tip_racks=[tips])
lysis_beads = reagents["A1"]
wash_buffer = reagents["A2"]
elution_buffer = reagents["A3"]
pipette.transfer(100, lysis_beads, sample_plate.columns()[0], mix_after=(5, 80))
protocol.delay(minutes=5)
protocol.move_labware(sample_plate, mag_block, use_gripper=True)
protocol.delay(minutes=3)
pipette.transfer(200, sample_plate.columns()[0], waste, new_tip="always")
protocol.move_labware(sample_plate, "C1", use_gripper=True)
pipette.transfer(150, wash_buffer, sample_plate.columns()[0], mix_after=(, ))
protocol.move_labware(sample_plate, mag_block, use_gripper=)
protocol.delay(minutes=)
pipette.transfer(, sample_plate.columns()[], waste, new_tip=)
protocol.move_labware(sample_plate, , use_gripper=)
pipette.transfer(, wash_buffer, sample_plate.columns()[], mix_after=(, ))
protocol.move_labware(sample_plate, mag_block, use_gripper=)
protocol.delay(minutes=)
pipette.transfer(, sample_plate.columns()[], waste, new_tip=)
protocol.delay(minutes=)
protocol.move_labware(sample_plate, , use_gripper=)
pipette.transfer(, elution_buffer, sample_plate.columns()[], mix_after=(, ))
protocol.delay(minutes=)
protocol.move_labware(sample_plate, mag_block, use_gripper=)
protocol.delay(minutes=)
elution_plate = protocol.load_labware(, )
pipette.transfer(, sample_plate.columns()[], elution_plate.columns()[], new_tip=)
Common Patterns
PCR Cleanup (AMPure Beads)
mag_block = protocol.load_module("magneticBlockV1", "D1")
pcr_plate = protocol.load_labware("biorad_96_wellplate_200ul_pcr", "C1")
pipette.transfer(40, ampure_beads, pcr_plate.wells(), mix_after=(5, 35))
protocol.delay(minutes=5)
protocol.move_labware(pcr_plate, mag_block, use_gripper=True)
protocol.delay(minutes=3)
pipette.transfer(90, pcr_plate.wells(), waste.wells())
for _ in range(2):
pipette.transfer(150, ethanol_70, pcr_plate.wells())
protocol.delay(seconds=30)
pipette.transfer(150, pcr_plate.wells(), waste.wells())
protocol.delay(minutes=5)
protocol.move_labware(pcr_plate, "C2", use_gripper=True)
pipette.transfer(30, water, pcr_plate.wells(), mix_after=(5, 20))
protocol.delay(minutes=2)
protocol.move_labware(pcr_plate, mag_block, use_gripper=True)
protocol.delay(minutes=2)
pipette.transfer(25, pcr_plate.wells(), clean_plate.wells())
NGS Library Preparation
mag_block = protocol.load_module("magneticBlockV1", "D2")
lib_plate = mag_block.load_labware("biorad_96_wellplate_200ul_pcr")
pipette.transfer(30, spri_beads, lib_plate.wells(), mix_after=(5, 25))
protocol.delay(minutes=5)
protocol.move_labware(lib_plate, mag_block, use_gripper=True)
protocol.delay(minutes=3)
protocol.move_labware(lib_plate, "C1", use_gripper=True)
pipette.transfer(20, spri_beads, lib_plate.wells(), mix_after=(5, 30))
protocol.delay(minutes=5)
protocol.move_labware(lib_plate, mag_block, use_gripper=True)
protocol.delay(minutes=3)
pipette.transfer(100, lib_plate.wells(), waste.wells())
Protein Immunoprecipitation
mag_block = protocol.load_module("magneticBlockV1", "D1")
ip_plate = mag_block.load_labware("biorad_96_wellplate_200ul_pcr")
pipette.transfer(100, lysate_plate.wells(), ip_plate.wells(), mix_after=(3, 80))
protocol.delay(minutes=30)
for wash_num in range(3):
protocol.move_labware(ip_plate, mag_block, use_gripper=True)
protocol.delay(minutes=2)
pipette.transfer(150, ip_plate.wells(), waste.wells())
protocol.move_labware(ip_plate, "C1", use_gripper=True)
pipette.transfer(150, wash_buffer, ip_plate.wells(), mix_after=(3, 100))
protocol.move_labware(ip_plate, "C1", use_gripper=True)
pipette.transfer(50, elution_buffer, ip_plate.wells(), mix_after=(5, 30))
protocol.delay(minutes=5)
protocol.move_labware(ip_plate, mag_block, use_gripper=True)
protocol.delay(minutes=2)
pipette.transfer(45, ip_plate.wells(), analysis_plate.wells())
Integration with Other Modules
With Heater-Shaker (Heated Lysis)
hs_mod = protocol.load_module("heaterShakerModuleV1", "D1")
mag_block = protocol.load_module("magneticBlockV1", "D2")
sample_plate = protocol.load_labware("biorad_96_wellplate_200ul_pcr", "C1")
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)
With Temperature Module (Cold Elution)
temp_mod = protocol.load_module("temperature module gen2", "D3")
mag_block = protocol.load_module("magneticBlockV1", "D2")
temp_mod.set_temperature(4)
protocol.move_labware(sample_plate, "C1", use_gripper=True)
pipette.transfer(50, cold_elution, sample_plate.wells(), mix_after=(5, 30))
protocol.move_labware(sample_plate, temp_mod, use_gripper=True)
protocol.delay(minutes=5)
protocol.move_labware(sample_plate, mag_block, use_gripper=True)
protocol.delay(minutes=2)
pipette.transfer(45, sample_plate.wells(), storage_plate.wells())
temp_mod.deactivate()
With Thermocycler (Post-PCR Cleanup)
tc_mod = protocol.load_module("thermocyclerModuleV2")
mag_block = protocol.load_module("magneticBlockV1", "D2")
tc_mod.close_lid()
tc_mod.set_block_temperature(4)
tc_mod.open_lid()
pcr_plate = tc_mod.labware
protocol.move_labware(pcr_plate, "C1", use_gripper=True)
pipette.transfer(40, ampure_beads, pcr_plate.wells(), mix_after=(5, 35))
protocol.delay(minutes=5)
protocol.move_labware(pcr_plate, mag_block, use_gripper=True)
Best Practices
- Allow sufficient separation time - Typically 2-5 minutes depending on bead type
- Use gripper for all plate movements - Manual movement defeats automation purpose
- Avoid disturbing beads when pipetting - Aspirate from opposite side of well
- Mix thoroughly after moving off magnets - Ensure complete bead resuspension
- Track bead volume in calculations - Account for beads when calculating total volume
- Use consistent bead types - Different beads have different separation times
- Plan deck layout - Position magnetic block near other modules for efficiency
- Test separation time - Optimize delay for your specific beads and sample type
- Don't over-dry beads - Can reduce elution efficiency
- Validate elution volume - Leave some headroom to avoid transferring beads
Separation Time Guidelines
Typical separation times by bead type:
- AMPure/SPRIselect (DNA): 2-3 minutes
- RNAClean (RNA): 3-4 minutes
- Protein G/A beads: 2-3 minutes
- High-density beads: 1-2 minutes
- Large volume samples: 4-5 minutes
Factors affecting separation:
- Bead concentration
- Sample volume
- Viscosity
- Magnetic bead strength
- Well geometry
Recommendation: Start with 3 minutes, adjust based on visual inspection or protocol optimization.
Common Mistakes
❌ Moving plate without gripper:
protocol.move_labware(sample_plate, mag_block, use_gripper=False)
✅ Correct:
protocol.move_labware(sample_plate, mag_block, use_gripper=True)
❌ Insufficient separation time:
protocol.move_labware(sample_plate, mag_block, use_gripper=True)
protocol.delay(seconds=30)
pipette.transfer(100, sample_plate.wells(), waste.wells())
✅ Correct:
protocol.move_labware(sample_plate, mag_block, use_gripper=True)
protocol.delay(minutes=3)
pipette.transfer(100, sample_plate.wells(), waste.wells())
❌ Pipetting through bead pellet:
pipette.aspirate(100, sample_plate.wells()[0])
✅ Correct:
pipette.aspirate(100, sample_plate.wells()[0].bottom(z=2))
❌ Incomplete bead resuspension:
protocol.move_labware(sample_plate, "C1", use_gripper=True)
pipette.transfer(150, wash_buffer, sample_plate.wells())
✅ Correct:
protocol.move_labware(sample_plate, "C1", use_gripper=True)
pipette.transfer(150, wash_buffer, sample_plate.wells(), mix_after=(5, 100))
❌ Using incompatible labware:
mag_plate = mag_block.load_labware("nest_96_wellplate_2ml_deep")
✅ Correct:
mag_plate = mag_block.load_labware("biorad_96_wellplate_200ul_pcr")
Troubleshooting
Beads not separating:
- Increase separation time (try 4-5 minutes)
- Check bead type and concentration
- Verify plate is properly seated on magnetic block
- Ensure labware is compatible with magnet positions
Beads being transferred with supernatant:
- Extend separation time
- Pipette more carefully (avoid bead pellet)
- Reduce aspiration flow rate
- Leave more residual volume
Incomplete elution:
- Ensure beads are fully resuspended before elution incubation
- Mix more vigorously
- Extend elution incubation time
- Verify beads haven't dried excessively
- Use appropriate elution buffer volume
Bead clumping:
- Mix more thoroughly when resuspending
- Ensure beads are well-mixed before adding to samples
- Avoid drying beads too long
- Check bead storage conditions
Variable recovery across wells:
- Ensure consistent bead addition volumes
- Mix uniformly across all wells
- Use consistent separation times
- Check for plate positioning issues on magnetic block
Advanced Techniques
Dual-Size Selection
pipette.transfer(30, spri_beads, lib_plate.wells(), mix_after=(5, 25))
protocol.delay(minutes=5)
protocol.move_labware(lib_plate, mag_block, use_gripper=True)
protocol.delay(minutes=3)
protocol.move_labware(lib_plate, "C1", use_gripper=True)
pipette.transfer(80, lib_plate.wells(), temp_plate.wells())
pipette.transfer(20, spri_beads, temp_plate.wells(), mix_after=(5, 30))
protocol.delay(minutes=5)
protocol.move_labware(temp_plate, mag_block, use_gripper=True)
protocol.delay(minutes=3)
pipette.transfer(100, temp_plate.wells(), waste.wells())
Differential Elution
pipette.transfer(50, elution_buffer_1, sample_plate.wells(), mix_after=(5, 30))
protocol.delay(minutes=2)
protocol.move_labware(sample_plate, mag_block, use_gripper=True)
protocol.delay(minutes=2)
pipette.transfer(45, sample_plate.wells(), fraction_1_plate.wells())
protocol.move_labware(sample_plate, "C1", use_gripper=True)
pipette.transfer(50, elution_buffer_2, sample_plate.wells(), mix_after=(5, 30))
protocol.delay(minutes=2)
protocol.move_labware(sample_plate, mag_block, use_gripper=True)
protocol.delay(minutes=2)
pipette.transfer(45, sample_plate.wells(), fraction_2_plate.wells())
No Electronic Control
Remember: The Magnetic Block has no electronic interface.
This means:
- ❌ Cannot turn magnets on/off programmatically
- ❌ No status reporting to robot
- ❌ No automatic timing
- ✅ Full control through plate positioning
- ✅ Predictable, passive magnetic field
- ✅ No calibration or initialization required
Control strategy: Move plate TO block = magnets engaged, move plate OFF block = magnets disengaged
API Version Requirements
- Minimum API version: 2.15 (Magnetic Block introduced)
- Recommended: 2.19+ for full Flex feature support
- Robot type: Must be Opentrons Flex
Additional Resources
Related Skills
opentrons - Main Opentrons Python API skill
opentrons-gripper - Automated labware movement (required)
opentrons-heater-shaker - Heated incubation with mixing
opentrons-temperature-module - Temperature control
opentrons-thermocycler - PCR for molecular workflows