[{"data":1,"prerenderedAt":2423},["ShallowReactive",2],{"navigation":3,"\u002Fautomate\u002Fyour-first-workflow":750,"\u002Fautomate\u002Fyour-first-workflow-surround":2418},[4,80,134,364,428,530,567,646],{"title":5,"path":6,"stem":7,"children":8,"page":42},"Get Started","\u002Fget-started","01.get-started",[9,13,17,43,47],{"title":10,"path":11,"stem":12},"Welcome to UniteLabs","\u002Fget-started\u002Fwelcome","01.get-started\u002F00.welcome",{"title":14,"path":15,"stem":16},"How it works","\u002Fget-started\u002Fhow-it-works","01.get-started\u002F01.how-it-works",{"title":18,"path":19,"stem":20,"children":21,"page":42},"Use Cases","\u002Fget-started\u002Fuse-cases","01.get-started\u002F02.use-cases",[22,26,30,34,38],{"title":23,"path":24,"stem":25},"Instrument Control","\u002Fget-started\u002Fuse-cases\u002Flow-level-instrument-control","01.get-started\u002F02.use-cases\u002F10.low-level-instrument-control",{"title":27,"path":28,"stem":29},"Multi-device Control","\u002Fget-started\u002Fuse-cases\u002Fmulti-device-control","01.get-started\u002F02.use-cases\u002F20.multi-device-control",{"title":31,"path":32,"stem":33},"Workflow Orchestration","\u002Fget-started\u002Fuse-cases\u002Fworkflow-orchestration","01.get-started\u002F02.use-cases\u002F30.workflow-orchestration",{"title":35,"path":36,"stem":37},"Custom Apps and LIMS Integration","\u002Fget-started\u002Fuse-cases\u002Fcustom-apps-lims","01.get-started\u002F02.use-cases\u002F40.custom-apps-lims",{"title":39,"path":40,"stem":41},"Scale and Fleet Management","\u002Fget-started\u002Fuse-cases\u002Fscale-and-fleet","01.get-started\u002F02.use-cases\u002F50.scale-and-fleet",false,{"title":44,"path":45,"stem":46},"Lab as Code","\u002Fget-started\u002Fwhy-code","01.get-started\u002F03.why-code",{"title":48,"path":49,"stem":50,"children":51,"page":42},"Setup","\u002Fget-started\u002Fsetup","01.get-started\u002F20.setup",[52,56,60,64,68,72,76],{"title":53,"path":54,"stem":55},"GroundControl","\u002Fget-started\u002Fsetup\u002Fgroundcontrol","01.get-started\u002F20.setup\u002F10.groundcontrol",{"title":57,"path":58,"stem":59},"Network requirements","\u002Fget-started\u002Fsetup\u002Fnetwork-requirements","01.get-started\u002F20.setup\u002F20.network-requirements",{"title":61,"path":62,"stem":63},"Multi-device Networking","\u002Fget-started\u002Fsetup\u002Fmultiple-devices","01.get-started\u002F20.setup\u002F30.multiple-devices",{"title":65,"path":66,"stem":67},"Connect to Platform","\u002Fget-started\u002Fsetup\u002Fconnect-to-platform","01.get-started\u002F20.setup\u002F40.connect-to-platform",{"title":69,"path":70,"stem":71},"Headless install","\u002Fget-started\u002Fsetup\u002Fheadless-install","01.get-started\u002F20.setup\u002F50.headless-install",{"title":73,"path":74,"stem":75},"Raspberry Pi","\u002Fget-started\u002Fsetup\u002Fraspberry-pi","01.get-started\u002F20.setup\u002F55.raspberry-pi",{"title":77,"path":78,"stem":79},"Installation","\u002Fget-started\u002Fsetup\u002Fsdk-installation","01.get-started\u002F20.setup\u002F60.sdk-installation",{"title":81,"path":82,"stem":83,"children":84,"page":42},"Integrate","\u002Fintegrate","02.integrate",[85,89,93,118],{"title":86,"path":87,"stem":88},"What is a connector?","\u002Fintegrate\u002Fwhat-is-a-connector","02.integrate\u002F00.what-is-a-connector",{"title":90,"path":91,"stem":92},"Calling a Connector","\u002Fintegrate\u002Fcontrol-with-code","02.integrate\u002F05.control-with-code",{"title":94,"path":95,"stem":96,"children":97,"page":42},"Concepts","\u002Fintegrate\u002Fconcepts","02.integrate\u002F10.concepts",[98,102,106,110,114],{"title":99,"path":100,"stem":101},"Connector","\u002Fintegrate\u002Fconcepts\u002Fconnector","02.integrate\u002F10.concepts\u002F10.connector",{"title":103,"path":104,"stem":105},"Module","\u002Fintegrate\u002Fconcepts\u002Fmodule","02.integrate\u002F10.concepts\u002F20.module",{"title":107,"path":108,"stem":109},"Action","\u002Fintegrate\u002Fconcepts\u002Faction","02.integrate\u002F10.concepts\u002F30.action",{"title":111,"path":112,"stem":113},"Subscription","\u002Fintegrate\u002Fconcepts\u002Fsubscription","02.integrate\u002F10.concepts\u002F40.subscription",{"title":115,"path":116,"stem":117},"Device","\u002Fintegrate\u002Fconcepts\u002Fdevice","02.integrate\u002F10.concepts\u002F50.device",{"title":119,"path":120,"stem":121,"children":122,"page":42},"Use a connector","\u002Fintegrate\u002Fuse-a-connector","02.integrate\u002F30.use-a-connector",[123,126,130],{"title":53,"path":124,"stem":125},"\u002Fintegrate\u002Fuse-a-connector\u002Fgroundcontrol","02.integrate\u002F30.use-a-connector\u002F10.groundcontrol",{"title":127,"path":128,"stem":129},"Platform","\u002Fintegrate\u002Fuse-a-connector\u002Fplatform","02.integrate\u002F30.use-a-connector\u002F20.platform",{"title":131,"path":132,"stem":133},"UniteLabs SDK & REST API","\u002Fintegrate\u002Fuse-a-connector\u002Fpython","02.integrate\u002F30.use-a-connector\u002F30.python",{"title":135,"path":136,"stem":137,"children":138,"page":42},"Operate","\u002Foperate","03.operate",[139,142,146,186,259],{"title":135,"path":140,"stem":141},"\u002Foperate\u002Foverview","03.operate\u002F00.overview",{"title":143,"path":144,"stem":145},"Your First Protocol","\u002Foperate\u002Fyour-first-protocol","03.operate\u002F05.your-first-protocol",{"title":94,"path":147,"stem":148,"children":149,"page":42},"\u002Foperate\u002Fconcepts","03.operate\u002F10.concepts",[150,154,158,162,166,170,174,178,182],{"title":151,"path":152,"stem":153},"Liquid Handling","\u002Foperate\u002Fconcepts\u002Fliquid-handling","03.operate\u002F10.concepts\u002F10.liquid-handling",{"title":155,"path":156,"stem":157},"Modules","\u002Foperate\u002Fconcepts\u002Fmodules","03.operate\u002F10.concepts\u002F20.modules",{"title":159,"path":160,"stem":161},"Deck","\u002Foperate\u002Fconcepts\u002Fdeck","03.operate\u002F10.concepts\u002F30.deck",{"title":163,"path":164,"stem":165},"Labware","\u002Foperate\u002Fconcepts\u002Flabware","03.operate\u002F10.concepts\u002F40.labware",{"title":167,"path":168,"stem":169},"Liquids","\u002Foperate\u002Fconcepts\u002Fliquids","03.operate\u002F10.concepts\u002F50.liquids",{"title":171,"path":172,"stem":173},"Liquid Classes","\u002Foperate\u002Fconcepts\u002Fliquid-classes","03.operate\u002F10.concepts\u002F60.liquid-classes",{"title":175,"path":176,"stem":177},"Tips and Tip Tracking","\u002Foperate\u002Fconcepts\u002Ftips","03.operate\u002F10.concepts\u002F70.tips",{"title":179,"path":180,"stem":181},"Simulation","\u002Foperate\u002Fconcepts\u002Fsimulation","03.operate\u002F10.concepts\u002F80.simulation",{"title":183,"path":184,"stem":185},"Error Handling","\u002Foperate\u002Fconcepts\u002Ferror-handling","03.operate\u002F10.concepts\u002F90.error-handling",{"title":187,"path":188,"stem":189,"children":190,"page":42},"Guides","\u002Foperate\u002Fguides","03.operate\u002F20.guides",[191,220,232,256],{"title":163,"path":192,"stem":193,"children":194},"\u002Foperate\u002Fguides\u002Flabware","03.operate\u002F20.guides\u002F10.labware\u002Findex",[195,196,200,204,208,212,216],{"title":163,"path":192,"stem":193},{"title":197,"path":198,"stem":199},"Standard Labware","\u002Foperate\u002Fguides\u002Flabware\u002Fstandard-labware","03.operate\u002F20.guides\u002F10.labware\u002F05.standard-labware",{"title":201,"path":202,"stem":203},"Plates","\u002Foperate\u002Fguides\u002Flabware\u002Fplates","03.operate\u002F20.guides\u002F10.labware\u002F10.plates",{"title":205,"path":206,"stem":207},"Tips and Tip Racks","\u002Foperate\u002Fguides\u002Flabware\u002Ftips-and-racks","03.operate\u002F20.guides\u002F10.labware\u002F20.tips-and-racks",{"title":209,"path":210,"stem":211},"Tubes and Tube Racks","\u002Foperate\u002Fguides\u002Flabware\u002Ftubes-and-tube-racks","03.operate\u002F20.guides\u002F10.labware\u002F30.tubes-and-tube-racks",{"title":213,"path":214,"stem":215},"Troughs","\u002Foperate\u002Fguides\u002Flabware\u002Ftroughs","03.operate\u002F20.guides\u002F10.labware\u002F35.troughs",{"title":217,"path":218,"stem":219},"Carriers and Adapters","\u002Foperate\u002Fguides\u002Flabware\u002Fcarriers-and-adapters","03.operate\u002F20.guides\u002F10.labware\u002F40.carriers-and-adapters",{"title":159,"path":221,"stem":222,"children":223,"page":42},"\u002Foperate\u002Fguides\u002Fdeck","03.operate\u002F20.guides\u002F20.deck",[224,228],{"title":225,"path":226,"stem":227},"Building a Deck","\u002Foperate\u002Fguides\u002Fdeck\u002Fbuilding-a-deck","03.operate\u002F20.guides\u002F20.deck\u002F10.building-a-deck",{"title":229,"path":230,"stem":231},"Save\u002FLoad a Deck","\u002Foperate\u002Fguides\u002Fdeck\u002Fsave-load-deck","03.operate\u002F20.guides\u002F20.deck\u002F20.save-load-deck",{"title":233,"path":234,"stem":235,"children":236,"page":42},"Pipetting","\u002Foperate\u002Fguides\u002Fpipetting","03.operate\u002F20.guides\u002F30.pipetting",[237,241,245,249,252],{"title":238,"path":239,"stem":240},"Basic Pipetting","\u002Foperate\u002Fguides\u002Fpipetting\u002Fbasic-pipetting","03.operate\u002F20.guides\u002F30.pipetting\u002F10.basic-pipetting",{"title":242,"path":243,"stem":244},"Advanced Pipetting","\u002Foperate\u002Fguides\u002Fpipetting\u002Fadvanced-pipetting","03.operate\u002F20.guides\u002F30.pipetting\u002F20.advanced-pipetting",{"title":246,"path":247,"stem":248},"Tip Handling","\u002Foperate\u002Fguides\u002Fpipetting\u002Ftip-handling","03.operate\u002F20.guides\u002F30.pipetting\u002F30.tip-handling",{"title":171,"path":250,"stem":251},"\u002Foperate\u002Fguides\u002Fpipetting\u002Fliquid-classes","03.operate\u002F20.guides\u002F30.pipetting\u002F40.liquid-classes",{"title":253,"path":254,"stem":255},"Labware Transport","\u002Foperate\u002Fguides\u002Fpipetting\u002Flabware-transport","03.operate\u002F20.guides\u002F30.pipetting\u002F50.labware-transport",{"title":179,"path":257,"stem":258},"\u002Foperate\u002Fguides\u002Fsimulation","03.operate\u002F20.guides\u002F40.simulation",{"title":260,"path":261,"stem":262,"children":263,"page":42},"Liquid Handler Guides","\u002Foperate\u002Fdevices","03.operate\u002F30.devices",[264,305,330,347],{"title":265,"path":266,"stem":267,"children":268,"page":42},"Hamilton STAR","\u002Foperate\u002Fdevices\u002Fhamilton-star","03.operate\u002F30.devices\u002F10.hamilton-star",[269,273,277,281,285,289,293,297,301],{"title":270,"path":271,"stem":272},"Positioning & Movement","\u002Foperate\u002Fdevices\u002Fhamilton-star\u002Fpositioning","03.operate\u002F30.devices\u002F10.hamilton-star\u002F10.positioning",{"title":274,"path":275,"stem":276},"Gripper Module","\u002Foperate\u002Fdevices\u002Fhamilton-star\u002Fcore-gripper","03.operate\u002F30.devices\u002F10.hamilton-star\u002F20.core-gripper",{"title":278,"path":279,"stem":280},"iSWAP Module","\u002Foperate\u002Fdevices\u002Fhamilton-star\u002Fiswap","03.operate\u002F30.devices\u002F10.hamilton-star\u002F30.iswap",{"title":282,"path":283,"stem":284},"Using TADM","\u002Foperate\u002Fdevices\u002Fhamilton-star\u002Ftadm","03.operate\u002F30.devices\u002F10.hamilton-star\u002F40.tadm",{"title":286,"path":287,"stem":288},"Autoload Module","\u002Foperate\u002Fdevices\u002Fhamilton-star\u002Fautoload","03.operate\u002F30.devices\u002F10.hamilton-star\u002F50.autoload",{"title":290,"path":291,"stem":292},"Waste Block","\u002Foperate\u002Fdevices\u002Fhamilton-star\u002Fwaste-block","03.operate\u002F30.devices\u002F10.hamilton-star\u002F60.waste-block",{"title":294,"path":295,"stem":296},"Complex Mixing","\u002Foperate\u002Fdevices\u002Fhamilton-star\u002Fcomplex-mixing","03.operate\u002F30.devices\u002F10.hamilton-star\u002F66.complex-mixing",{"title":298,"path":299,"stem":300},"Teaching Gripper Paddle Positions","\u002Foperate\u002Fdevices\u002Fhamilton-star\u002Fgripper-positions","03.operate\u002F30.devices\u002F10.hamilton-star\u002F70.gripper-positions",{"title":302,"path":303,"stem":304},"Training a Custom Deck Position With the iSWAP","\u002Foperate\u002Fdevices\u002Fhamilton-star\u002Fcustom-deck-position","03.operate\u002F30.devices\u002F10.hamilton-star\u002F75.custom-deck-position",{"title":306,"path":307,"stem":308,"children":309,"page":42},"Hamilton Vantage","\u002Foperate\u002Fdevices\u002Fhamilton-vantage","03.operate\u002F30.devices\u002F20.hamilton-vantage",[310,314,318,322,326],{"title":311,"path":312,"stem":313},"Waste Configuration","\u002Foperate\u002Fdevices\u002Fhamilton-vantage\u002Fwaste-configuration","03.operate\u002F30.devices\u002F20.hamilton-vantage\u002F05.waste-configuration",{"title":315,"path":316,"stem":317},"Covers and Lights","\u002Foperate\u002Fdevices\u002Fhamilton-vantage\u002Fcovers-and-lights","03.operate\u002F30.devices\u002F20.hamilton-vantage\u002F10.covers-and-lights",{"title":319,"path":320,"stem":321},"IDL Module","\u002Foperate\u002Fdevices\u002Fhamilton-vantage\u002Fidl","03.operate\u002F30.devices\u002F20.hamilton-vantage\u002F20.idl",{"title":323,"path":324,"stem":325},"IPG Module","\u002Foperate\u002Fdevices\u002Fhamilton-vantage\u002Fipg","03.operate\u002F30.devices\u002F20.hamilton-vantage\u002F30.ipg",{"title":327,"path":328,"stem":329},"XL Pipettes","\u002Foperate\u002Fdevices\u002Fhamilton-vantage\u002Fxl-channels","03.operate\u002F30.devices\u002F20.hamilton-vantage\u002F40.xl-channels",{"title":331,"path":332,"stem":333,"children":334,"page":42},"Agilent Bravo","\u002Foperate\u002Fdevices\u002Fagilent-bravo","03.operate\u002F30.devices\u002F30.agilent-bravo",[335,338,341,344],{"title":246,"path":336,"stem":337},"\u002Foperate\u002Fdevices\u002Fagilent-bravo\u002Ftip-handling","03.operate\u002F30.devices\u002F30.agilent-bravo\u002F10.tip-handling",{"title":238,"path":339,"stem":340},"\u002Foperate\u002Fdevices\u002Fagilent-bravo\u002Fbasic-pipetting","03.operate\u002F30.devices\u002F30.agilent-bravo\u002F20.basic-pipetting",{"title":171,"path":342,"stem":343},"\u002Foperate\u002Fdevices\u002Fagilent-bravo\u002Fliquid-classes","03.operate\u002F30.devices\u002F30.agilent-bravo\u002F25.liquid-classes",{"title":274,"path":345,"stem":346},"\u002Foperate\u002Fdevices\u002Fagilent-bravo\u002Fusing-the-gripper","03.operate\u002F30.devices\u002F30.agilent-bravo\u002F30.using-the-gripper",{"title":348,"path":349,"stem":350,"children":351,"page":42},"Tecan FluentControl","\u002Foperate\u002Fdevices\u002Ftecan-fluentcontrol","03.operate\u002F30.devices\u002F40.tecan-fluentcontrol",[352,356,360],{"title":353,"path":354,"stem":355},"Connect & Run a Method","\u002Foperate\u002Fdevices\u002Ftecan-fluentcontrol\u002Fconnect-and-run","03.operate\u002F30.devices\u002F40.tecan-fluentcontrol\u002F10.connect-and-run",{"title":357,"path":358,"stem":359},"Sending XML Commands","\u002Foperate\u002Fdevices\u002Ftecan-fluentcontrol\u002Fsending-xml-commands","03.operate\u002F30.devices\u002F40.tecan-fluentcontrol\u002F20.sending-xml-commands",{"title":361,"path":362,"stem":363},"Full Workflow Example","\u002Foperate\u002Fdevices\u002Ftecan-fluentcontrol\u002Ffull-workflow-example","03.operate\u002F30.devices\u002F40.tecan-fluentcontrol\u002F30.full-workflow-example",{"title":365,"path":366,"stem":367,"children":368,"page":42},"Device Guides","\u002Fdevice-guides","06.device-guides",[369,372,385,402,415],{"title":365,"path":370,"stem":371},"\u002Fdevice-guides\u002Foverview","06.device-guides\u002F00.overview",{"title":373,"path":374,"stem":375,"children":376,"page":42},"Incubation","\u002Fdevice-guides\u002Fincubation","06.device-guides\u002F20.incubation",[377,381],{"title":378,"path":379,"stem":380},"Inheco ODTC","\u002Fdevice-guides\u002Fincubation\u002Finheco-odtc","06.device-guides\u002F20.incubation\u002F10.inheco-odtc",{"title":382,"path":383,"stem":384},"Inheco SCILA","\u002Fdevice-guides\u002Fincubation\u002Finheco-scila","06.device-guides\u002F20.incubation\u002F20.inheco-scila",{"title":386,"path":387,"stem":388,"children":389,"page":42},"Heater-Shakers","\u002Fdevice-guides\u002Fheater-shakers","06.device-guides\u002F30.heater-shakers",[390,394,398],{"title":391,"path":392,"stem":393},"Inheco Thermoshake","\u002Fdevice-guides\u002Fheater-shakers\u002Finheco-thermoshake","06.device-guides\u002F30.heater-shakers\u002F10.inheco-thermoshake",{"title":395,"path":396,"stem":397},"QInstruments Bioshake","\u002Fdevice-guides\u002Fheater-shakers\u002Fqinstruments-bioshake","06.device-guides\u002F30.heater-shakers\u002F20.qinstruments-bioshake",{"title":399,"path":400,"stem":401},"QInstruments ColdPlate","\u002Fdevice-guides\u002Fheater-shakers\u002Fqinstruments-coldplate","06.device-guides\u002F30.heater-shakers\u002F30.qinstruments-coldplate",{"title":403,"path":404,"stem":405,"children":406,"page":42},"Readers","\u002Fdevice-guides\u002Freaders","06.device-guides\u002F40.readers",[407,411],{"title":408,"path":409,"stem":410},"Biotek Gen5","\u002Fdevice-guides\u002Freaders\u002Fbiotek-gen5","06.device-guides\u002F40.readers\u002F10.biotek-gen5",{"title":412,"path":413,"stem":414},"Biotek Synergy H1","\u002Fdevice-guides\u002Freaders\u002Fbiotek-synergy-h1","06.device-guides\u002F40.readers\u002F20.biotek-synergy-H1",{"title":416,"path":417,"stem":418,"children":419,"page":42},"Tilt & Turn","\u002Fdevice-guides\u002Ftilt-and-turn","06.device-guides\u002F50.tilt-and-turn",[420,424],{"title":421,"path":422,"stem":423},"TurnStation","\u002Fdevice-guides\u002Ftilt-and-turn\u002Fqinstruments-turnstation","06.device-guides\u002F50.tilt-and-turn\u002F10.qinstruments-turnstation",{"title":425,"path":426,"stem":427},"TiltStation","\u002Fdevice-guides\u002Ftilt-and-turn\u002Fqinstruments-tiltstation","06.device-guides\u002F50.tilt-and-turn\u002F20.qinstruments-tiltstation",{"title":429,"path":430,"stem":431,"children":432,"page":42},"Automate","\u002Fautomate","07.automate",[433,437,441,445,494],{"title":434,"path":435,"stem":436},"What is a workflow?","\u002Fautomate\u002Fwhat-is-a-workflow","07.automate\u002F00.what-is-a-workflow",{"title":438,"path":439,"stem":440},"Workflow template","\u002Fautomate\u002Fworkflow-template","07.automate\u002F05.workflow-template",{"title":442,"path":443,"stem":444},"Your First Workflow","\u002Fautomate\u002Fyour-first-workflow","07.automate\u002F08.your-first-workflow",{"title":94,"pages":446,"path":456,"stem":457,"children":458,"page":42},[447,448,449,450,451,452,453,454,455],"workflow","phase","step","runs","input","artifacts","logs","human-in-the-loop","error-handling","\u002Fautomate\u002Fconcepts","07.automate\u002F10.concepts",[459,463,467,471,475,479,483,487,491],{"title":460,"path":461,"stem":462},"Workflow","\u002Fautomate\u002Fconcepts\u002Fworkflow","07.automate\u002F10.concepts\u002F10.workflow",{"title":464,"path":465,"stem":466},"Phase","\u002Fautomate\u002Fconcepts\u002Fphase","07.automate\u002F10.concepts\u002F20.phase",{"title":468,"path":469,"stem":470},"Step","\u002Fautomate\u002Fconcepts\u002Fstep","07.automate\u002F10.concepts\u002F30.step",{"title":472,"path":473,"stem":474},"Runs","\u002Fautomate\u002Fconcepts\u002Fruns","07.automate\u002F10.concepts\u002F40.runs",{"title":476,"path":477,"stem":478},"Input","\u002Fautomate\u002Fconcepts\u002Finput","07.automate\u002F10.concepts\u002F50.input",{"title":480,"path":481,"stem":482},"Artifacts","\u002Fautomate\u002Fconcepts\u002Fartifacts","07.automate\u002F10.concepts\u002F60.artifacts",{"title":484,"path":485,"stem":486},"Logs","\u002Fautomate\u002Fconcepts\u002Flogs","07.automate\u002F10.concepts\u002F70.logs",{"title":488,"path":489,"stem":490},"Human in the Loop","\u002Fautomate\u002Fconcepts\u002Fhuman-in-the-loop","07.automate\u002F10.concepts\u002F80.human-in-the-loop",{"title":183,"path":492,"stem":493},"\u002Fautomate\u002Fconcepts\u002Ferror-handling","07.automate\u002F10.concepts\u002F90.error-handling",{"title":187,"path":495,"stem":496,"children":497,"page":42},"\u002Fautomate\u002Fguides","07.automate\u002F25.guides",[498,502,506,510,514,518,522,526],{"title":499,"path":500,"stem":501},"Deploy a workflow","\u002Fautomate\u002Fguides\u002Fdeploy-a-workflow","07.automate\u002F25.guides\u002F30.deploy-a-workflow",{"title":503,"path":504,"stem":505},"Run a workflow","\u002Fautomate\u002Fguides\u002Frun-a-workflow","07.automate\u002F25.guides\u002F35.run-a-workflow",{"title":507,"path":508,"stem":509},"CI\u002FCD for workflows","\u002Fautomate\u002Fguides\u002Fcicd-for-workflows","07.automate\u002F25.guides\u002F40.cicd-for-workflows",{"title":511,"path":512,"stem":513},"HITL basics","\u002Fautomate\u002Fguides\u002Fbasic-hitl","07.automate\u002F25.guides\u002F50.basic-hitl",{"title":515,"path":516,"stem":517},"Typed operator inputs","\u002Fautomate\u002Fguides\u002Ftyped-operator-inputs","07.automate\u002F25.guides\u002F55.typed-operator-inputs",{"title":519,"path":520,"stem":521},"Error recovery","\u002Fautomate\u002Fguides\u002Fbasic-error-handling","07.automate\u002F25.guides\u002F60.basic-error-handling",{"title":523,"path":524,"stem":525},"Advanced error handling","\u002Fautomate\u002Fguides\u002Fadvanced-error-handling","07.automate\u002F25.guides\u002F70.advanced-error-handling",{"title":527,"path":528,"stem":529},"Workflows REST API","\u002Fautomate\u002Fguides\u002Fworkflows-api","07.automate\u002F25.guides\u002F80.workflows-api",{"title":531,"path":532,"stem":533,"children":534,"page":42},"Observe","\u002Fobserve","08.observe",[535,539,555],{"title":536,"path":537,"stem":538},"Overview","\u002Fobserve\u002Foverview","08.observe\u002F10.overview",{"title":94,"path":540,"stem":541,"children":542,"page":42},"\u002Fobserve\u002Fconcepts","08.observe\u002F20.concepts",[543,547,551],{"title":544,"path":545,"stem":546},"Object Storage","\u002Fobserve\u002Fconcepts\u002Fstorage","08.observe\u002F20.concepts\u002F10.storage",{"title":548,"path":549,"stem":550},"Secrets","\u002Fobserve\u002Fconcepts\u002Fsecrets","08.observe\u002F20.concepts\u002F20.secrets",{"title":552,"path":553,"stem":554},"Data sources","\u002Fobserve\u002Fconcepts\u002Fdata-sources","08.observe\u002F20.concepts\u002F30.data-sources",{"title":187,"path":556,"stem":557,"children":558,"page":42},"\u002Fobserve\u002Fguides","08.observe\u002F30.guides",[559,563],{"title":560,"path":561,"stem":562},"File System Connector","\u002Fobserve\u002Fguides\u002Ffilesystem-connector","08.observe\u002F30.guides\u002F10.filesystem-connector",{"title":564,"path":565,"stem":566},"Building an ETL","\u002Fobserve\u002Fguides\u002Fbuilding-an-etl","08.observe\u002F30.guides\u002F20.building-an-etl",{"title":568,"path":569,"stem":570,"children":571,"page":42},"Technical Reference","\u002Ftechnical-reference","10.technical-reference",[572,576,580,592,603,614,624,635],{"title":573,"path":574,"stem":575},"Introduction","\u002Ftechnical-reference\u002Fplatform-blueprint","10.technical-reference\u002F00.platform-blueprint",{"title":577,"path":578,"stem":579},"REST API","\u002Ftechnical-reference\u002Frest-api","10.technical-reference\u002F01.rest-api",{"title":53,"path":581,"stem":582,"children":583,"page":42},"\u002Ftechnical-reference\u002Fgroundcontrol","10.technical-reference\u002F10.groundcontrol",[584,588],{"title":585,"path":586,"stem":587},"Install & Setup","\u002Ftechnical-reference\u002Fgroundcontrol\u002Finstall","10.technical-reference\u002F10.groundcontrol\u002F10.install",{"title":589,"path":590,"stem":591},"Changelog","\u002Ftechnical-reference\u002Fgroundcontrol\u002Fchangelog","10.technical-reference\u002F10.groundcontrol\u002F20.changelog",{"title":593,"path":594,"stem":595,"children":596,"page":42},"UniteLabs SDK","\u002Ftechnical-reference\u002Fpython-sdk","10.technical-reference\u002F20.python-sdk",[597,600],{"title":585,"path":598,"stem":599},"\u002Ftechnical-reference\u002Fpython-sdk\u002Finstall","10.technical-reference\u002F20.python-sdk\u002F10.install",{"title":589,"path":601,"stem":602},"\u002Ftechnical-reference\u002Fpython-sdk\u002Fchangelog","10.technical-reference\u002F20.python-sdk\u002F20.changelog",{"title":604,"path":605,"stem":606,"children":607,"page":42},"Liquid Handling SDK","\u002Ftechnical-reference\u002Fpython-liquid-handling-sdk","10.technical-reference\u002F30.python-liquid-handling-sdk",[608,611],{"title":585,"path":609,"stem":610},"\u002Ftechnical-reference\u002Fpython-liquid-handling-sdk\u002Finstall","10.technical-reference\u002F30.python-liquid-handling-sdk\u002F10.install",{"title":589,"path":612,"stem":613},"\u002Ftechnical-reference\u002Fpython-liquid-handling-sdk\u002Fchangelog","10.technical-reference\u002F30.python-liquid-handling-sdk\u002F20.changelog",{"title":163,"path":615,"stem":616,"children":617,"page":42},"\u002Ftechnical-reference\u002Flabware","10.technical-reference\u002F40.labware",[618,621],{"title":585,"path":619,"stem":620},"\u002Ftechnical-reference\u002Flabware\u002Finstall","10.technical-reference\u002F40.labware\u002F10.install",{"title":589,"path":622,"stem":623},"\u002Ftechnical-reference\u002Flabware\u002Fchangelog","10.technical-reference\u002F40.labware\u002F20.changelog",{"title":625,"path":626,"stem":627,"children":628,"page":42},"Python Omnibus","\u002Ftechnical-reference\u002Fpython-omnibus","10.technical-reference\u002F50.python-omnibus",[629,632],{"title":585,"path":630,"stem":631},"\u002Ftechnical-reference\u002Fpython-omnibus\u002Finstall","10.technical-reference\u002F50.python-omnibus\u002F10.install",{"title":589,"path":633,"stem":634},"\u002Ftechnical-reference\u002Fpython-omnibus\u002Fchangelog","10.technical-reference\u002F50.python-omnibus\u002F20.changelog",{"title":636,"path":637,"stem":638,"children":639,"page":42},"Python CDK","\u002Ftechnical-reference\u002Fpython-cdk","10.technical-reference\u002F60.python-cdk",[640,643],{"title":585,"path":641,"stem":642},"\u002Ftechnical-reference\u002Fpython-cdk\u002Finstall","10.technical-reference\u002F60.python-cdk\u002F10.install",{"title":589,"path":644,"stem":645},"\u002Ftechnical-reference\u002Fpython-cdk\u002Fchangelog","10.technical-reference\u002F60.python-cdk\u002F20.changelog",{"title":647,"path":648,"stem":649,"children":650},"Connector Development (CDK)","\u002Fconnector-development","20.connector-development",[651,653,672,705,713,744],{"title":647,"path":648,"stem":652},"20.connector-development\u002Findex",{"title":654,"path":655,"stem":656,"children":657,"page":42},"Getting Started","\u002Fconnector-development\u002Fgetting-started","20.connector-development\u002F10.getting-started",[658,661,665,668],{"title":536,"path":659,"stem":660},"\u002Fconnector-development\u002Fgetting-started\u002Foverview","20.connector-development\u002F10.getting-started\u002F10.overview",{"title":662,"path":663,"stem":664},"What's new","\u002Fconnector-development\u002Fgetting-started\u002Fwhats-new","20.connector-development\u002F10.getting-started\u002F20.whats-new",{"title":77,"path":666,"stem":667},"\u002Fconnector-development\u002Fgetting-started\u002Finstallation","20.connector-development\u002F10.getting-started\u002F30.installation",{"title":669,"path":670,"stem":671},"Contributing","\u002Fconnector-development\u002Fgetting-started\u002Fcontributing","20.connector-development\u002F10.getting-started\u002F40.contributing",{"title":673,"path":674,"stem":675,"children":676,"page":42},"Tutorial","\u002Fconnector-development\u002Ftutorial","20.connector-development\u002F20.tutorial",[677,681,685,689,693,697,701],{"title":678,"path":679,"stem":680},"Walkthrough","\u002Fconnector-development\u002Ftutorial\u002Fwalkthrough","20.connector-development\u002F20.tutorial\u002F00.walkthrough",{"title":682,"path":683,"stem":684},"SiLA Endpoints","\u002Fconnector-development\u002Ftutorial\u002Fsila-endpoints","20.connector-development\u002F20.tutorial\u002F10.sila-endpoints",{"title":686,"path":687,"stem":688},"Data Endpoints","\u002Fconnector-development\u002Ftutorial\u002Fdata-endpoints","20.connector-development\u002F20.tutorial\u002F20.data-endpoints",{"title":690,"path":691,"stem":692},"Controls","\u002Fconnector-development\u002Ftutorial\u002Fcontrols","20.connector-development\u002F20.tutorial\u002F30.controls",{"title":694,"path":695,"stem":696},"SiLA Data Types","\u002Fconnector-development\u002Ftutorial\u002Fdata-types","20.connector-development\u002F20.tutorial\u002F40.data-types",{"title":698,"path":699,"stem":700},"Feature","\u002Fconnector-development\u002Ftutorial\u002Fconnector-structure","20.connector-development\u002F20.tutorial\u002F70.connector-structure",{"title":702,"path":703,"stem":704},"Hardware Communication","\u002Fconnector-development\u002Ftutorial\u002Fhardware-communication","20.connector-development\u002F20.tutorial\u002F90.hardware-communication",{"title":94,"path":706,"stem":707,"children":708,"page":42},"\u002Fconnector-development\u002Fconcepts","20.connector-development\u002F30.concepts",[709],{"title":710,"path":711,"stem":712},"SiLA","\u002Fconnector-development\u002Fconcepts\u002Fsila","20.connector-development\u002F30.concepts\u002Fsila",{"title":187,"path":714,"stem":715,"children":716,"page":42},"\u002Fconnector-development\u002Fguides","20.connector-development\u002F40.guides",[717,721,725,729,733,736,740],{"title":718,"path":719,"stem":720},"Configuration","\u002Fconnector-development\u002Fguides\u002Fconfiguration","20.connector-development\u002F40.guides\u002F20.configuration",{"title":722,"path":723,"stem":724},"Deployment","\u002Fconnector-development\u002Fguides\u002Fdeployment","20.connector-development\u002F40.guides\u002F30.deployment",{"title":726,"path":727,"stem":728},"Security","\u002Fconnector-development\u002Fguides\u002Fsecurity","20.connector-development\u002F40.guides\u002F40.security",{"title":730,"path":731,"stem":732},"Subscriptions","\u002Fconnector-development\u002Fguides\u002Fsubscriptions","20.connector-development\u002F40.guides\u002F45.subscriptions",{"title":183,"path":734,"stem":735},"\u002Fconnector-development\u002Fguides\u002Ferror-handling","20.connector-development\u002F40.guides\u002F50.error-handling",{"title":737,"path":738,"stem":739},"Serial Troubleshooting","\u002Fconnector-development\u002Fguides\u002Fserial-troubleshooting","20.connector-development\u002F40.guides\u002F70.serial-troubleshooting",{"title":741,"path":742,"stem":743},"Testing","\u002Fconnector-development\u002Fguides\u002Ftesting","20.connector-development\u002F40.guides\u002F80.testing",{"title":745,"path":746,"stem":747,"children":748},"References","\u002Fconnector-development\u002Freference","20.connector-development\u002F50.reference\u002Findex",[749],{"title":745,"path":746,"stem":747},{"id":751,"title":442,"body":752,"description":2412,"extension":2413,"links":2414,"meta":2415,"navigation":1028,"path":443,"seo":2416,"stem":444,"__hash__":2417},"docs\u002F07.automate\u002F08.your-first-workflow.md",{"type":753,"value":754,"toc":2396},"minimark",[755,765,771,803,808,843,846,854,880,884,891,920,933,940,943,950,957,1071,1084,1091,1423,1457,1464,1478,1482,1502,1505,1522,1526,1542,1604,1611,2304,2307,2336,2347,2351,2392],[756,757,758,759,764],"p",{},"In this guide you'll clone the ",[760,761,763],"a",{"href":762},"\u002Fautomate\u002Fworkflow-template\u002F","workflow template",", run its hello-world example locally to confirm your environment works, and copy it into a new workflow of your own.",[756,766,767],{},[768,769,770],"strong",{},"Prerequisites",[772,773,774,778,790,793,796],"ul",{},[775,776,777],"li",{},"Python 3.12 or newer",[775,779,780,789],{},[760,781,785],{"href":782,"rel":783},"https:\u002F\u002Fdocs.astral.sh\u002Fuv\u002F",[784],"nofollow",[786,787,788],"code",{},"uv"," installed (latest)",[775,791,792],{},"A VS Code based IDE",[775,794,795],{},"A UniteLabs account with API credentials (only needed when you deploy — not for local runs)",[775,797,798,799,802],{},"GitLab SSH access for the ",[786,800,801],{},"unitelabs-*"," SDK libraries",[804,805,807],"h2",{"id":806},"clone-the-template","Clone the template",[809,810,815],"pre",{"className":811,"code":812,"language":813,"meta":814,"style":814},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","git clone https:\u002F\u002Fgitlab.com\u002Funitelabs\u002Fworkflows\u002Fworkflow-template.git\ncd workflow-template\n","bash","",[786,816,817,833],{"__ignoreMap":814},[818,819,822,826,830],"span",{"class":820,"line":821},"line",1,[818,823,825],{"class":824},"sBMFI","git",[818,827,829],{"class":828},"sfazB"," clone",[818,831,832],{"class":828}," https:\u002F\u002Fgitlab.com\u002Funitelabs\u002Fworkflows\u002Fworkflow-template.git\n",[818,834,836,840],{"class":820,"line":835},2,[818,837,839],{"class":838},"s2Zo4","cd",[818,841,842],{"class":828}," workflow-template\n",[756,844,845],{},"The template ships three reference workflows side-by-side:",[809,847,852],{"className":848,"code":850,"language":851},[849],"language-text","workflow-template\u002F\n├── shared\u002F                 # shared library (config, custom labware, reusable @task steps)\n├── w01-hello-world\u002F        # the example we'll use here\n├── w02-liquid-handling\u002F    # real liquid handling demo (runs in simulation)\n├── w03-plateloc-sealer\u002F    # human-in-the-loop demo\n└── scripts\u002Fdeploy.py       # the deploy CLI\n","text",[786,853,850],{"__ignoreMap":814},[756,855,856,857,860,861,864,865,868,869,868,872,875,876,879],{},"Each ",[786,858,859],{},"w*-*\u002F"," directory is a ",[768,862,863],{},"standalone Python package"," — with its own ",[786,866,867],{},"pyproject.toml",", its own ",[786,870,871],{},"uv.lock",[786,873,874],{},".venv",". The ",[786,877,878],{},"shared\u002F"," library is consumed via a path dependency so edits there are picked up by every workflow without a re-sync.",[804,881,883],{"id":882},"sync-the-dependencies","Sync the dependencies",[756,885,886,887,890],{},"Sync ",[786,888,889],{},"shared"," first, then the workflow you want to run:",[809,892,894],{"className":811,"code":893,"language":813,"meta":814,"style":814},"uv sync --directory shared\nuv sync --directory w01-hello-world\n",[786,895,896,909],{"__ignoreMap":814},[818,897,898,900,903,906],{"class":820,"line":821},[818,899,788],{"class":824},[818,901,902],{"class":828}," sync",[818,904,905],{"class":828}," --directory",[818,907,908],{"class":828}," shared\n",[818,910,911,913,915,917],{"class":820,"line":835},[818,912,788],{"class":824},[818,914,902],{"class":828},[818,916,905],{"class":828},[818,918,919],{"class":828}," w01-hello-world\n",[756,921,922,923,926,927,929,930,932],{},"This creates ",[786,924,925],{},"w01-hello-world\u002F.venv\u002F"," with the UniteLabs workflow engine, the UniteLabs SDK pins from the workflow's ",[786,928,867],{},", and ",[786,931,889],{}," installed editable.",[804,934,936,937],{"id":935},"tour-w01-hello-world","Tour ",[786,938,939],{},"w01-hello-world",[756,941,942],{},"Every workflow has the same three pieces.",[944,945,947,948],"h3",{"id":946},"_1-the-package-metadata-pyprojecttoml","1. The package metadata — ",[786,949,867],{},[756,951,952,953,956],{},"The interesting bit is ",[786,954,955],{},"[tool.unitelabs.workflow]"," — that's the contract with the deploy script:",[809,958,963],{"className":959,"code":960,"filename":961,"language":962,"meta":814,"style":814},"language-toml shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","[project]\nname = \"w01-hello-world\"           # the workflow's slug\nversion = \"1.0.1\"                  # bump this when you release\ndescription = \"Sanity check that the SDK is wired correctly.\"\ndependencies = [\n    \"shared\",\n    \"prefect>=3.2.9,\u003C4.0.0\",\n    \"unitelabs-sdk~=0.6.0\",\n    # ...\n]\n\n[tool.unitelabs.workflow]\ndisplay_name = \"[deploy-test] Hello World\"     # what shows on the platform\nentrypoint = \"workflow.py:hello_world_flow\"    # \u003Cfile>:\u003Cfunc> inside the package\ntags = [\"deploy-test\"]\n\n[tool.uv.sources]\nshared = { path = \"..\u002Fshared\", editable = true }\n","w01-hello-world\u002Fpyproject.toml","toml",[786,964,965,970,975,981,987,993,999,1005,1011,1017,1023,1030,1036,1042,1048,1054,1059,1065],{"__ignoreMap":814},[818,966,967],{"class":820,"line":821},[818,968,969],{},"[project]\n",[818,971,972],{"class":820,"line":835},[818,973,974],{},"name = \"w01-hello-world\"           # the workflow's slug\n",[818,976,978],{"class":820,"line":977},3,[818,979,980],{},"version = \"1.0.1\"                  # bump this when you release\n",[818,982,984],{"class":820,"line":983},4,[818,985,986],{},"description = \"Sanity check that the SDK is wired correctly.\"\n",[818,988,990],{"class":820,"line":989},5,[818,991,992],{},"dependencies = [\n",[818,994,996],{"class":820,"line":995},6,[818,997,998],{},"    \"shared\",\n",[818,1000,1002],{"class":820,"line":1001},7,[818,1003,1004],{},"    \"prefect>=3.2.9,\u003C4.0.0\",\n",[818,1006,1008],{"class":820,"line":1007},8,[818,1009,1010],{},"    \"unitelabs-sdk~=0.6.0\",\n",[818,1012,1014],{"class":820,"line":1013},9,[818,1015,1016],{},"    # ...\n",[818,1018,1020],{"class":820,"line":1019},10,[818,1021,1022],{},"]\n",[818,1024,1026],{"class":820,"line":1025},11,[818,1027,1029],{"emptyLinePlaceholder":1028},true,"\n",[818,1031,1033],{"class":820,"line":1032},12,[818,1034,1035],{},"[tool.unitelabs.workflow]\n",[818,1037,1039],{"class":820,"line":1038},13,[818,1040,1041],{},"display_name = \"[deploy-test] Hello World\"     # what shows on the platform\n",[818,1043,1045],{"class":820,"line":1044},14,[818,1046,1047],{},"entrypoint = \"workflow.py:hello_world_flow\"    # \u003Cfile>:\u003Cfunc> inside the package\n",[818,1049,1051],{"class":820,"line":1050},15,[818,1052,1053],{},"tags = [\"deploy-test\"]\n",[818,1055,1057],{"class":820,"line":1056},16,[818,1058,1029],{"emptyLinePlaceholder":1028},[818,1060,1062],{"class":820,"line":1061},17,[818,1063,1064],{},"[tool.uv.sources]\n",[818,1066,1068],{"class":820,"line":1067},18,[818,1069,1070],{},"shared = { path = \"..\u002Fshared\", editable = true }\n",[756,1072,1073,1074,1077,1078,929,1081,1083],{},"The deploy script reads ",[786,1075,1076],{},"[project].name",", ",[786,1079,1080],{},"[project].version",[786,1082,955],{}," directly from this file. There's no central manifest to keep in sync.",[944,1085,1087,1088],{"id":1086},"_2-the-flow-srcw01_hello_worldworkflowpy","2. The flow — ",[786,1089,1090],{},"src\u002Fw01_hello_world\u002Fworkflow.py",[809,1092,1097],{"className":1093,"code":1094,"filename":1095,"language":1096,"meta":814,"style":814},"language-python shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","from unitelabs.labware import __version__ as labware_version\nfrom unitelabs.liquid_handling import __version__ as liquid_handling_version\nfrom unitelabs.sdk import __version__ as sdk_version\nfrom unitelabs.sdk import workflow, get_logger\n\n\n@workflow(\n    name=\"Hello World\",\n    retries=0,\n)\nasync def hello_world_flow(recipient_name: str = \"world\") -> None:\n    \"\"\"Log a greeting and SDK version info to confirm the environment works.\"\"\"\n    logger = get_logger()\n    logger.info(f\"Hello, {recipient_name}!\")\n    logger.info(f\"UniteLabs SDK:             {sdk_version}\")\n    logger.info(f\"UniteLabs Labware:         {labware_version}\")\n    logger.info(f\"UniteLabs Liquid Handling: {liquid_handling_version}\")\n","w01-hello-world\u002Fsrc\u002Fw01_hello_world\u002Fworkflow.py","python",[786,1098,1099,1128,1148,1168,1189,1193,1197,1207,1227,1240,1245,1289,1301,1314,1345,1371,1397],{"__ignoreMap":814},[818,1100,1101,1105,1109,1113,1116,1119,1122,1125],{"class":820,"line":821},[818,1102,1104],{"class":1103},"s7zQu","from",[818,1106,1108],{"class":1107},"sTEyZ"," unitelabs",[818,1110,1112],{"class":1111},"sMK4o",".",[818,1114,1115],{"class":1107},"labware ",[818,1117,1118],{"class":1103},"import",[818,1120,1121],{"class":1107}," __version__ ",[818,1123,1124],{"class":1103},"as",[818,1126,1127],{"class":1107}," labware_version\n",[818,1129,1130,1132,1134,1136,1139,1141,1143,1145],{"class":820,"line":835},[818,1131,1104],{"class":1103},[818,1133,1108],{"class":1107},[818,1135,1112],{"class":1111},[818,1137,1138],{"class":1107},"liquid_handling ",[818,1140,1118],{"class":1103},[818,1142,1121],{"class":1107},[818,1144,1124],{"class":1103},[818,1146,1147],{"class":1107}," liquid_handling_version\n",[818,1149,1150,1152,1154,1156,1159,1161,1163,1165],{"class":820,"line":977},[818,1151,1104],{"class":1103},[818,1153,1108],{"class":1107},[818,1155,1112],{"class":1111},[818,1157,1158],{"class":1107},"sdk ",[818,1160,1118],{"class":1103},[818,1162,1121],{"class":1107},[818,1164,1124],{"class":1103},[818,1166,1167],{"class":1107}," sdk_version\n",[818,1169,1170,1172,1174,1176,1178,1180,1183,1186],{"class":820,"line":983},[818,1171,1104],{"class":1103},[818,1173,1108],{"class":1107},[818,1175,1112],{"class":1111},[818,1177,1158],{"class":1107},[818,1179,1118],{"class":1103},[818,1181,1182],{"class":1107}," workflow",[818,1184,1185],{"class":1111},",",[818,1187,1188],{"class":1107}," get_logger\n",[818,1190,1191],{"class":820,"line":989},[818,1192,1029],{"emptyLinePlaceholder":1028},[818,1194,1195],{"class":820,"line":995},[818,1196,1029],{"emptyLinePlaceholder":1028},[818,1198,1199,1202,1204],{"class":820,"line":1001},[818,1200,1201],{"class":1111},"@",[818,1203,447],{"class":838},[818,1205,1206],{"class":1111},"(\n",[818,1208,1209,1213,1216,1219,1222,1224],{"class":820,"line":1007},[818,1210,1212],{"class":1211},"sHdIc","    name",[818,1214,1215],{"class":1111},"=",[818,1217,1218],{"class":1111},"\"",[818,1220,1221],{"class":828},"Hello World",[818,1223,1218],{"class":1111},[818,1225,1226],{"class":1111},",\n",[818,1228,1229,1232,1234,1238],{"class":820,"line":1013},[818,1230,1231],{"class":1211},"    retries",[818,1233,1215],{"class":1111},[818,1235,1237],{"class":1236},"sbssI","0",[818,1239,1226],{"class":1111},[818,1241,1242],{"class":820,"line":1019},[818,1243,1244],{"class":1111},")\n",[818,1246,1247,1251,1254,1257,1260,1263,1266,1269,1272,1275,1278,1280,1283,1286],{"class":820,"line":1025},[818,1248,1250],{"class":1249},"spNyl","async",[818,1252,1253],{"class":1249}," def",[818,1255,1256],{"class":838}," hello_world_flow",[818,1258,1259],{"class":1111},"(",[818,1261,1262],{"class":1211},"recipient_name",[818,1264,1265],{"class":1111},":",[818,1267,1268],{"class":824}," str",[818,1270,1271],{"class":1111}," =",[818,1273,1274],{"class":1111}," \"",[818,1276,1277],{"class":828},"world",[818,1279,1218],{"class":1111},[818,1281,1282],{"class":1111},")",[818,1284,1285],{"class":1111}," ->",[818,1287,1288],{"class":1111}," None:\n",[818,1290,1291,1294,1298],{"class":820,"line":1032},[818,1292,1293],{"class":1103},"    \"\"\"",[818,1295,1297],{"class":1296},"sHwdD","Log a greeting and SDK version info to confirm the environment works.",[818,1299,1300],{"class":1103},"\"\"\"\n",[818,1302,1303,1306,1308,1311],{"class":820,"line":1038},[818,1304,1305],{"class":1107},"    logger ",[818,1307,1215],{"class":1111},[818,1309,1310],{"class":838}," get_logger",[818,1312,1313],{"class":1111},"()\n",[818,1315,1316,1319,1321,1324,1326,1329,1332,1335,1337,1340,1343],{"class":820,"line":1044},[818,1317,1318],{"class":1107},"    logger",[818,1320,1112],{"class":1111},[818,1322,1323],{"class":838},"info",[818,1325,1259],{"class":1111},[818,1327,1328],{"class":1249},"f",[818,1330,1331],{"class":828},"\"Hello, ",[818,1333,1334],{"class":1236},"{",[818,1336,1262],{"class":838},[818,1338,1339],{"class":1236},"}",[818,1341,1342],{"class":828},"!\"",[818,1344,1244],{"class":1111},[818,1346,1347,1349,1351,1353,1355,1357,1360,1362,1365,1367,1369],{"class":820,"line":1050},[818,1348,1318],{"class":1107},[818,1350,1112],{"class":1111},[818,1352,1323],{"class":838},[818,1354,1259],{"class":1111},[818,1356,1328],{"class":1249},[818,1358,1359],{"class":828},"\"UniteLabs SDK:             ",[818,1361,1334],{"class":1236},[818,1363,1364],{"class":838},"sdk_version",[818,1366,1339],{"class":1236},[818,1368,1218],{"class":828},[818,1370,1244],{"class":1111},[818,1372,1373,1375,1377,1379,1381,1383,1386,1388,1391,1393,1395],{"class":820,"line":1056},[818,1374,1318],{"class":1107},[818,1376,1112],{"class":1111},[818,1378,1323],{"class":838},[818,1380,1259],{"class":1111},[818,1382,1328],{"class":1249},[818,1384,1385],{"class":828},"\"UniteLabs Labware:         ",[818,1387,1334],{"class":1236},[818,1389,1390],{"class":838},"labware_version",[818,1392,1339],{"class":1236},[818,1394,1218],{"class":828},[818,1396,1244],{"class":1111},[818,1398,1399,1401,1403,1405,1407,1409,1412,1414,1417,1419,1421],{"class":820,"line":1061},[818,1400,1318],{"class":1107},[818,1402,1112],{"class":1111},[818,1404,1323],{"class":838},[818,1406,1259],{"class":1111},[818,1408,1328],{"class":1249},[818,1410,1411],{"class":828},"\"UniteLabs Liquid Handling: ",[818,1413,1334],{"class":1236},[818,1415,1416],{"class":838},"liquid_handling_version",[818,1418,1339],{"class":1236},[818,1420,1218],{"class":828},[818,1422,1244],{"class":1111},[756,1424,1425,1426,1428,1429,1432,1433,1436,1437,1440,1441,1444,1445,1448,1449,1452,1453,1112],{},"A workflow is just an ",[786,1427,1250],{}," function decorated with ",[786,1430,1431],{},"@workflow",". Larger workflows split into ",[768,1434,1435],{},"phases"," (also ",[786,1438,1439],{},"@phase","-decorated) and ",[768,1442,1443],{},"steps"," (",[786,1446,1447],{},"@step","-decorated, often coming from ",[786,1450,1451],{},"shared\u002Fsteps\u002F",") — see the ",[760,1454,1456],{"href":1455},"\u002Fautomate\u002Fconcepts\u002Fworkflow\u002F","Workflow → Phase → Step taxonomy",[944,1458,1460,1461],{"id":1459},"_3-the-entrypoint-srcw01_hello_world__main__py","3. The entrypoint — ",[786,1462,1463],{},"src\u002Fw01_hello_world\u002F__main__.py",[756,1465,1466,1467,1470,1471,1474,1475,1112],{},"This is what ",[786,1468,1469],{},"uv run --directory w01-hello-world workflow"," calls — a thin wrapper that runs ",[786,1472,1473],{},"hello_world_flow"," via ",[786,1476,1477],{},"asyncio.run",[804,1479,1481],{"id":1480},"run-it-locally","Run it locally",[809,1483,1485],{"className":811,"code":1484,"language":813,"meta":814,"style":814},"uv run --directory w01-hello-world workflow\n",[786,1486,1487],{"__ignoreMap":814},[818,1488,1489,1491,1494,1496,1499],{"class":820,"line":821},[818,1490,788],{"class":824},[818,1492,1493],{"class":828}," run",[818,1495,905],{"class":828},[818,1497,1498],{"class":828}," w01-hello-world",[818,1500,1501],{"class":828}," workflow\n",[756,1503,1504],{},"You should see the log output with the greeting and three SDK version lines. No credentials, no hardware.",[1506,1507,1509],"callout",{"icon":1508},"i-heroicons-light-bulb",[756,1510,1511,1512,1514,1515,1517,1518,1521],{},"The ",[786,1513,447],{}," console script is declared in each workflow's ",[786,1516,867],{}," under ",[786,1519,1520],{},"[project.scripts]"," — every workflow exposes the same entry, so the run command is identical regardless of which workflow you point at.",[804,1523,1525],{"id":1524},"create-your-own-first-workflow","Create your own first workflow",[756,1527,1528,1529,1531,1532,1535,1536,1539,1540,1265],{},"The mechanical recipe — copy ",[786,1530,939],{}," to your own ",[786,1533,1534],{},"w**-..."," directory and add it as a separate workspace in ",[786,1537,1538],{},"workflow-template.code-workspace",". Then update the new workflow's ",[786,1541,867],{},[809,1543,1546],{"className":959,"code":1544,"filename":1545,"language":962,"meta":814,"style":814},"[project]\nname = \"w02-sample-quality\"\nversion = \"0.1.0\"\ndescription = \"Fetch samples and evaluate them against a concentration threshold.\"\n\n[project.scripts]\nworkflow = \"w02_sample_quality.__main__:main\"   # match the new package name\n\n[tool.unitelabs.workflow]\ndisplay_name = \"Sample Quality\"\nentrypoint = \"workflow.py:sample_quality_flow\"\ntags = [\"qc\"]\n","w02-sample-quality\u002Fpyproject.toml",[786,1547,1548,1552,1557,1562,1567,1571,1576,1581,1585,1589,1594,1599],{"__ignoreMap":814},[818,1549,1550],{"class":820,"line":821},[818,1551,969],{},[818,1553,1554],{"class":820,"line":835},[818,1555,1556],{},"name = \"w02-sample-quality\"\n",[818,1558,1559],{"class":820,"line":977},[818,1560,1561],{},"version = \"0.1.0\"\n",[818,1563,1564],{"class":820,"line":983},[818,1565,1566],{},"description = \"Fetch samples and evaluate them against a concentration threshold.\"\n",[818,1568,1569],{"class":820,"line":989},[818,1570,1029],{"emptyLinePlaceholder":1028},[818,1572,1573],{"class":820,"line":995},[818,1574,1575],{},"[project.scripts]\n",[818,1577,1578],{"class":820,"line":1001},[818,1579,1580],{},"workflow = \"w02_sample_quality.__main__:main\"   # match the new package name\n",[818,1582,1583],{"class":820,"line":1007},[818,1584,1029],{"emptyLinePlaceholder":1028},[818,1586,1587],{"class":820,"line":1013},[818,1588,1035],{},[818,1590,1591],{"class":820,"line":1019},[818,1592,1593],{},"display_name = \"Sample Quality\"\n",[818,1595,1596],{"class":820,"line":1025},[818,1597,1598],{},"entrypoint = \"workflow.py:sample_quality_flow\"\n",[818,1600,1601],{"class":820,"line":1032},[818,1602,1603],{},"tags = [\"qc\"]\n",[756,1605,1606,1607,1610],{},"And rewrite ",[786,1608,1609],{},"workflow.py"," with the flow of your own — for example, a quality check that fetches samples and applies a concentration threshold:",[809,1612,1615],{"className":1093,"code":1613,"filename":1614,"language":1096,"meta":814,"style":814},"from unitelabs.sdk import (\n    workflow,\n    phase,\n    step,\n    get_logger\n)\n\n@step(name=\"Fetch Samples\")\nasync def fetch_samples_task(source: str) -> list[dict]:\n    logger = get_logger()\n    logger.info(f\"Fetching samples from {source}\")\n    # Replace with your actual data retrieval.\n    return [\n        {\"id\": \"sample_001\", \"concentration\": 450.0},\n        {\"id\": \"sample_002\", \"concentration\": 210.0},\n        {\"id\": \"sample_003\", \"concentration\": 890.0},\n    ]\n\n\n@step(name=\"Evaluate Samples\")\nasync def evaluate_samples_task(samples: list[dict], min_concentration: float) -> dict:\n    passed = [s for s in samples if s[\"concentration\"] >= min_concentration]\n    failed = [s for s in samples if s[\"concentration\"] \u003C min_concentration]\n    return {\n        \"passed\": passed,\n        \"failed\": failed,\n        \"pass_rate\": len(passed) \u002F len(samples) if samples else 0.0,\n    }\n\n\n@phase(name=\"Sample Quality\", retries=0)\nasync def sample_quality_flow(\n    source: str = \"data_warehouse\",\n    min_concentration: float = 300.0,\n) -> dict:\n    \"\"\"Fetch samples and evaluate them against a concentration threshold.\"\"\"\n    samples = await fetch_samples_task(source=source)\n    return await evaluate_samples_task(samples=samples, min_concentration=min_concentration)\n","w02-sample-quality\u002Fsrc\u002Fw02_sample_quality\u002Fworkflow.py",[786,1616,1617,1632,1639,1646,1653,1658,1662,1666,1688,1722,1732,1757,1762,1770,1808,1842,1876,1881,1885,1890,1912,1956,2006,2047,2055,2073,2090,2135,2141,2146,2151,2182,2194,2215,2232,2243,2253,2276],{"__ignoreMap":814},[818,1618,1619,1621,1623,1625,1627,1629],{"class":820,"line":821},[818,1620,1104],{"class":1103},[818,1622,1108],{"class":1107},[818,1624,1112],{"class":1111},[818,1626,1158],{"class":1107},[818,1628,1118],{"class":1103},[818,1630,1631],{"class":1111}," (\n",[818,1633,1634,1637],{"class":820,"line":835},[818,1635,1636],{"class":1107},"    workflow",[818,1638,1226],{"class":1111},[818,1640,1641,1644],{"class":820,"line":977},[818,1642,1643],{"class":1107},"    phase",[818,1645,1226],{"class":1111},[818,1647,1648,1651],{"class":820,"line":983},[818,1649,1650],{"class":1107},"    step",[818,1652,1226],{"class":1111},[818,1654,1655],{"class":820,"line":989},[818,1656,1657],{"class":1107},"    get_logger\n",[818,1659,1660],{"class":820,"line":995},[818,1661,1244],{"class":1111},[818,1663,1664],{"class":820,"line":1001},[818,1665,1029],{"emptyLinePlaceholder":1028},[818,1667,1668,1670,1672,1674,1677,1679,1681,1684,1686],{"class":820,"line":1007},[818,1669,1201],{"class":1111},[818,1671,449],{"class":838},[818,1673,1259],{"class":1111},[818,1675,1676],{"class":1211},"name",[818,1678,1215],{"class":1111},[818,1680,1218],{"class":1111},[818,1682,1683],{"class":828},"Fetch Samples",[818,1685,1218],{"class":1111},[818,1687,1244],{"class":1111},[818,1689,1690,1692,1694,1697,1699,1702,1704,1706,1708,1710,1713,1716,1719],{"class":820,"line":1013},[818,1691,1250],{"class":1249},[818,1693,1253],{"class":1249},[818,1695,1696],{"class":838}," fetch_samples_task",[818,1698,1259],{"class":1111},[818,1700,1701],{"class":1211},"source",[818,1703,1265],{"class":1111},[818,1705,1268],{"class":824},[818,1707,1282],{"class":1111},[818,1709,1285],{"class":1111},[818,1711,1712],{"class":1107}," list",[818,1714,1715],{"class":1111},"[",[818,1717,1718],{"class":824},"dict",[818,1720,1721],{"class":1111},"]:\n",[818,1723,1724,1726,1728,1730],{"class":820,"line":1019},[818,1725,1305],{"class":1107},[818,1727,1215],{"class":1111},[818,1729,1310],{"class":838},[818,1731,1313],{"class":1111},[818,1733,1734,1736,1738,1740,1742,1744,1747,1749,1751,1753,1755],{"class":820,"line":1025},[818,1735,1318],{"class":1107},[818,1737,1112],{"class":1111},[818,1739,1323],{"class":838},[818,1741,1259],{"class":1111},[818,1743,1328],{"class":1249},[818,1745,1746],{"class":828},"\"Fetching samples from ",[818,1748,1334],{"class":1236},[818,1750,1701],{"class":838},[818,1752,1339],{"class":1236},[818,1754,1218],{"class":828},[818,1756,1244],{"class":1111},[818,1758,1759],{"class":820,"line":1032},[818,1760,1761],{"class":1296},"    # Replace with your actual data retrieval.\n",[818,1763,1764,1767],{"class":820,"line":1038},[818,1765,1766],{"class":1103},"    return",[818,1768,1769],{"class":1111}," [\n",[818,1771,1772,1775,1777,1780,1782,1784,1786,1789,1791,1793,1795,1798,1800,1802,1805],{"class":820,"line":1044},[818,1773,1774],{"class":1111},"        {",[818,1776,1218],{"class":1111},[818,1778,1779],{"class":828},"id",[818,1781,1218],{"class":1111},[818,1783,1265],{"class":1111},[818,1785,1274],{"class":1111},[818,1787,1788],{"class":828},"sample_001",[818,1790,1218],{"class":1111},[818,1792,1185],{"class":1111},[818,1794,1274],{"class":1111},[818,1796,1797],{"class":828},"concentration",[818,1799,1218],{"class":1111},[818,1801,1265],{"class":1111},[818,1803,1804],{"class":1236}," 450.0",[818,1806,1807],{"class":1111},"},\n",[818,1809,1810,1812,1814,1816,1818,1820,1822,1825,1827,1829,1831,1833,1835,1837,1840],{"class":820,"line":1050},[818,1811,1774],{"class":1111},[818,1813,1218],{"class":1111},[818,1815,1779],{"class":828},[818,1817,1218],{"class":1111},[818,1819,1265],{"class":1111},[818,1821,1274],{"class":1111},[818,1823,1824],{"class":828},"sample_002",[818,1826,1218],{"class":1111},[818,1828,1185],{"class":1111},[818,1830,1274],{"class":1111},[818,1832,1797],{"class":828},[818,1834,1218],{"class":1111},[818,1836,1265],{"class":1111},[818,1838,1839],{"class":1236}," 210.0",[818,1841,1807],{"class":1111},[818,1843,1844,1846,1848,1850,1852,1854,1856,1859,1861,1863,1865,1867,1869,1871,1874],{"class":820,"line":1056},[818,1845,1774],{"class":1111},[818,1847,1218],{"class":1111},[818,1849,1779],{"class":828},[818,1851,1218],{"class":1111},[818,1853,1265],{"class":1111},[818,1855,1274],{"class":1111},[818,1857,1858],{"class":828},"sample_003",[818,1860,1218],{"class":1111},[818,1862,1185],{"class":1111},[818,1864,1274],{"class":1111},[818,1866,1797],{"class":828},[818,1868,1218],{"class":1111},[818,1870,1265],{"class":1111},[818,1872,1873],{"class":1236}," 890.0",[818,1875,1807],{"class":1111},[818,1877,1878],{"class":820,"line":1061},[818,1879,1880],{"class":1111},"    ]\n",[818,1882,1883],{"class":820,"line":1067},[818,1884,1029],{"emptyLinePlaceholder":1028},[818,1886,1888],{"class":820,"line":1887},19,[818,1889,1029],{"emptyLinePlaceholder":1028},[818,1891,1893,1895,1897,1899,1901,1903,1905,1908,1910],{"class":820,"line":1892},20,[818,1894,1201],{"class":1111},[818,1896,449],{"class":838},[818,1898,1259],{"class":1111},[818,1900,1676],{"class":1211},[818,1902,1215],{"class":1111},[818,1904,1218],{"class":1111},[818,1906,1907],{"class":828},"Evaluate Samples",[818,1909,1218],{"class":1111},[818,1911,1244],{"class":1111},[818,1913,1915,1917,1919,1922,1924,1927,1929,1931,1933,1935,1938,1941,1943,1946,1948,1950,1953],{"class":820,"line":1914},21,[818,1916,1250],{"class":1249},[818,1918,1253],{"class":1249},[818,1920,1921],{"class":838}," evaluate_samples_task",[818,1923,1259],{"class":1111},[818,1925,1926],{"class":1211},"samples",[818,1928,1265],{"class":1111},[818,1930,1712],{"class":1107},[818,1932,1715],{"class":1111},[818,1934,1718],{"class":824},[818,1936,1937],{"class":1111},"],",[818,1939,1940],{"class":1211}," min_concentration",[818,1942,1265],{"class":1111},[818,1944,1945],{"class":824}," float",[818,1947,1282],{"class":1111},[818,1949,1285],{"class":1111},[818,1951,1952],{"class":824}," dict",[818,1954,1955],{"class":1111},":\n",[818,1957,1959,1962,1964,1967,1970,1973,1976,1979,1982,1985,1988,1990,1992,1994,1996,1999,2002,2004],{"class":820,"line":1958},22,[818,1960,1961],{"class":1107},"    passed ",[818,1963,1215],{"class":1111},[818,1965,1966],{"class":1111}," [",[818,1968,1969],{"class":1107},"s ",[818,1971,1972],{"class":1103},"for",[818,1974,1975],{"class":1107}," s ",[818,1977,1978],{"class":1103},"in",[818,1980,1981],{"class":1107}," samples ",[818,1983,1984],{"class":1103},"if",[818,1986,1987],{"class":1107}," s",[818,1989,1715],{"class":1111},[818,1991,1218],{"class":1111},[818,1993,1797],{"class":828},[818,1995,1218],{"class":1111},[818,1997,1998],{"class":1111},"]",[818,2000,2001],{"class":1111}," >=",[818,2003,1940],{"class":1107},[818,2005,1022],{"class":1111},[818,2007,2009,2012,2014,2016,2018,2020,2022,2024,2026,2028,2030,2032,2034,2036,2038,2040,2043,2045],{"class":820,"line":2008},23,[818,2010,2011],{"class":1107},"    failed ",[818,2013,1215],{"class":1111},[818,2015,1966],{"class":1111},[818,2017,1969],{"class":1107},[818,2019,1972],{"class":1103},[818,2021,1975],{"class":1107},[818,2023,1978],{"class":1103},[818,2025,1981],{"class":1107},[818,2027,1984],{"class":1103},[818,2029,1987],{"class":1107},[818,2031,1715],{"class":1111},[818,2033,1218],{"class":1111},[818,2035,1797],{"class":828},[818,2037,1218],{"class":1111},[818,2039,1998],{"class":1111},[818,2041,2042],{"class":1111}," \u003C",[818,2044,1940],{"class":1107},[818,2046,1022],{"class":1111},[818,2048,2050,2052],{"class":820,"line":2049},24,[818,2051,1766],{"class":1103},[818,2053,2054],{"class":1111}," {\n",[818,2056,2058,2061,2064,2066,2068,2071],{"class":820,"line":2057},25,[818,2059,2060],{"class":1111},"        \"",[818,2062,2063],{"class":828},"passed",[818,2065,1218],{"class":1111},[818,2067,1265],{"class":1111},[818,2069,2070],{"class":1107}," passed",[818,2072,1226],{"class":1111},[818,2074,2076,2078,2081,2083,2085,2088],{"class":820,"line":2075},26,[818,2077,2060],{"class":1111},[818,2079,2080],{"class":828},"failed",[818,2082,1218],{"class":1111},[818,2084,1265],{"class":1111},[818,2086,2087],{"class":1107}," failed",[818,2089,1226],{"class":1111},[818,2091,2093,2095,2098,2100,2102,2105,2107,2109,2111,2114,2116,2118,2120,2122,2125,2127,2130,2133],{"class":820,"line":2092},27,[818,2094,2060],{"class":1111},[818,2096,2097],{"class":828},"pass_rate",[818,2099,1218],{"class":1111},[818,2101,1265],{"class":1111},[818,2103,2104],{"class":838}," len",[818,2106,1259],{"class":1111},[818,2108,2063],{"class":838},[818,2110,1282],{"class":1111},[818,2112,2113],{"class":1111}," \u002F",[818,2115,2104],{"class":838},[818,2117,1259],{"class":1111},[818,2119,1926],{"class":838},[818,2121,1282],{"class":1111},[818,2123,2124],{"class":1103}," if",[818,2126,1981],{"class":1107},[818,2128,2129],{"class":1103},"else",[818,2131,2132],{"class":1236}," 0.0",[818,2134,1226],{"class":1111},[818,2136,2138],{"class":820,"line":2137},28,[818,2139,2140],{"class":1111},"    }\n",[818,2142,2144],{"class":820,"line":2143},29,[818,2145,1029],{"emptyLinePlaceholder":1028},[818,2147,2149],{"class":820,"line":2148},30,[818,2150,1029],{"emptyLinePlaceholder":1028},[818,2152,2154,2156,2158,2160,2162,2164,2166,2169,2171,2173,2176,2178,2180],{"class":820,"line":2153},31,[818,2155,1201],{"class":1111},[818,2157,448],{"class":838},[818,2159,1259],{"class":1111},[818,2161,1676],{"class":1211},[818,2163,1215],{"class":1111},[818,2165,1218],{"class":1111},[818,2167,2168],{"class":828},"Sample Quality",[818,2170,1218],{"class":1111},[818,2172,1185],{"class":1111},[818,2174,2175],{"class":1211}," retries",[818,2177,1215],{"class":1111},[818,2179,1237],{"class":1236},[818,2181,1244],{"class":1111},[818,2183,2185,2187,2189,2192],{"class":820,"line":2184},32,[818,2186,1250],{"class":1249},[818,2188,1253],{"class":1249},[818,2190,2191],{"class":838}," sample_quality_flow",[818,2193,1206],{"class":1111},[818,2195,2197,2200,2202,2204,2206,2208,2211,2213],{"class":820,"line":2196},33,[818,2198,2199],{"class":1211},"    source",[818,2201,1265],{"class":1111},[818,2203,1268],{"class":824},[818,2205,1271],{"class":1111},[818,2207,1274],{"class":1111},[818,2209,2210],{"class":828},"data_warehouse",[818,2212,1218],{"class":1111},[818,2214,1226],{"class":1111},[818,2216,2218,2221,2223,2225,2227,2230],{"class":820,"line":2217},34,[818,2219,2220],{"class":1211},"    min_concentration",[818,2222,1265],{"class":1111},[818,2224,1945],{"class":824},[818,2226,1271],{"class":1111},[818,2228,2229],{"class":1236}," 300.0",[818,2231,1226],{"class":1111},[818,2233,2235,2237,2239,2241],{"class":820,"line":2234},35,[818,2236,1282],{"class":1111},[818,2238,1285],{"class":1111},[818,2240,1952],{"class":824},[818,2242,1955],{"class":1111},[818,2244,2246,2248,2251],{"class":820,"line":2245},36,[818,2247,1293],{"class":1103},[818,2249,2250],{"class":1296},"Fetch samples and evaluate them against a concentration threshold.",[818,2252,1300],{"class":1103},[818,2254,2256,2259,2261,2264,2266,2268,2270,2272,2274],{"class":820,"line":2255},37,[818,2257,2258],{"class":1107},"    samples ",[818,2260,1215],{"class":1111},[818,2262,2263],{"class":1103}," await",[818,2265,1696],{"class":838},[818,2267,1259],{"class":1111},[818,2269,1701],{"class":1211},[818,2271,1215],{"class":1111},[818,2273,1701],{"class":838},[818,2275,1244],{"class":1111},[818,2277,2279,2281,2283,2285,2287,2289,2291,2293,2295,2297,2299,2302],{"class":820,"line":2278},38,[818,2280,1766],{"class":1103},[818,2282,2263],{"class":1103},[818,2284,1921],{"class":838},[818,2286,1259],{"class":1111},[818,2288,1926],{"class":1211},[818,2290,1215],{"class":1111},[818,2292,1926],{"class":838},[818,2294,1185],{"class":1111},[818,2296,1940],{"class":1211},[818,2298,1215],{"class":1111},[818,2300,2301],{"class":838},"min_concentration",[818,2303,1244],{"class":1111},[756,2305,2306],{},"Sync and run:",[809,2308,2310],{"className":811,"code":2309,"language":813,"meta":814,"style":814},"uv sync --directory w02-sample-quality\nuv run --directory w02-sample-quality workflow\n",[786,2311,2312,2323],{"__ignoreMap":814},[818,2313,2314,2316,2318,2320],{"class":820,"line":821},[818,2315,788],{"class":824},[818,2317,902],{"class":828},[818,2319,905],{"class":828},[818,2321,2322],{"class":828}," w02-sample-quality\n",[818,2324,2325,2327,2329,2331,2334],{"class":820,"line":835},[818,2326,788],{"class":824},[818,2328,1493],{"class":828},[818,2330,905],{"class":828},[818,2332,2333],{"class":828}," w02-sample-quality",[818,2335,1501],{"class":828},[1506,2337,2338],{"icon":1508},[756,2339,2340,2341,2343,2344,2346],{},"Keep each ",[786,2342,1447],{}," focused on one responsibility — fetch, transform, persist, notify. Orchestrate them in the ",[786,2345,1439],{},", not inside the steps themselves. The UniteLabs workflow engine runs independent steps concurrently.",[804,2348,2350],{"id":2349},"next-steps","Next steps",[772,2352,2353,2365,2374,2383],{},[775,2354,2355,2361,2362,1112],{},[760,2356,2358],{"href":2357},"\u002Fautomate\u002Fguides\u002Fdeploy-a-workflow\u002F",[768,2359,2360],{},"Deploy your workflow"," — bundle and ship with ",[786,2363,2364],{},"scripts\u002Fdeploy.py",[775,2366,2367,2373],{},[760,2368,2370],{"href":2369},"\u002Fautomate\u002Fguides\u002Fcicd-for-workflows\u002F",[768,2371,2372],{},"Set up CI\u002FCD"," — automate dev\u002Fstg\u002Fprd deploys on GitHub Actions or GitLab CI.",[775,2375,2376,2382],{},[760,2377,2379],{"href":2378},"\u002Fautomate\u002Fguides\u002Fbasic-error-handling\u002F",[768,2380,2381],{},"Add error handling"," — make failures surface cleanly.",[775,2384,2385,2391],{},[760,2386,2388],{"href":2387},"\u002Fautomate\u002Fguides\u002Fbasic-hitl\u002F",[768,2389,2390],{},"Add human-in-the-loop steps"," — use W02 as the reference pattern.",[2393,2394,2395],"style",{},"html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}",{"title":814,"searchDepth":821,"depth":835,"links":2397},[2398,2399,2400,2409,2410,2411],{"id":806,"depth":835,"text":807},{"id":882,"depth":835,"text":883},{"id":935,"depth":835,"text":2401,"children":2402},"Tour w01-hello-world",[2403,2405,2407],{"id":946,"depth":977,"text":2404},"1. The package metadata — pyproject.toml",{"id":1086,"depth":977,"text":2406},"2. The flow — src\u002Fw01_hello_world\u002Fworkflow.py",{"id":1459,"depth":977,"text":2408},"3. The entrypoint — src\u002Fw01_hello_world\u002F__main__.py",{"id":1480,"depth":835,"text":1481},{"id":1524,"depth":835,"text":1525},{"id":2349,"depth":835,"text":2350},"Clone the workflow template, run the hello-world example locally, and scaffold your own first workflow in under 15 minutes.","md",null,{},{"title":442,"description":2412},"Fpz2rvIhBGxurFOt0jdHp1e8_2GKvp8BiomKmiIrSDM",[2419,2421],{"title":438,"path":439,"stem":440,"description":2420},"Clone a production-ready monorepo, run a workflow in simulation, and deploy any of the three reference workflows to the platform.",{"title":460,"path":461,"stem":462,"description":2422},"The top-level executable process that coordinates phases, data flow, and physical state to achieve a specific scientific outcome.",1783607784699]