<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Orkes Developers</title>
    <description>The latest articles on DEV Community by Orkes Developers (@orkesdev).</description>
    <link>https://dev.to/orkesdev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2246628%2Faebe2ba5-ca87-471a-8aad-30f04a32abce.png</url>
      <title>DEV Community: Orkes Developers</title>
      <link>https://dev.to/orkesdev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/orkesdev"/>
    <language>en</language>
    <item>
      <title>Automating Serialization/Deserialization Tests with Orkes Conductor and LLMs</title>
      <dc:creator>Orkes Developers</dc:creator>
      <pubDate>Thu, 29 May 2025 13:33:11 +0000</pubDate>
      <link>https://dev.to/orkes/automating-serializationdeserialization-tests-with-orkes-conductor-and-llms-2bph</link>
      <guid>https://dev.to/orkes/automating-serializationdeserialization-tests-with-orkes-conductor-and-llms-2bph</guid>
      <description>&lt;p&gt;&lt;strong&gt;Writing unit tests for serialization and deserialization can be time-consuming and repetitive work.&lt;/strong&gt; It’s monotonous and prone to human error, but still essential for ensuring that data is correctly sent across systems (API to server, application to application, SDK clients to server).&lt;/p&gt;

&lt;p&gt;Unlike humans, software systems don’t get tired, bored, or distracted, even if faced with such mind-numbing work of writing serialization and deserialization (SerDe) tests. &lt;/p&gt;

&lt;p&gt;Enter &lt;strong&gt;Orkes Conductor&lt;/strong&gt;, a workflow orchestration platform. Combined with large language models (LLMs), Conductor transformed a week-long grind into a streamlined automation pipeline, cutting the testing time by over half.&lt;/p&gt;

&lt;p&gt;In this post, we’ll walk through what SerDe tests are, why they matter, how we automated their creation using orchestration, and what made Orkes Conductor the ideal orchestration tool for the job.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick recap: serialization/deserialization
&lt;/h2&gt;

&lt;p&gt;Serialization refers to the conversion of a data object from its current state into a format that can be stored in a database or transmitted through a network. For example, a Python object into JSON, or a Java object into a stream of bytes.&lt;/p&gt;

&lt;p&gt;Deserialization is the exact opposite of serialization: it refers to the process of reconstructing the data object from its serialized format so that it can be used again. For example, from JSON back into a Python object so that it can be used in a function.&lt;/p&gt;

&lt;p&gt;Serialization and deserialization are key processes for transmitting data across distributed systems in a standardized format while maintaining usability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why serialization/deserialization tests matter
&lt;/h2&gt;

&lt;p&gt;Serialization and deserialization tests are critical for data integrity. They ensure that your data objects can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Be accurately converted to/from different formats (such as from POJOs to JSON).&lt;/li&gt;
&lt;li&gt;Retain structure and meaning across services.&lt;/li&gt;
&lt;li&gt;Interoperate reliably between client-side and server-side components.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Neglecting these tests can introduce subtle, high-impact bugs, especially in systems where APIs evolve or where SDKs are maintained separately from backend logic. &lt;/p&gt;

&lt;p&gt;Yet writing these tests is typically:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Manual:&lt;/strong&gt; You have to craft JSON input/output cases for each class.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Boilerplate-heavy:&lt;/strong&gt; The structure of each test is nearly identical, with minor differences in class names or references.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error-prone:&lt;/strong&gt; A wrong class reference or mismatched field can easily slip through.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s exactly what our engineering team was facing at Orkes: dozens of nearly identical tests with minor variations. Instead of slogging through them manually, we built an automated solution using Orkes Conductor.&lt;/p&gt;

&lt;h2&gt;
  
  
  Automating SerDe tests using Conductor + LLMs
&lt;/h2&gt;

&lt;p&gt;In our case at Orkes, we needed to create tests to validate the mappings between SDK POJOs and server-side POJOs to ensure that data is transmitted correctly. &lt;/p&gt;

&lt;p&gt;Accurate serialization and deserialization are crucial for the SDK's functionality, as they ensure that workflows and tasks are correctly interpreted by the Conductor server. By including comprehensive tests, developers can confidently make changes to the SDK without introducing regressions in data handling.&lt;/p&gt;

&lt;p&gt;Using an orchestration tool like Orkes Conductor, we can automate repetitive actions across multiple services while ensuring that intermittent failures are remediated through retries and &lt;a href="https://dev.to/orkes/why-your-applications-need-durable-execution-and-best-practices-to-achieve-it-5ham"&gt;state persistence&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here’s the high-level breakdown of the automated process:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Retrieve test resources like mapping files and JSON templates.&lt;/li&gt;
&lt;li&gt;Generate a test branch in the repository.&lt;/li&gt;
&lt;li&gt;Generate the SerDe tests using LLMs and &lt;a href="https://dev.to/orkes/guide-to-prompt-engineering-pof"&gt;prompt engineering&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Polish and publish the test code to the branch.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let’s explore how Conductor’s enterprise functionalities enable seamless automation at each step.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Initial setup and data retrieval
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1hwk9tx070y06mhzy9h6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1hwk9tx070y06mhzy9h6.png" alt="Screenshot of Conductor workflow containing the HTTP and JSON JQ Transform Tasks for data retrieval." width="800" height="1226"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fetch a mapping file that links each SDK POJO to its corresponding server-side POJO.&lt;/li&gt;
&lt;li&gt;Pull JSON templates generated from server POJOs. These templates will serve as the base for test generation.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"templates"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"IndexedDoc"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"score"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;123.456&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"metadata"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"sample_key"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sample_value"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"docId"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sample_docId"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sample_text"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"parentDocId"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sample_parentDocId"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"dependencies"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;rest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;JSON&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;template&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Parse the mapping file to each extract server-to-SDK relationship. Tests will be created for each server-SDK POJO mapping later.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using built-in system tasks like &lt;a href="https://orkes.io/content/reference-docs/system-tasks/http" rel="noopener noreferrer"&gt;HTTP Task&lt;/a&gt; and &lt;a href="https://orkes.io/content/reference-docs/system-tasks/jq-transform" rel="noopener noreferrer"&gt;JSON JQ Transform Task&lt;/a&gt;, these steps can be quickly assembled without needing to code everything from scratch. &lt;/p&gt;

&lt;h3&gt;
  
  
  2. Branch management
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz2rm3yrr97bygxjsgyzp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz2rm3yrr97bygxjsgyzp.png" alt="Screenshot of Conductor workflow containing the HTTP for branch management." width="800" height="693"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Retrieve the SHA of the SDK repo’s target branch.&lt;/li&gt;
&lt;li&gt;Use the SHA to create a new feature branch specifically for test generation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using dynamic references like “${variable}” in the HTTP Task’s URI &lt;code&gt;https://api.github.com/repos/${previousTask.output.owner}/${previousTask.output.repo}/git/refs/heads/${workflow.input.sdkbranch}&lt;/code&gt;, the workflow is repeatable across multiple execution runs. Going beyond, the workflow becomes reusable and can be embedded in other workflows as well.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Iterative test generation using LLMs
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4dj5gjsab9ahqagae1vd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4dj5gjsab9ahqagae1vd.png" alt="Screenshot of Conductor workflow containing a series of tasks in a Do While loop for iterative test generation." width="800" height="594"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we arrive at the heart of the workflow. For each server-SDK POJO mapping, the workflow will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fetch the SDK POJO source code and file SHA for version control.&lt;/li&gt;
&lt;li&gt;Use the class path to generate a JSON representation.&lt;/li&gt;
&lt;li&gt;Clean the Java class (remove annotations/comments) using GPT-4o.&lt;/li&gt;
&lt;li&gt;Generate the actual test code via prompt engineering and LLM assistance.&lt;/li&gt;
&lt;li&gt;Encode the test, create the proper file path, and commit the file to the new branch.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The suite of pre-built LLM tasks like &lt;a href="https://orkes.io/content/reference-docs/ai-tasks/llm-text-complete" rel="noopener noreferrer"&gt;LLM Text Complete&lt;/a&gt; facilitates rapid assembly of AI-powered tasks using any LLM provider. Conductor also supports prompt management, so you can create, test, and refine your prompts. Here is a snippet of an initial prompt to generate the test code:&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Polish and publish
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F97ebccufbmf8w2rx79sz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F97ebccufbmf8w2rx79sz.png" alt="Screenshot of Conductor workflow containing the Simple and HTTP Tasks for polishing and publishing." width="800" height="853"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With all the test code generated, it’s time to wrap up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run &lt;a href="https://github.com/diffplug/spotless" rel="noopener noreferrer"&gt;Spotless&lt;/a&gt; to auto-format the code for style consistency.&lt;/li&gt;
&lt;li&gt;Create a Pull Request for all the new test files.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Conductor tracks the data flow of every single task for each workflow run, making it easy to audit what has happened. Here is the execution trace of an example execution:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"ownerApp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user@example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"createTime"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1744977613276&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"updateTime"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1744978814626&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"createdBy"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user@example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"COMPLETED"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"endTime"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1744978814621&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"workflowId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"af4f073b-1c4c-11f0-8645-4e34a87470b0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
 &lt;/span&gt;&lt;span class="nl"&gt;"tasks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"taskType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"HTTP"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"COMPLETED"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"inputData"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nl"&gt;"asyncComplete"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nl"&gt;"http_request"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
         &lt;/span&gt;&lt;span class="nl"&gt;"headers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
           &lt;/span&gt;&lt;span class="nl"&gt;"Authorization"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"token &lt;/span&gt;&lt;span class="se"&gt;\$&lt;/span&gt;&lt;span class="s2"&gt;{workflow.secrets.githubToken}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
           &lt;/span&gt;&lt;span class="nl"&gt;"Accept"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"application/json"&lt;/span&gt;&lt;span class="w"&gt;
         &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
         &lt;/span&gt;&lt;span class="nl"&gt;"method"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"GET"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
         &lt;/span&gt;&lt;span class="nl"&gt;"uri"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://raw.githubusercontent.com/orkes-io/sdk-codegen/base-code/conductor-java-sdk/SdkServerpojoMappings.json"&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"referenceTaskName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"getMappingFile"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"retryCount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"seq"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"pollCount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"taskDefName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"get_mapping_file"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"scheduledTime"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1744977613280&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"startTime"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1744977613299&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"endTime"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1744977613321&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"updateTime"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1744977613299&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"startDelayInSeconds"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"retried"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"executed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"workflowInstanceId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"af4f073b-1c4c-11f0-8645-4e34a87470b0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"workflowType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"SDK_POJO_ser_deser_test"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"taskId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"af4fa37c-1c4c-11f0-8645-4e34a87470b0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"callbackAfterSeconds"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"workerId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"orkes-workers-deployment-6c5b9f55dc-5xknz"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"outputData"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="nl"&gt;"response"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why use Orkes Conductor?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Orchestration at scale&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Conductor is built for chaining together complex, fault-tolerant workflows. This automation pipeline included over a dozen steps, with multiple dependencies across GitHub, OpenAI, and other services — exactly what Conductor was designed to handle.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LLM-ready&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Not every task is rigid. For creative, generative work like cleaning up Java classes or writing test code, LLMs excel even when traditional automation breaks down. Conductor made it easy to drop in LLM-powered steps wherever flexible automation was required.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reusable components&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once we built workers for custom tasks like applying Spotless auto-formatting and generating JSON templates, they became modular, reusable components. Now, creating a new workflow for a different use is just a matter of assembling these pieces together.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Developer-friendly&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;With &lt;strong&gt;REST APIs&lt;/strong&gt;, &lt;strong&gt;SDKs&lt;/strong&gt;, and a powerful &lt;strong&gt;UI&lt;/strong&gt;, Conductor meets you where you are. Whether you need full developer tooling to build integrated workflows with your systems or visual dashboards to get complete visibility into the pipeline’s execution, Conductor’s product suite makes it seamless.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scaling work from days to minutes
&lt;/h2&gt;

&lt;p&gt;The original estimate for manually writing SerDe tests for this task was more than 5 days. Using Conductor and LLMs? Just 2.5 days to build and test the workflow itself. Now that the automated system exists, regenerating or extending the tests takes &lt;strong&gt;less than an hour&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;More than just saving time, Orkes Conductor reframed how to think about developer productivity. Using Orkes Conductor with LLMs lets you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Automate repetitive tasks&lt;/strong&gt;, even those with variations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Focus your energy on high-value work&lt;/strong&gt;, like reviewing code and refining scalable systems.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maximize your impact&lt;/strong&gt; by reusing components across projects.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The next time you need to ask yourself: “&lt;strong&gt;Can I orchestrate this instead?&lt;/strong&gt;”&lt;/p&gt;

&lt;p&gt;Because chances are, with Orkes Conductor, the answer is yes. Take a stab at automating repetitive work using our free &lt;a href="https://developer.orkescloud.com/?utm_campaign=automate-serde-tests-blog&amp;amp;utm_source=devto-blog&amp;amp;utm_medium=web" rel="noopener noreferrer"&gt;Developer Playground&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>orchestration</category>
      <category>automation</category>
      <category>testing</category>
      <category>ai</category>
    </item>
    <item>
      <title>Workflow-Level Resilience in Orkes Conductor: Timeouts and Failure Workflows</title>
      <dc:creator>Orkes Developers</dc:creator>
      <pubDate>Mon, 12 May 2025 09:07:15 +0000</pubDate>
      <link>https://dev.to/orkes/workflow-level-resilience-in-orkes-conductor-timeouts-and-failure-workflows-1nc5</link>
      <guid>https://dev.to/orkes/workflow-level-resilience-in-orkes-conductor-timeouts-and-failure-workflows-1nc5</guid>
      <description>&lt;p&gt;Building resilient, production-grade workflows means preparing for the unexpected—from task stalls to external service outages. While task-level timeouts catch issues in isolated steps, &lt;strong&gt;workflow-level resilience settings&lt;/strong&gt; act as a safety net for your entire orchestration. They ensure your system behaves predictably under stress and provides a &lt;strong&gt;graceful fallback&lt;/strong&gt; when things go wrong.&lt;/p&gt;

&lt;p&gt;In this post, we’ll explore two key features in Orkes Conductor that help you build robust workflows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Workflow Timeouts&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Failure Workflows&lt;/strong&gt; (a.k.a. Compensation flows)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Workflow timeouts: Don’t let things hang
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;workflow timeout&lt;/strong&gt; defines how long a workflow is allowed to run before it's forcibly marked as timed out. This is crucial when your business logic needs to meet service-level agreements (SLAs) or avoid workflows stalling indefinitely.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Workflow timeout parameters&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Parameter&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;timeoutSeconds&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Maximum duration (in seconds) for which the workflow is allowed to run. If the workflow hasn’t reached a terminal state within this time, it is marked as &lt;em&gt;TIMED_OUT&lt;/em&gt;. Set to 0 to disable.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;timeoutPolicy&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Action to take when a timeout occurs. Supports:&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;TIME_OUT_WF&lt;/strong&gt;–Terminates the workflow as &lt;em&gt;TIMED_OUT&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ALERT_ONLY&lt;/strong&gt;–Logs an alert but lets the workflow continue.&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Use case: E-commerce checkout with 30-minute SLA
&lt;/h3&gt;

&lt;p&gt;Imagine a checkout flow involving payment, inventory locking, and order confirmation. You don’t want stale carts holding inventory hostage for hours. A 30-minute timeout ensures the workflow either completes or fails cleanly.&lt;/p&gt;

&lt;p&gt;Here’s a simplified implementation in Python using the Conductor SDK:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;register_workflow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;workflow_executor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;WorkflowExecutor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ConductorWorkflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# 1) HTTP task to fetch product price (simulated with dummy URL)
&lt;/span&gt;    &lt;span class="n"&gt;fetch_random_number_task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;HttpTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;task_ref_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fetch_random_number&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;http_input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;uri&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://www.random.org/integers/?num=1&amp;amp;min=1&amp;amp;max=100&amp;amp;col=1&amp;amp;base=10&amp;amp;format=plain&amp;amp;rnd=new&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;method&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;GET&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;headers&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Content-Type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 2) Set variable for base price
&lt;/span&gt;    &lt;span class="n"&gt;set_base_price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SetVariableTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task_ref_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;set_base_price&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;set_base_price&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;input_parameters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;base_price&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;${fetch_random_number.output.response.body}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="c1"&gt;# 3) Inline task to calculate final price
&lt;/span&gt;    &lt;span class="n"&gt;calculate_price_task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;InlineTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;task_ref_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;calculate_final_price&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;script&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'''&lt;/span&gt;&lt;span class="s"&gt;
            (function() {
                let basePrice = $.base_price;
                let loyaltyDiscount = $.loyalty_discount === &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gold&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; ? 0.2 : 0;
                let promotionDiscount = $.promotion_discount ? 0.1 : 0;
                return basePrice * (1 - loyaltyDiscount - promotionDiscount);
            })();
        &lt;/span&gt;&lt;span class="sh"&gt;'''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;bindings&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;base_price&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;${workflow.variables.base_price}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;loyalty_discount&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;${workflow.input.loyalty_status}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;promotion_discount&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;${workflow.input.is_promotion_active}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 4) Set final calculated price
&lt;/span&gt;    &lt;span class="n"&gt;set_price_variable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SetVariableTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task_ref_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;set_final_price_variable&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;set_price_variable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;input_parameters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;final_price&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;${calculate_final_price.output.result}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="c1"&gt;# Define the workflow with a 30-minute timeout
&lt;/span&gt;    &lt;span class="n"&gt;workflow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ConductorWorkflow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;checkout_workflow&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;workflow_executor&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;E-commerce checkout workflow with 30-min timeout&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timeout_seconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1800&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# 30 minutes
&lt;/span&gt;    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timeout_policy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TimeoutPolicy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TIME_OUT_WORKFLOW&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fetch_random_number_task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;set_base_price&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;calculate_price_task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;set_price_variable&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Register the workflow definition
&lt;/span&gt;    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;overwrite&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;workflow&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/conductor-oss/awesome-conductor-apps/blob/main/python/retries_timeouts_examples/ecommerce_workflow.py" rel="noopener noreferrer"&gt;Check out the full sample code for the E-commerce workflow.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If the workflow exceeds 30 minutes, it is marked as &lt;em&gt;TIMED_OUT&lt;/em&gt; automatically, allowing you to alert a team, start a cleanup flow, or retry.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flxvv016plj5vkk7ecqbj.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flxvv016plj5vkk7ecqbj.jpg" alt="E-commerce workflow" width="800" height="766"&gt;&lt;/a&gt;&lt;/p&gt;
E-commerce workflow with a 30-minute timeout



&lt;h2&gt;
  
  
  Failure workflows: Your fallback plan
&lt;/h2&gt;

&lt;p&gt;What happens when a workflow fails unexpectedly, due to a timeout, an API error, or an unhandled edge case? That’s where &lt;strong&gt;failure workflows&lt;/strong&gt; come in.&lt;/p&gt;

&lt;p&gt;These are separate workflows that are triggered when the main workflow fails. They allow you to &lt;strong&gt;compensate&lt;/strong&gt;, &lt;strong&gt;clean up&lt;/strong&gt;, and &lt;strong&gt;notify&lt;/strong&gt; downstream systems or users.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Failure workflow parameters&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Parameter&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;failureWorkflow&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The name of the fallback workflow to be triggered if this one fails. The default is empty.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Use case: Hotel booking with compensation flow
&lt;/h3&gt;

&lt;p&gt;Let’s say your travel booking app orchestrates a hotel reservation workflow. If the booking fails (maybe the payment went through, but the room wasn’t confirmed), you’d want to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Trigger a refund flow, and&lt;/li&gt;
&lt;li&gt;Notify the customer that the booking failed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Main workflow code&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;register_hotel_booking_workflow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;workflow_executor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;WorkflowExecutor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ConductorWorkflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# 1) HTTP task to reserve a hotel (simulated with dummy URL)
&lt;/span&gt;    &lt;span class="n"&gt;reserve_hotel_task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;HttpTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;task_ref_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reserve_hotel&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;http_input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;uri&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://httpbin.org/post&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;method&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;POST&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;headers&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Content-Type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;body&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hotel_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;${workflow.input.hotel_id}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;checkin&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;${workflow.input.checkin_date}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;checkout&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;${workflow.input.checkout_date}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;customer_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;${workflow.input.customer_id}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 2) Set variable to confirm reservation status (simulate from body)
&lt;/span&gt;    &lt;span class="n"&gt;set_status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SetVariableTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task_ref_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;set_reservation_status&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;set_status&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;input_parameters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;reservation_status&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;${reserve_hotel.output.response.body.json.status}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="c1"&gt;# 3) Inline task to check booking status
&lt;/span&gt;    &lt;span class="n"&gt;evaluate_reservation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;InlineTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;task_ref_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;check_booking_status&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;script&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'''&lt;/span&gt;&lt;span class="s"&gt;
            (function() {
                if ($.reservation_status !== &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;confirmed&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;) {
                    throw new Error(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Booking failed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;);
                }
                return &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;confirmed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;;
            })();
        &lt;/span&gt;&lt;span class="sh"&gt;'''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;bindings&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;reservation_status&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;${workflow.variables.reservation_status}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;workflow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ConductorWorkflow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;hotel_booking_workflow&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;workflow_executor&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hotel reservation flow with SLA and failure handling&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timeout_seconds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;900&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# 15 minutes
&lt;/span&gt;    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timeout_policy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;TimeoutPolicy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TIME_OUT_WORKFLOW&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;failure_workflow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hotel_booking_failure_handler&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reserve_hotel_task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;set_status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;evaluate_reservation&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;overwrite&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;workflow&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Failure workflow code&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;register_failure_workflow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;workflow_executor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;WorkflowExecutor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ConductorWorkflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# 1) Notify customer (simulated with dummy URL)
&lt;/span&gt;    &lt;span class="n"&gt;notify_customer_task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;HttpTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;task_ref_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;notify_customer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;http_input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;uri&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://httpbin.org/post&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;method&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;POST&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;headers&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Content-Type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;body&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;customer_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;${workflow.input.customer_id}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Your hotel booking could not be completed. We apologize for the inconvenience.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 2) Trigger refund (simulated with dummy URL)
&lt;/span&gt;    &lt;span class="n"&gt;refund_payment_task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;HttpTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;task_ref_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;trigger_refund&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;http_input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;uri&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://httpbin.org/post&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;method&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;POST&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;headers&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Content-Type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;body&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;payment_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;${workflow.input.payment_id}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reason&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hotel booking failed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;failure_workflow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ConductorWorkflow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hotel_booking_failure_handler&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;workflow_executor&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;failure_workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;failure_workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Handles failed hotel bookings with customer notification and refund&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="n"&gt;failure_workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;notify_customer_task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;failure_workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;refund_payment_task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;failure_workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;overwrite&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;failure_workflow&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/conductor-oss/awesome-conductor-apps/blob/main/python/retries_timeouts_examples/hotel_checkout_workflow.py" rel="noopener noreferrer"&gt;Check out the full sample code for the hotel booking workflow.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxqjp2es3qwmsxbr25nq3.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxqjp2es3qwmsxbr25nq3.jpg" alt="Hotel booking workflow" width="800" height="422"&gt;&lt;/a&gt;&lt;/p&gt;
Hotel booking workflow with a failure handler workflow



&lt;h2&gt;
  
  
  Best practices
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Always define &lt;code&gt;timeoutSeconds&lt;/code&gt; at both workflow and critical task levels to prevent resource overuse.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;failureWorkflow&lt;/code&gt; for any workflow that produces side effects or artifacts that need cleanup in the event of failure.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Wrap up
&lt;/h2&gt;

&lt;p&gt;Building production-ready workflows in Orkes Conductor means planning for both success and failure. Timeout policies and failure workflows aren’t just safeguards—they’re essential tools for maintaining system health, meeting SLAs, and ensuring a reliable user experience. When combined thoughtfully, they allow your workflows to self-regulate, recover from disruptions, and maintain a clean system state, even when things don’t go as planned.&lt;/p&gt;

&lt;p&gt;—&lt;/p&gt;

&lt;p&gt;&lt;a href="https://orkes.io/platform" rel="noopener noreferrer"&gt;Orkes Conductor&lt;/a&gt; is an enterprise-grade Unified Application Platform for process automation, API and microservices orchestration, agentic workflows, and more. Check out the &lt;a href="https://orkes.io/pricing" rel="noopener noreferrer"&gt;full set of features&lt;/a&gt;, or try it yourself using our free &lt;a href="https://developer.orkescloud.com/?utm_campaign=timeout-blog-3&amp;amp;utm_source=devto-blog&amp;amp;utm_medium=web" rel="noopener noreferrer"&gt;Developer Playground&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>timeout</category>
      <category>resilience</category>
      <category>retries</category>
      <category>python</category>
    </item>
    <item>
      <title>Task-Level Resilience in Orkes Conductor: Timeouts and Retries in Action</title>
      <dc:creator>Orkes Developers</dc:creator>
      <pubDate>Mon, 12 May 2025 08:52:28 +0000</pubDate>
      <link>https://dev.to/orkes/task-level-resilience-in-orkes-conductor-timeouts-and-retries-in-action-2fg5</link>
      <guid>https://dev.to/orkes/task-level-resilience-in-orkes-conductor-timeouts-and-retries-in-action-2fg5</guid>
      <description>&lt;p&gt;In distributed systems, individual task failure is not a matter of if, but when. APIs go down, services stall, and workers disappear. What matters is how your system responds. With Orkes Conductor, you don’t just handle these failures—you design for them.&lt;/p&gt;

&lt;p&gt;Conductor provides fine-grained control over how each task behaves under failure. With customizable &lt;strong&gt;timeouts&lt;/strong&gt; and &lt;strong&gt;retries&lt;/strong&gt;, you can recover from transient issues without human intervention, ensure critical steps don’t hang indefinitely, and build workflows that fail gracefully instead of catastrophically.&lt;/p&gt;

&lt;p&gt;In this blog, we’ll explore three core capabilities that enable resilient task execution in Orkes Conductor:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Task Retries&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Task Timeouts&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;System Task Timeouts&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Task retries: Recovering from flaky failures
&lt;/h2&gt;

&lt;p&gt;One of the most common failure scenarios is a transient error—momentary service unavailability, network hiccups, or throttling by an external API. Conductor lets you retry failed tasks automatically, using configurable backoff strategies to avoid overwhelming downstream services.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Retry parameters&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Parameter&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;retryCount&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The maximum number of retry attempts. Default is 3.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;retryLogic&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Retry strategy for the tasks. Supports:&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;FIXED&lt;/strong&gt;–Retries after a fixed interval defined by &lt;code&gt;retryDelaySeconds&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LINEAR_BACKOFF&lt;/strong&gt;–Retries occur with a delay that increases linearly based on &lt;code&gt;retryDelaySeconds x backoffScaleFactor x attempt_number&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;EXPONENTIAL_BACKOFF&lt;/strong&gt;–Retries occur with a delay that increases exponentially based on &lt;code&gt;retryDelaySeconds x (backoffScaleFactor ^ attempt_number&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;retryDelaySeconds&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The delay between retries. This combines with the backoff logic to calculate the actual wait time. &lt;br&gt; &lt;strong&gt;Note&lt;/strong&gt;: The actual duration depends on the retry policy set in &lt;code&gt;retryLogic&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;backoffScaleFactor&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Multiplier applied to &lt;code&gt;retryDelaySeconds&lt;/code&gt; to adjust how fast delays increase. Default is 1.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Use case: Flaky email provider
&lt;/h3&gt;

&lt;p&gt;Imagine your email provider fails intermittently. The first request sends a 500 error, but the second or third might succeed. This is a perfect scenario for retries.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;conductor.client.configuration.configuration&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Configuration&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;conductor.client.http.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TaskDef&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;conductor.client.orkes_clients&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OrkesClients&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;api_config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Configuration&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;clients&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OrkesClients&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;configuration&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;api_config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;metadata_client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;clients&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_metadata_client&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;task_def&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;TaskDef&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;task_def&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;send_email_task&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="n"&gt;task_def&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Send an email with retry on intermittent failures&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="n"&gt;task_def&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;retry_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
    &lt;span class="n"&gt;task_def&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;retry_logic&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;EXPONENTIAL_BACKOFF&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="n"&gt;task_def&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;retry_delay_seconds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
    &lt;span class="n"&gt;task_def&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;backoff_scale_factor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;

    &lt;span class="n"&gt;metadata_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register_task_def&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task_def&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;task_def&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Registered the task -- view at &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;api_config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ui_host&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/taskDef/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;task_def&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/conductor-oss/awesome-conductor-apps/blob/main/python/retries_timeouts_examples/send_email_task.py" rel="noopener noreferrer"&gt;Check out the full sample code for the send email task.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here, if the email task fails, it will automatically retry up to 3 times with increasing delays—2s, 4s, and 8s—allowing time for the service to recover between attempts.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs0x5ggduzldg24kn0ct1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs0x5ggduzldg24kn0ct1.jpg" alt="Email validation workflow" width="800" height="1124"&gt;&lt;/a&gt;&lt;/p&gt;
Email validation workflow using a Send Email task with exponential-backoff retries



&lt;h2&gt;
  
  
  Task timeouts: Preventing workflow stalls
&lt;/h2&gt;

&lt;p&gt;Retries help you recover, but timeouts prevent you from getting stuck in the first place. Whether a worker goes offline or an external service hangs, task-level timeouts ensure your workflow doesn’t wait forever.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Timeout parameters&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Parameter&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pollTimeoutSeconds&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The time to wait for a worker to poll this task before marking it as &lt;em&gt;TIMED_OUT&lt;/em&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;responseTimeoutSeconds&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The time to wait for a worker to send a status update (like &lt;em&gt;IN_PROGRESS&lt;/em&gt;) after polling.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;timeoutSeconds&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Total time allowed for the task to reach a terminal state.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;timeoutPolicy&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Action to take when a timeout occurs:&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;RETRY&lt;/strong&gt;–Retries the task using retry settings.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TIME_OUT_WF&lt;/strong&gt;–Marks the whole workflow as &lt;em&gt;TIMED_OUT&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ALERT_ONLY&lt;/strong&gt;–Logs an alert but lets the task continue.&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Use case: Slow inventory API
&lt;/h3&gt;

&lt;p&gt;Say you're calling a third-party inventory API that sometimes takes too long to respond. You don't want to wait forever, but you also don’t want to fail immediately. Here's how you'd configure a balanced timeout with retries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;conductor.client.configuration.configuration&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Configuration&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;conductor.client.http.models&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TaskDef&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;conductor.client.orkes_clients&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OrkesClients&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;api_config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Configuration&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;clients&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OrkesClients&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;configuration&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;api_config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;metadata_client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;clients&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_metadata_client&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;task_def&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;TaskDef&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;task_def&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;inventory_check_task&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="n"&gt;task_def&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Check inventory status with timeout and retry settings&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;

    &lt;span class="c1"&gt;# Retry settings
&lt;/span&gt;    &lt;span class="n"&gt;task_def&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;retry_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
    &lt;span class="n"&gt;task_def&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;retry_logic&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;FIXED&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
    &lt;span class="n"&gt;task_def&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;retry_delay_seconds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;

    &lt;span class="c1"&gt;# Timeout settings
&lt;/span&gt;    &lt;span class="n"&gt;task_def&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timeout_seconds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;
    &lt;span class="n"&gt;task_def&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;poll_timeout_seconds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
    &lt;span class="n"&gt;task_def&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;response_timeout_seconds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;
    &lt;span class="n"&gt;task_def&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timeout_policy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;RETRY&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;

    &lt;span class="n"&gt;metadata_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register_task_def&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task_def&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;task_def&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Registered the task -- view at &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;api_config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ui_host&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/taskDef/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;task_def&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/conductor-oss/awesome-conductor-apps/blob/main/python/retries_timeouts_examples/inventory_check_task.py" rel="noopener noreferrer"&gt;Check out the full sample code for the check inventory task.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This setup gives your worker 30 seconds to complete the task. If it doesn’t respond or fails, Conductor will retry it twice, waiting 5 seconds between each attempt.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9zz5egfa2kjg6i3zfc13.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9zz5egfa2kjg6i3zfc13.jpg" alt="Inventory workflow" width="800" height="1992"&gt;&lt;/a&gt;&lt;/p&gt;
Inventory workflow with a Check Inventory task with a 30-second timeout



&lt;p&gt;Together, these retry and timeout configurations help you build workflows that are not just reactive, but &lt;strong&gt;resilient by design&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Next, we’ll look at how the same principles apply at the &lt;strong&gt;workflow level&lt;/strong&gt;, giving you end-to-end control over your system’s behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  System task resilience
&lt;/h2&gt;

&lt;p&gt;A key part of building resilient workflows is defining how long system tasks should wait on external services or heavy computations. In Orkes Conductor, each system task has default or configurable timeout settings to control this behavior.&lt;/p&gt;

&lt;h3&gt;
  
  
  HTTP task resilience
&lt;/h3&gt;

&lt;p&gt;In Orkes Conductor, HTTP timeouts are defined by two parameters:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Parameter&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Default Values&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;connectionTimeout&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The maximum time (in milliseconds) to establish a TCP connection to the remote server.&lt;/td&gt;
&lt;td&gt;30 sec&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;readTimeout&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The maximum time (in milliseconds) to wait for a response after the connection is established and the request is sent.&lt;/td&gt;
&lt;td&gt;60 sec&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In Orkes Conductor, these defaults are enforced to ensure platform stability. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fosx0oq1416d12yddng6m.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fosx0oq1416d12yddng6m.jpg" alt="HTTP timeouts" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;
Orkes Conductor making an HTTP request to an external server, illustrating timeout applications.



&lt;h3&gt;
  
  
  Internal timeouts resilience
&lt;/h3&gt;

&lt;p&gt;Some system tasks have implicit timeout behaviors based on internal implementation. If you're designing workflows around system tasks, it's critical to understand and respect these limits.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;System Task&lt;/th&gt;
&lt;th&gt;Connection Timeout&lt;/th&gt;
&lt;th&gt;Read Timeout&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;HTTP&lt;/td&gt;
&lt;td&gt;30 sec&lt;/td&gt;
&lt;td&gt;60 sec&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LLM&lt;/td&gt;
&lt;td&gt;60 sec&lt;/td&gt;
&lt;td&gt;60 sec&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Opsgenie&lt;/td&gt;
&lt;td&gt;30 sec&lt;/td&gt;
&lt;td&gt;60 sec&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Inline&lt;/td&gt;
&lt;td&gt;n/a&lt;/td&gt;
&lt;td&gt;4 sec (max execution time)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Business Rule&lt;/td&gt;
&lt;td&gt;10 sec&lt;/td&gt;
&lt;td&gt;120 sec&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Wrap up
&lt;/h2&gt;

&lt;p&gt;Task failures are unavoidable, but with proper retry and timeout configurations, they don’t have to break your workflows. Conductor’s task-level resilience features help you avoid cascading failures, handle transient issues gracefully, and prevent workflows from hanging indefinitely.&lt;/p&gt;

&lt;p&gt;In the next article, we’ll scale this approach up and explore workflow-level failure handling strategies like &lt;strong&gt;timeout policies&lt;/strong&gt; and &lt;strong&gt;compensation flows&lt;/strong&gt; that give you end-to-end resilience.&lt;/p&gt;

&lt;p&gt;Next up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/orkes/workflow-level-resilience-in-orkes-conductor-timeouts-and-failure-workflows-1nc5"&gt;Workflow-Level Resilience&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;—&lt;/p&gt;

&lt;p&gt;&lt;a href="https://orkes.io/platform" rel="noopener noreferrer"&gt;Orkes Conductor&lt;/a&gt; is an enterprise-grade Unified Application Platform for process automation, API and microservices orchestration, agentic workflows, and more. Check out the &lt;a href="https://orkes.io/pricing" rel="noopener noreferrer"&gt;full set of features&lt;/a&gt;, or try it yourself using our free &lt;a href="https://developer.orkescloud.com/?utm_campaign=timeout-blog-2&amp;amp;utm_source=devto-blog&amp;amp;utm_medium=web" rel="noopener noreferrer"&gt;Developer Playground&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>python</category>
      <category>timeout</category>
      <category>retries</category>
      <category>resilience</category>
    </item>
    <item>
      <title>Fail Fast, Recover Smart: Timeouts, Retries, and Recovery in Orkes Conductor</title>
      <dc:creator>Orkes Developers</dc:creator>
      <pubDate>Mon, 12 May 2025 08:31:39 +0000</pubDate>
      <link>https://dev.to/orkes/fail-fast-recover-smart-timeouts-retries-and-recovery-in-orkes-conductor-1632</link>
      <guid>https://dev.to/orkes/fail-fast-recover-smart-timeouts-retries-and-recovery-in-orkes-conductor-1632</guid>
      <description>&lt;p&gt;In distributed systems, failure isn’t a possibility—it’s a certainty. APIs hang, workers crash, and networks drop. What matters isn’t avoiding failure, but recovering from it quickly and cleanly.&lt;/p&gt;

&lt;p&gt;Orkes Conductor gives you the tools to do exactly that. Timeouts and retries aren’t just configurable—they’re core to how Conductor ensures reliability at scale. In this post, you’ll learn how to use them effectively at both the &lt;strong&gt;task&lt;/strong&gt; and &lt;strong&gt;workflow&lt;/strong&gt; levels, how they interact with &lt;strong&gt;failure workflows&lt;/strong&gt;, and how to design resilient systems that heal themselves without manual intervention.&lt;/p&gt;

&lt;p&gt;Let’s dive in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why failure handling is critical in workflow applications
&lt;/h2&gt;

&lt;p&gt;Imagine you're orchestrating a payment flow. After the user places an order, your workflow triggers tasks to charge the card, update inventory, and send a confirmation email.&lt;/p&gt;

&lt;p&gt;All good—until the inventory API goes silent.&lt;/p&gt;

&lt;p&gt;Now you're in a mess: the card is charged, but inventory isn’t updated, and the user doesn’t get a confirmation. This is &lt;em&gt;exactly&lt;/em&gt; the kind of situation &lt;strong&gt;timeouts and retries&lt;/strong&gt; are designed to avoid.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdfvpjdh63vl0v8sr8y4a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdfvpjdh63vl0v8sr8y4a.png" alt="IUnresponsive HTTP task in an inventory workflow" width="800" height="1083"&gt;&lt;/a&gt;&lt;/p&gt;
Unresponsive HTTP task in an inventory workflow



&lt;p&gt;In Orkes Conductor, &lt;strong&gt;timeouts and retries work together&lt;/strong&gt; to provide resilience and control:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Timeouts&lt;/strong&gt; prevent your workflow from hanging indefinitely.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Retries&lt;/strong&gt; recover from transient errors without manual intervention.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Together, they help you gracefully handle:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Unresponsive services&lt;/strong&gt;: If a downstream API is taking too long, timeout the task and retry or move on.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Crashed or unresponsive workers&lt;/strong&gt;: If a worker crashes mid-task, timeouts ensure the task doesn’t hang forever.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transient errors&lt;/strong&gt;: If a task fails quickly (like a network blip or 500 error), retries can automatically reattempt the operation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Misconfigured or under-provisioned systems&lt;/strong&gt;: If no worker is available to pick up a task, timeouts ensure the system doesn’t just wait forever.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is more than resilience—it’s &lt;em&gt;control&lt;/em&gt;. Instead of writing custom error-handling logic for every edge case, you get:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;At-least-once delivery&lt;/li&gt;
&lt;li&gt;Automatic retry logic&lt;/li&gt;
&lt;li&gt;Configurable timeouts&lt;/li&gt;
&lt;li&gt;Self-healing workflows&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Task timeouts vs task retries
&lt;/h2&gt;

&lt;p&gt;As you design resilient workflows, it’s important to understand the difference between &lt;strong&gt;timeouts&lt;/strong&gt; and &lt;strong&gt;retries&lt;/strong&gt; for individual tasks—they solve different problems:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;Retry&lt;/th&gt;
&lt;th&gt;Timeout&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;What it is&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A second (or third, etc.) attempt to run the &lt;em&gt;same task&lt;/em&gt; after it fails.&lt;/td&gt;
&lt;td&gt;A &lt;em&gt;time limit&lt;/em&gt; for how long a task is allowed to run (or how long you wait for it to start/progress).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Trigger&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Happens after a task &lt;strong&gt;fails&lt;/strong&gt; (e.g., returns &lt;em&gt;FAILED&lt;/em&gt;).&lt;/td&gt;
&lt;td&gt;Happens if the task &lt;strong&gt;takes too long&lt;/strong&gt; to respond to or complete.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Example&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;API call fails with 500 Internal Server Error → Retry it after a delay.&lt;/td&gt;
&lt;td&gt;API call hangs with no response after 30 seconds → Timeout triggers a recovery action.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Configured via&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;retryCount&lt;/code&gt;, &lt;code&gt;retryLogic&lt;/code&gt;, &lt;code&gt;retryDelaySeconds&lt;/code&gt;, &lt;code&gt;backoffScaleFactor&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;timeoutSeconds&lt;/code&gt;, &lt;code&gt;pollTimeoutSeconds&lt;/code&gt;, &lt;code&gt;responseTimeoutSeconds&lt;/code&gt;, &lt;code&gt;timeoutPolicy&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In short:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Retries&lt;/strong&gt; deal with tasks that fail fast.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Timeouts&lt;/strong&gt; deal with tasks that hang slow.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both are essential for robust, fault-tolerant tasks.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feohanknnnmgbp3vk9zut.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feohanknnnmgbp3vk9zut.jpg" alt="Task timeouts vs task retries" width="800" height="680"&gt;&lt;/a&gt;&lt;/p&gt;
Failed worker resulting in task-timeout and retries



&lt;h2&gt;
  
  
  Workflow timeouts and failure workflows
&lt;/h2&gt;

&lt;p&gt;Just like tasks, entire workflows can time out or fail, and Conductor gives you powerful tools to handle those cases gracefully.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;Workflow Timeout&lt;/th&gt;
&lt;th&gt;Failure Workflow&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;What it is&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A maximum time limit for the whole workflow to complete.&lt;/td&gt;
&lt;td&gt;A backup workflow that runs automatically when the original workflow fails.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Trigger&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Happens when the workflow exceeds its configured timeout.&lt;/td&gt;
&lt;td&gt;Happens when the workflow ends in &lt;em&gt;FAILED&lt;/em&gt; or &lt;em&gt;TERMINATED&lt;/em&gt; status.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Example&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A data pipeline takes too long (e.g., &amp;gt; 2 hours) → Workflow is marked &lt;em&gt;TIMED_OUT&lt;/em&gt;.&lt;/td&gt;
&lt;td&gt;A workflow fails due to repeated task failures → A failure workflow sends alerts and logs diagnostics.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Configured via&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;timeoutSeconds&lt;/code&gt;, &lt;code&gt;timeoutPolicy&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;failureWorkflow&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In short:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Workflow timeouts&lt;/strong&gt; protect against indefinitely running flows.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Failure workflows&lt;/strong&gt; let you define recovery logic and postmortems for failed flows.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Together, they make workflows self-aware and recoverable.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faa9kza0zkywg35vv8dnv.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faa9kza0zkywg35vv8dnv.jpg" alt="Workflow timeouts and failure workflows" width="800" height="866"&gt;&lt;/a&gt;&lt;/p&gt;
Long-running worker exceeds workflow timeout and triggers compensation workflow



&lt;h2&gt;
  
  
  Combining retries, timeouts, and failure Workflows
&lt;/h2&gt;

&lt;p&gt;Retries give tasks more chances. Timeouts limit how long each attempt can run. Workflow timeouts cap the total duration of the workflow. If all else fails, failure workflows take over.&lt;/p&gt;

&lt;p&gt;Here’s how it all fits together:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Task fails&lt;/strong&gt; → &lt;em&gt;Task Retry&lt;/em&gt;: it’s retried (up to &lt;code&gt;retryCount&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Each retry has a timeout&lt;/strong&gt; → &lt;em&gt;Task Timeout&lt;/em&gt;: Limits how long you wait per attempt.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Too many failures or long delay&lt;/strong&gt; → &lt;em&gt;Workflow Timeout&lt;/em&gt;: Workflow fails or times out.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Workflow fails&lt;/strong&gt; → &lt;em&gt;Failure Workflow&lt;/em&gt;: A failure workflow runs to clean up or alert.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This layered approach gives you fault-tolerance at every level:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh7yy3n6h6mwjdw4kpzpl.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh7yy3n6h6mwjdw4kpzpl.jpg" alt="Resilience pyramid" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Default vs custom configuration: When to override
&lt;/h2&gt;

&lt;p&gt;Orkes Conductor ships with sane defaults.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Task retry settings&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"retryCount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"retryDelaySeconds"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"retryLogic"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"FIXED"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"backoffScaleFactor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Task timeout settings&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"responseTimeoutSeconds"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"timeoutSeconds"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"pollTimeoutSeconds"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"timeoutPolicy"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"TIME_OUT_WF"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Workflow settings&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"timeoutSeconds"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"timeoutPolicy"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ALERT_ONLY"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"failureWorkflow"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These are a solid starting point, but not always ideal for your SLAs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Override the defaults when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You have &lt;strong&gt;strict latency goals&lt;/strong&gt;, such as completing checkout in under 5 minutes.&lt;/li&gt;
&lt;li&gt;You interact with &lt;strong&gt;unreliable third-party APIs&lt;/strong&gt;, like a flaky partner API.&lt;/li&gt;
&lt;li&gt;You need &lt;strong&gt;predictable system behavior&lt;/strong&gt; under load or failure.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On the flip side, &lt;strong&gt;don’t override just for the sake of it&lt;/strong&gt;. Defaults help reduce configuration sprawl and are good enough for many internal service workflows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap up
&lt;/h2&gt;

&lt;p&gt;In distributed systems, failure is inevitable, but downtime doesn’t have to be. With Orkes Conductor, resilience is built in, not bolted on.&lt;/p&gt;

&lt;p&gt;Timeouts help prevent indefinite hangs, and retries offer automatic recovery from transient issues. Workflow-level timeouts and failure workflows ensure your entire system can fail gracefully and bounce back, without manual intervention.&lt;/p&gt;

&lt;p&gt;By combining these tools thoughtfully, you get more than reliability—you get confidence—confidence that your workflows will keep running, even when parts of your system don’t.&lt;/p&gt;

&lt;p&gt;So, whether you're orchestrating high-stakes payment flows or background data pipelines, remember: design for failure, recover automatically, and keep moving forward.&lt;/p&gt;

&lt;p&gt;Go more in-depth with task and workflow resilience with these follow-up articles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/orkes/task-level-resilience-in-orkes-conductor-timeouts-and-retries-in-action-2fg5"&gt;Task-Level Resilience&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/orkes/workflow-level-resilience-in-orkes-conductor-timeouts-and-failure-workflows-1nc5"&gt;Workflow-Level Resilience&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;—&lt;/p&gt;

&lt;p&gt;&lt;a href="https://orkes.io/platform" rel="noopener noreferrer"&gt;Orkes Conductor&lt;/a&gt; is an enterprise-grade Unified Application Platform for process automation, API and microservices orchestration, agentic workflows, and more. Check out the &lt;a href="https://orkes.io/pricing" rel="noopener noreferrer"&gt;full set of features&lt;/a&gt;, or try it yourself using our free &lt;a href="https://developer.orkescloud.com/?utm_campaign=timeout-blog-1&amp;amp;utm_source=devto-blog&amp;amp;utm_medium=web" rel="noopener noreferrer"&gt;Developer Playground&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>timeout</category>
      <category>retries</category>
      <category>recovery</category>
      <category>python</category>
    </item>
    <item>
      <title>Orkes Operators: Parallelism and Reusability</title>
      <dc:creator>Orkes Developers</dc:creator>
      <pubDate>Mon, 28 Apr 2025 12:57:39 +0000</pubDate>
      <link>https://dev.to/orkes/orkes-operators-parallelism-and-reusability-4g32</link>
      <guid>https://dev.to/orkes/orkes-operators-parallelism-and-reusability-4g32</guid>
      <description>&lt;p&gt;Workflows don’t just move forward—they branch, scale, and reuse logic. Whether you’re processing tasks in parallel, delegating work to subflows, or triggering asynchronous side-jobs, these patterns let you build smarter, more modular orchestration.&lt;/p&gt;

&lt;p&gt;In this post, we’ll explore operators that boost concurrency and composability in Orkes Conductor:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Fork/Join&lt;/strong&gt; for running multiple branches in parallel&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic Fork&lt;/strong&gt; for scalable, input-driven concurrency&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sub Workflow&lt;/strong&gt; for reusing logic across workflows&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Start Workflow&lt;/strong&gt; for async, fire-and-forget execution&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;From concurrent notifications to reusable payment flows, these operators help you scale orchestration cleanly—without duplicating logic or overcomplicating control flow. Let’s dive in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fork/Join
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Fork/Join&lt;/strong&gt; task in Orkes Conductor enables parallel execution of multiple task branches within a workflow. When a &lt;strong&gt;Fork&lt;/strong&gt; task is reached, it splits the workflow into separate paths that run concurrently, allowing different sequences of tasks to execute in parallel. Once all branches are complete, a &lt;strong&gt;Join&lt;/strong&gt; task is used to synchronize them before continuing with the rest of the workflow. This pattern is ideal for optimizing performance and handling tasks that can be executed independently, such as running multiple validation checks or data fetch operations simultaneously.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example implementation
&lt;/h3&gt;

&lt;p&gt;A common use case for the &lt;strong&gt;Fork/Join&lt;/strong&gt; task is in a multi-channel notification workflow. Suppose a Fork task dispatches three parallel notifications—email, SMS, and HTTP. Each branch sends its respective message independently to maximize concurrency. Since HTTP responses can be retried and don’t need to block the overall flow, the Join task is configured with &lt;code&gt;joinOn&lt;/code&gt; and is set to only the &lt;code&gt;email_notification&lt;/code&gt; and &lt;code&gt;sms_notification&lt;/code&gt; tasks. This allows the workflow to proceed as soon as the critical email and SMS tasks are complete, while the HTTP notification continues in the background. This setup enables partial synchronization—balancing reliability with improved efficiency.&lt;/p&gt;

&lt;p&gt;Here’s the workflow visualized:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ircot8629gz03wspfk5.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ircot8629gz03wspfk5.jpg" alt="Workflow using a Fork/Join operator" width="800" height="406"&gt;&lt;/a&gt;&lt;/p&gt;
Workflow using a Fork/Join operator



&lt;p&gt;Here’s the code snippet for creating the workflow in code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
def register_notification_workflow(workflow_executor: WorkflowExecutor) -&amp;gt; ConductorWorkflow:
    # 1) Define each notification path
    email_branch = [
        SimpleTask(
            task_def_name="process_notification_payload",
            task_reference_name="process_notification_payload_email"
        ),
        SimpleTask(
            task_def_name="email_notification",
            task_reference_name="email_notification_ref"
        )
    ]

    sms_branch = [
        SimpleTask(
            task_def_name="process_notification_payload",
            task_reference_name="process_notification_payload_sms"
        ),
        SimpleTask(
            task_def_name="sms_notification",
            task_reference_name="sms_notification_ref"
        )
    ]

    http_branch = [
        SimpleTask(
            task_def_name="process_notification_payload",
            task_reference_name="process_notification_payload_http"
        ),
        HttpTask(
            task_ref_name="http_notification_ref",
            http_input={
                "uri": "${workflow.input.http_target_url}",
                "method": "POST",
                "headers": {
                    "Content-Type": "application/json"
                },
                "body": {
                    "message": "Notification triggered"
                }
            }
        )
    ]

    # 2) Fork-Join setup (only join on email + sms)
    fork_join = ForkTask(
        task_ref_name="my_fork_join_ref",
        forked_tasks=[email_branch, sms_branch, http_branch],
        join_on=["email_notification_ref", "sms_notification_ref"]
    )

    workflow = ConductorWorkflow(
        name="notification_workflow_with_fork_join",
        executor=workflow_executor
    )
    workflow.version = 1
    workflow.add(fork_join)
    workflow.register(overwrite=True)

    return workflow


@worker_task(task_definition_name="process_notification_payload")
def process_notification_payload() -&amp;gt; dict:
    print("🛠️ Processing notification payload...")
    return {"payload_processed": True}


@worker_task(task_definition_name="email_notification")
def email_notification() -&amp;gt; dict:
    print("📧 Email sent to test@example.com")
    return {
        "email_sent_at": "2021-11-06T07:37:17+0000",
        "email_sent_to": "test@example.com"
    }


@worker_task(task_definition_name="sms_notification")
def sms_notification() -&amp;gt; dict:
    print("📱 SMS sent to +1-xxx-xxx-xxxx")
    return {
        "sms_sent_at": "2021-11-06T07:37:17+0129",
        "sms_sent_to": "+1-xxx-xxx-xxxx"
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/conductor-oss/awesome-conductor-apps/blob/main/python/operator_examples/forkjoin-workflow.py" rel="noopener noreferrer"&gt;Check out the full sample code for the Fork/Join Workflow.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Dynamic Fork
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Dynamic Fork&lt;/strong&gt; task allows you to create and execute multiple parallel task branches based on dynamic input at runtime. Unlike a standard fork, which defines branches statically, Dynamic Forks generates parallel tasks on the fly using input parameters. This is particularly useful when the number of tasks isn’t known ahead of time—such as sending notifications to a dynamic list of users or processing a batch of files. Each dynamically generated task runs independently, and a corresponding &lt;strong&gt;Join&lt;/strong&gt; task is used to synchronize them once all have been completed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example implementation
&lt;/h3&gt;

&lt;p&gt;Imagine a content moderation workflow that needs to process different types of user-generated content—text, images, and videos. Each content type requires a different moderation approach, like scanning text for profanity, running image recognition for flagged visuals, or transcribing and analyzing video audio. Since the type and number of content items vary per request, a &lt;strong&gt;Dynamic Fork&lt;/strong&gt; is ideal. At runtime, it dynamically generates tasks like &lt;code&gt;moderate_text&lt;/code&gt;, &lt;code&gt;moderate_image&lt;/code&gt;, and &lt;code&gt;moderate_video&lt;/code&gt;, each configured with input specific to the content item. Once all moderation tasks are complete, a Join task consolidates the results for final review. This setup ensures flexibility and scalability for diverse, real-time moderation needs.&lt;/p&gt;

&lt;p&gt;Here’s the workflow visualized:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fovduc0c4r9yt11hkv30d.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fovduc0c4r9yt11hkv30d.jpg" alt="Workflow using a Dynamic Fork operator." width="800" height="572"&gt;&lt;/a&gt;&lt;/p&gt;
Workflow using a Dynamic Fork operator



&lt;p&gt;Here’s the code snippet for creating the workflow in code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
def register_moderation_workflow(workflow_executor: WorkflowExecutor) -&amp;gt; ConductorWorkflow:
    # 1) Define Join task
    join_task = JoinTask(
        task_ref_name="join_ref",
        join_on=[]
    )

    # 2) Define Dynamic Fork Task with inputParameters dict
    dynamic_fork = DynamicForkTask(
        task_ref_name="fork_join_dynamic_ref",
        join_task=join_task
    )
    dynamic_fork.input_parameters.update({
        "dynamicTasks": "${workflow.input.dynamicTasks}",
        "dynamicTasksInputs": "${workflow.input.dynamicTasksInputs}"
    })

    workflow = ConductorWorkflow(
        name="DynamicForkExample",
        executor=workflow_executor
    )
    workflow.version = 1
    workflow.add(dynamic_fork)
    workflow.register(overwrite=True)

    return workflow


@worker_task(task_definition_name="moderate_text")
def moderate_text() -&amp;gt; dict:
    print("📝 Moderating text...")
    return {"status": "Text moderation complete"}


@worker_task(task_definition_name="moderate_image")
def moderate_image() -&amp;gt; dict:
    print("🖼️ Moderating image...")
    return {"status": "Image moderation complete"}


@worker_task(task_definition_name="moderate_video")
def moderate_video() -&amp;gt; dict:
    print("🎥 Moderating video...")
    return {"status": "Video moderation complete"}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/conductor-oss/awesome-conductor-apps/blob/main/python/operator_examples/dynamicfork-workflow.py" rel="noopener noreferrer"&gt;Check out the full sample code for the Dynamic Fork Workflow.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Sub Workflow
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Sub Workflow&lt;/strong&gt; task in Orkes Conductor allows you to encapsulate and execute another workflow synchronously within the context of a parent workflow. This task enables modularity and reusability, letting you delegate specific parts of a workflow to be handled by a separate workflow definition. The sub-workflow can run independently and return results to the parent workflow, helping to simplify complex workflows and manage different logic in isolation. It also provides better scalability and maintainability by breaking down large workflows into smaller, reusable components.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example implementation
&lt;/h3&gt;

&lt;p&gt;In a subscription management workflow, the &lt;strong&gt;Sub Workflow&lt;/strong&gt; task is used to modularize payment processing. Instead of duplicating the entire payment logic within the subscription workflow, the &lt;code&gt;payment_for_subscription&lt;/code&gt; workflow is called as a sub-workflow whenever payment needs to be processed. This ensures that any updates made to the payment workflow are automatically reflected across all parent workflows, improving maintainability and consistency. The parent workflow can invoke the sub-workflow multiple times, allowing for seamless integration of payment logic into the larger subscription process.&lt;/p&gt;

&lt;p&gt;Here’s the workflow visualized:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fguajrzmrk1jjk7mtmwn6.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fguajrzmrk1jjk7mtmwn6.jpg" alt="Workflow using a Sub Workflow operator." width="800" height="623"&gt;&lt;/a&gt;&lt;/p&gt;
Workflow using a Sub Workflow operator



&lt;p&gt;Here’s the code snippet for creating the workflow in code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
# --- Payment Workflow (Sub-Workflow for Subscription) ---

def register_payment_workflow(workflow_executor: WorkflowExecutor) -&amp;gt; ConductorWorkflow:
    # 1) Process payment (for subscription)
    process_payment = SimpleTask(
        task_def_name="process_payment",
        task_reference_name="process_payment"
    )
    process_payment.input_parameters.update({
        "amount": "${workflow.input.amount}"
    })

    workflow = ConductorWorkflow(
        name="payment_for_subscription",
        executor=workflow_executor
    )
    workflow.version = 1
    workflow.add(process_payment)
    workflow.register(overwrite=True)

    return workflow


# --- Subscription Workflow Definition (using Sub-Workflow) ---

def register_subscription_workflow(workflow_executor: WorkflowExecutor) -&amp;gt; ConductorWorkflow:
    # 1) Check if the user is subscribed
    check_status = SimpleTask(
        task_def_name="check_subscription_status",
        task_reference_name="check_subscription_status"
    )

    # 2) Trigger payment using sub-workflow
    trigger_payment = SubWorkflowTask(
        task_ref_name="trigger_payment",
        workflow_name="payment_for_subscription",  # The sub-workflow to invoke
        version=1
    )
    trigger_payment.input_parameters.update({
        "amount": "${workflow.input.amount}",  # Mapping input to sub-workflow
        "subscription_id": "${workflow.input.subscription_id}",
        "user_id": "${workflow.input.user_id}"
    })

    # 3) Send welcome email
    send_email = SimpleTask(
        task_def_name="send_welcome_email",
        task_reference_name="send_welcome_email"
    )

    workflow = ConductorWorkflow(
        name="subscription_management",
        executor=workflow_executor
    )
    workflow.version = 1
    workflow.add(check_status)
    workflow.add(trigger_payment)
    workflow.add(send_email)
    workflow.register(overwrite=True)

    return workflow


@worker_task(task_definition_name="check_subscription_status")
def check_subscription_status() -&amp;gt; dict:
    print("📡 Checking subscription status...")
    return {"status": "active"}


@worker_task(task_definition_name="send_welcome_email")
def send_welcome_email() -&amp;gt; dict:
    print("📨 Sending welcome email to subscriber...")
    return {"status": "email_sent"}


@worker_task(task_definition_name="process_payment")
def process_payment(amount) -&amp;gt; dict:
    print(f"💰 Charging customer: ${amount.input_data['amount']}")
    return {"status": "Payment successful"}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/conductor-oss/awesome-conductor-apps/blob/main/python/operator_examples/subwork-workflow.py" rel="noopener noreferrer"&gt;Check out the full sample code for the Sub Workflow Workflow.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Start Workflow
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Start Workflow&lt;/strong&gt; task is an operator in Orkes Conductor that launches another workflow asynchronously from within the current one. Unlike the Sub Workflow task, which pauses the parent workflow until the child workflow completes, the Start Workflow task triggers the target workflow and immediately continues execution without waiting for its result. This is ideal for use cases like fire-and-forget processing, background jobs, or decoupled side operations where real-time feedback isn't needed, allowing for greater concurrency and throughput in orchestration.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example implementation
&lt;/h3&gt;

&lt;p&gt;A common use case for the Start Workflow task is submitting background jobs that don’t need to block the main workflow. For example, in an e-commerce checkout workflow, once the payment is processed, a &lt;strong&gt;Start Workflow&lt;/strong&gt; task can be used to asynchronously trigger an &lt;code&gt;email_receipt_workflow&lt;/code&gt; that sends a receipt to the customer. This ensures the checkout flow completes quickly without waiting for email processing, which can be handled independently.&lt;/p&gt;

&lt;p&gt;Here’s the workflow visualized:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fznw15lvyp7wzfavj5sxr.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fznw15lvyp7wzfavj5sxr.jpg" alt="Workflow using a Start Workflow operator." width="800" height="623"&gt;&lt;/a&gt;&lt;/p&gt;
Workflow using a Start Workflow operator



&lt;p&gt;Here’s the code snippet for creating the workflow in code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
# --- Email Receipt Workflow (Sub-Workflow for emails) ---

def register_email_receipt_workflow(executor: WorkflowExecutor) -&amp;gt; ConductorWorkflow:
    email_task = SimpleTask(
        task_def_name="send_receipt_email",
        task_reference_name="send_receipt_email_ref"
    )

    workflow = ConductorWorkflow(
        name="email_receipt_workflow",
        executor=executor
    )
    workflow.version = 1
    workflow.add(email_task)
    workflow.register(overwrite=True)
    return workflow


# --- Main Checkout Workflow Definition (using Sub-Workflow) ---

def register_checkout_workflow(executor: WorkflowExecutor) -&amp;gt; ConductorWorkflow:
    # 1) Task to process payment
    payment_task = SimpleTask(
        task_def_name="process_payment",
        task_reference_name="process_payment_ref"
    )

    # 2) Task to asynchronously start email_receipt_workflow
    start_email_workflow_input = StartWorkflowRequest(
        name="email_receipt_workflow",
        version=1,
        input={
            "customer_email": "${workflow.input.customer_email}",
            "order_id": "${workflow.input.order_id}"
        }
    )

    start_email_workflow_task = StartWorkflowTask(
        task_ref_name="start_email_workflow_ref",
        workflow_name="email_receipt_workflow",
        start_workflow_request=start_email_workflow_input,
        version=1
    )

    workflow = ConductorWorkflow(
        name="checkout_workflow",
        executor=executor
    )
    workflow.version = 1
    workflow.add(payment_task)
    workflow.add(start_email_workflow_task)
    workflow.register(overwrite=True)
    return workflow

@worker_task(task_definition_name="process_payment")
def process_payment() -&amp;gt; dict:
    print("💳 Payment processed successfully.")
    return {"payment_status": "success"}


@worker_task(task_definition_name="send_receipt_email")
def send_receipt_email() -&amp;gt; dict:
    print("📧 Receipt email sent to customer.")
    return {"email_status": "sent"}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/conductor-oss/awesome-conductor-apps/blob/main/python/operator_examples/start-workflow.py" rel="noopener noreferrer"&gt;Check out the full sample code for the Start Workflow Workflow.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap up
&lt;/h2&gt;

&lt;p&gt;Parallelism and reusability aren’t just performance optimizations—they’re architectural superpowers. With operators like Fork/Join, Dynamic Fork, Sub Workflow, and Start Workflow, Orkes Conductor makes it easy to run tasks concurrently, compose modular logic, and trigger workflows asynchronously.&lt;/p&gt;

&lt;p&gt;No threads to manage, no glue code to write—just clean, declarative orchestration that scales.&lt;/p&gt;

&lt;p&gt;—&lt;/p&gt;

&lt;p&gt;&lt;a href="https://orkes.io/platform?utm_campaign=operators-blog-4&amp;amp;utm_source=devto-blog&amp;amp;utm_medium=web" rel="noopener noreferrer"&gt;Orkes Conductor&lt;/a&gt; is an enterprise-grade Unified Application Platform for process automation, API and microservices orchestration, agentic workflows, and more. Check out the &lt;a href="https://orkes.io/pricing" rel="noopener noreferrer"&gt;full set of features&lt;/a&gt;, or try it yourself using our free &lt;a href="https://developer.orkescloud.com/?utm_campaign=operators-blog-4&amp;amp;utm_source=devto-blog&amp;amp;utm_medium=web" rel="noopener noreferrer"&gt;Developer Playground&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>beginners</category>
      <category>python</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>Orkes Operators: Loops, Waits, and Human-in-the-Loop</title>
      <dc:creator>Orkes Developers</dc:creator>
      <pubDate>Mon, 28 Apr 2025 12:44:18 +0000</pubDate>
      <link>https://dev.to/orkes/orkes-operators-loops-waits-and-human-in-the-loop-2ece</link>
      <guid>https://dev.to/orkes/orkes-operators-loops-waits-and-human-in-the-loop-2ece</guid>
      <description>&lt;p&gt;Not all workflows are linear. Some wait, some repeat, and some need a human to step in before moving forward.&lt;/p&gt;

&lt;p&gt;In this post, we explore three essential operators that add patience, persistence, and people to your workflows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Do While&lt;/strong&gt; for flexible, condition-based iteration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Wait&lt;/strong&gt; for clean, pause-and-resume control&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Human&lt;/strong&gt; for structured human input and approvals&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Whether you're looping through review stages, waiting for external input, or routing manual approvals across teams, these operators help you build dynamic, resilient, and human-aware workflows without writing custom orchestration logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Do While
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Do While&lt;/strong&gt; task is a loop operator that repeatedly executes a set of tasks as long as a specified condition remains true. Similar to a do-while loop in programming, it ensures the loop body runs at least once before evaluating the condition. This is useful for polling, retries, approval loops, or any scenario requiring repeated execution until a dynamic condition is met. The loop condition is evaluated after each iteration, and loop variables can be updated within the loop to control its execution.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example implementation
&lt;/h3&gt;

&lt;p&gt;This workflow handles a ticket that must go through multiple internal review stages: support agent, QA team, and team lead. Using a Do While Task, the workflow loops through these stages automatically, sending the ticket to each reviewer in sequence. The loop runs once for each reviewer using the &lt;code&gt;itemslist&lt;/code&gt; and exits cleanly once all reviews are complete.&lt;/p&gt;

&lt;p&gt;Here’s the workflow visualized:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0opbw23jkgdz6u259xo0.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0opbw23jkgdz6u259xo0.jpg" alt="Workflow using a Do While operator." width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;
Workflow using a Do While operator



&lt;p&gt;Here’s the code snippet for creating the workflow in code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
def register_workflow(workflow_executor: WorkflowExecutor) -&amp;gt; ConductorWorkflow:
    # 1) Task to simulate review step with HTTP POST
    review_task = HttpTask(
        task_ref_name="log_review_comment",
        http_input={
            "uri": "https://jsonplaceholder.typicode.com/posts",
            "method": "POST",
            "headers": {
                "Content-Type": "application/json"
            },
            "body": {
                "reviewer": "${review_ticket_loop.output.item}",
                "comment": "Reviewed and updated by ${review_ticket_loop.output.item}"
            }
        }
    )

    # 2) DoWhileTask to iterate over reviewer stages
    review_loop = DoWhileTask(
        task_ref_name="review_ticket_loop",
        termination_condition="$.review_ticket_loop.iteration &amp;lt; $.review_ticket_loop.input.items.length",
        tasks=[review_task]
    )
    review_loop.input_parameters.update({
        "items": ["support_agent", "qa_team", "team_lead"]
    })

    workflow = ConductorWorkflow(
        name="ticket_review_workflow",
        executor=workflow_executor
    )
    workflow.version = 1
    workflow.add(review_loop)
    workflow.register(overwrite=True)

    return workflow
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/conductor-oss/awesome-conductor-apps/blob/main/python/operator_examples/dowhile-workflow.py" rel="noopener noreferrer"&gt;Check out the full sample code for the Do While Workflow.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wait
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Wait&lt;/strong&gt; task is a control flow operator used to pause workflow execution until an external signal is received. It’s ideal for scenarios that require human input, external approvals, or asynchronous events from another system. When the workflow reaches a Wait task, it halts and remains paused until it's explicitly resumed using the Conductor API or UI. This makes it easy to build workflows that involve manual steps or depend on external triggers without resorting to constant polling or custom state management.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example implementation
&lt;/h3&gt;

&lt;p&gt;In an employee onboarding workflow, after provisioning accounts and sending welcome materials, the process may require the new hire to complete a digital form or provide verification documents. A Wait task can pause the workflow at this point until the user submits the required information. Once the input is received—via a webhook or manual trigger—the workflow resumes automatically, continuing with the next steps like assigning a manager or scheduling training.&lt;/p&gt;

&lt;p&gt;Here’s the workflow visualized:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3qzda0fudy8fbch0ke76.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3qzda0fudy8fbch0ke76.jpg" alt="Workflow using a Wait operator." width="800" height="698"&gt;&lt;/a&gt;&lt;/p&gt;
Workflow using a Wait operator



&lt;p&gt;Here’s the code snippet for creating the workflow in code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
def register_workflow(workflow_executor: WorkflowExecutor) -&amp;gt; ConductorWorkflow:
    # 1) Simulate account provisioning
    provision_account = HttpTask(
        task_ref_name="provision_account",
        http_input={
            "uri": "https://jsonplaceholder.typicode.com/users",
            "method": "POST",
            "headers": {
                "Content-Type": "application/json"
            },
            "body": {
                "employeeId": "${workflow.input.employeeId}",
                "email": "${workflow.input.email}"
            }
        }
    )

    # 2) Send welcome materials
    send_welcome = HttpTask(
        task_ref_name="send_welcome_materials",
        http_input={
            "uri": "https://jsonplaceholder.typicode.com/posts",
            "method": "POST",
            "headers": {
                "Content-Type": "application/json"
            },
            "body": {
                "employeeId": "${workflow.input.employeeId}",
                "message": "Welcome to the company!"
            }
        }
    )

    # 3) Wait for the new employee to submit verification (simulate with 10s wait)
    wait_for_input = WaitTask(
        task_ref_name="wait_for_employee_response",
        wait_for_seconds=10
    )

    # 4) Assign a manager
    assign_manager = SetVariableTask(task_ref_name="assign_manager")
    assign_manager.input_parameters.update({
        "manager": "alice.smith@company.com"
    })

    # 5) Schedule training
    schedule_training = SetVariableTask(task_ref_name="schedule_training")
    schedule_training.input_parameters.update({
        "training_date": "2025-04-20"
    })

    workflow = ConductorWorkflow(
        name="employee_onboarding_workflow",
        executor=workflow_executor
    )
    workflow.version = 1

    workflow.add(provision_account)
    workflow.add(send_welcome)
    workflow.add(wait_for_input)
    workflow.add(assign_manager)
    workflow.add(schedule_training)

    workflow.register(overwrite=True)
    return workflow
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/conductor-oss/awesome-conductor-apps/blob/main/python/operator_examples/wait-workflow.py" rel="noopener noreferrer"&gt;Check out the full sample code for the Wait Workflow.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Human
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Human&lt;/strong&gt; task in Orkes Conductor is used to pause a workflow and wait for manual input or approval from a human before continuing. It's ideal for workflows that involve human-in-the-loop decisions, such as document reviews, access approvals, or data verification. When a Human task is reached, the workflow enters a WAITING state until a user provides the required input through the API or UI. This enables seamless integration of manual steps into automated workflows while maintaining visibility and control over the process.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example implementation
&lt;/h3&gt;

&lt;p&gt;In this example, an expense approval workflow uses two Human tasks to gather approvals from different departments. First, the HR department is prompted with a form showing the expense details in read-only fields. If HR approves, the workflow continues to the Finance department for a second round of approval using the same form template. Upon Finance’s approval, a notification workflow is triggered. If either department rejects the request, the workflow terminates early. This use case shows how Human tasks enable structured, multi-step approvals with manual input inside an otherwise automated process.&lt;/p&gt;

&lt;p&gt;Here’s the workflow visualized:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5svslqtqcettiocmhm62.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5svslqtqcettiocmhm62.jpg" alt="Workflow using a Human operator." width="800" height="964"&gt;&lt;/a&gt;&lt;/p&gt;
Workflow using a Human operator



&lt;p&gt;To create this workflow in Conductor, you must first define the &lt;code&gt;expense_approval_form&lt;/code&gt; using the appropriate fields in the Orkes UI. Here’s the code snippet for creating the &lt;code&gt;expense_approval_form&lt;/code&gt; in JSON:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
{
  "createTime": 1744849075315,
  "updateTime": 1744849570917,
  "createdBy": "USER:john.doe@acme.com",
  "updatedBy": "USER:john.doe@acme.com",
  "name": "expense_approval_form",
  "version": 1,
  "jsonSchema": {
    "$schema": "http://json-schema.org/draft-07/schema",
    "properties": {
      "approvalStatus": {
        "type": "string",
        "enum": [
          "APPROVED",
          "REJECTED"
        ]
      }
    },
    "required": [
      "approvalStatus"
    ]
  },
  "templateUI": {
    "type": "VerticalLayout",
    "elements": [
      {
        "type": "Control",
        "scope": "#/properties/approvalStatus",
        "label": "Department Approval",
        "options": {}
      }
    ]
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here’s the code snippet for creating the workflow in code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
# --- Notification Workflow ---

def register_notification_workflow(executor: WorkflowExecutor) -&amp;gt; ConductorWorkflow:
    notify_task = SimpleTask(
        task_def_name="notify_expense_approval",
        task_reference_name="notify_expense_approval_ref"
    )

    workflow = ConductorWorkflow(
        name="notification_workflow",
        executor=executor
    )
    workflow.version = 1
    workflow.add(notify_task)
    workflow.register(overwrite=True)
    return workflow


# --- Expense Approval Workflow ---

def register_expense_approval_workflow(executor: WorkflowExecutor) -&amp;gt; ConductorWorkflow:
    # 1) HR Approval Step
    hr_approval = HumanTask(
        task_ref_name="hr_approval_task",
        display_name="HR Approval",
        form_template="expense_approval_form",
        form_version=1,
        assignment_completion_strategy=AssignmentCompletionStrategy.TERMINATE
    )

    check_hr = SwitchTask(
        task_ref_name="check_hr_approval",
        case_expression="${hr_approval_task.output.approvalStatus}"
    ).switch_case("APPROVED", [])

    # 2) Finance Approval Step
    finance_approval = HumanTask(
        task_ref_name="finance_approval_task",
        display_name="Finance Approval",
        form_template="expense_approval_form",
        form_version=1,
        assignment_completion_strategy=AssignmentCompletionStrategy.TERMINATE
    )

    check_finance = SwitchTask(
        task_ref_name="check_finance_approval",
        case_expression="${finance_approval_task.output.approvalStatus}"
    ).switch_case("APPROVED", [])

    # 3) Start Notification Workflow
    start_notification = StartWorkflowTask(
        task_ref_name="start_notification_workflow",
        workflow_name="notification_workflow",
        start_workflow_request=StartWorkflowRequest(
            name="notification_workflow",
            version=1,
            input={
                "expense_id": "${workflow.input.expense_id}",
                "submitted_by": "${workflow.input.submitted_by}"
            }
        ),
        version=1
    )

    # Add the notification task inside the finance approval success branch
    check_finance.switch_case("APPROVED", [start_notification])

    # Add finance approval after HR approves
    check_hr.switch_case("APPROVED", [finance_approval, check_finance])

    workflow = ConductorWorkflow(
        name="expense_approval_workflow",
        executor=executor
    )
    workflow.version = 1
    workflow.add(hr_approval)
    workflow.add(check_hr)
    workflow.register(overwrite=True)
    return workflow


# --- Worker for notification task ---

@worker_task(task_definition_name="notify_expense_approval")
def notify_expense_approval() -&amp;gt; dict:
    print("🔔 Expense approval notification sent.")
    return {"notified": True}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/conductor-oss/awesome-conductor-apps/blob/main/python/operator_examples/human-workflow.py" rel="noopener noreferrer"&gt;Check out the full sample code for the Human Workflow.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap up
&lt;/h2&gt;

&lt;p&gt;Loops, waits, and human steps bring real-world rhythm to your workflows, allowing them to persist, pause, or involve people when needed. With tasks like Do While, Wait, and Human, Conductor makes asynchronous logic declarative, structured, and resilient. No brittle timers, no custom coordination—just clean, event-driven flow.&lt;/p&gt;

&lt;p&gt;Next up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/orkes/orkes-operators-parallelism-and-reusability-4g32"&gt;Parallelism and Reusability&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://orkes.io/platform?utm_campaign=operators-blog-3&amp;amp;utm_source=devto-blog&amp;amp;utm_medium=web" rel="noopener noreferrer"&gt;Orkes Conductor&lt;/a&gt; is an enterprise-grade Unified Application Platform for process automation, API and microservices orchestration, agentic workflows, and more. Check out the &lt;a href="https://orkes.io/pricing" rel="noopener noreferrer"&gt;full set of features&lt;/a&gt;, or try it yourself using our free &lt;a href="https://developer.orkescloud.com/?utm_campaign=operators-blog-3&amp;amp;utm_source=devto-blog&amp;amp;utm_medium=web" rel="noopener noreferrer"&gt;Developer Playground&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>distributedsystems</category>
      <category>humanintheloop</category>
      <category>programming</category>
      <category>python</category>
    </item>
    <item>
      <title>Orkes Operators: Branching and Conditionals</title>
      <dc:creator>Orkes Developers</dc:creator>
      <pubDate>Mon, 28 Apr 2025 12:10:02 +0000</pubDate>
      <link>https://dev.to/orkes/orkes-operators-branching-and-conditionals-2pe4</link>
      <guid>https://dev.to/orkes/orkes-operators-branching-and-conditionals-2pe4</guid>
      <description>&lt;p&gt;Smart workflows don’t just follow a straight line—they make decisions.&lt;/p&gt;

&lt;p&gt;Orkes Conductor provides a set of declarative operators that let your workflows respond to input, handle conditions, and dynamically route execution without hardcoding logic into your services.&lt;/p&gt;

&lt;p&gt;In this article, we’ll walk through four core decision-making operators:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Switch&lt;/strong&gt; for branching logic based on runtime conditions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic&lt;/strong&gt; for generating tasks on the fly based on data&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Set Variable&lt;/strong&gt; for setting and updating internal state during execution&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Terminate&lt;/strong&gt; for gracefully ending workflows early when needed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With these operators, you can model flexible, maintainable decision paths that react to real-world complexity—all without writing imperative glue code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Switch
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Switch&lt;/strong&gt; task is a control flow operator that enables conditional branching within a workflow, similar to a switch-case or if-else statement in code. It evaluates an expression at runtime and routes execution to a matching case, with support for a default path if no match is found. This makes it ideal for directing workflow logic based on dynamic values such as user input, AI-powered decisions, or status flags.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example implementation
&lt;/h3&gt;

&lt;p&gt;Let’s say you're building an order processing workflow that needs to handle different shipping methods. Based on the &lt;code&gt;shippingType&lt;/code&gt; selected by the user (&lt;em&gt;standard, express, or overnight&lt;/em&gt;), the workflow should branch into a different fulfillment path. A Switch task can evaluate the &lt;code&gt;shippingType&lt;/code&gt; and route the workflow accordingly.&lt;/p&gt;

&lt;p&gt;Here’s the workflow visualized:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F27wep79m8ug0m9wqiu5w.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F27wep79m8ug0m9wqiu5w.jpg" alt="High-level diagram of the Switch workflow vs the actual workflow diagram in Conductor." width="800" height="500"&gt;&lt;/a&gt;Workflow using a Switch operator.&lt;/p&gt;

&lt;p&gt;Here’s the code snippet for creating the workflow in code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;register_workflow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;workflow_executor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;WorkflowExecutor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ConductorWorkflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# 1) Task to fetch order details
&lt;/span&gt;    &lt;span class="n"&gt;fetch_order_details&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;HttpTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;task_ref_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fetch_order_details&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;http_input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;uri&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://jsonplaceholder.typicode.com/posts/${workflow.input.orderId}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;method&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;GET&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;headers&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Content-Type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 2) SetVariable tasks for each shipping method
&lt;/span&gt;    &lt;span class="n"&gt;standard_shipping&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SetVariableTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task_ref_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;standard_shipping_var&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;standard_shipping&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;input_parameters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;selected_shipping_method&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;standard&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="n"&gt;express_shipping&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SetVariableTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task_ref_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;express_shipping_var&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;express_shipping&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;input_parameters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;selected_shipping_method&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;express&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="n"&gt;overnight_shipping&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SetVariableTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task_ref_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;overnight_shipping_var&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;overnight_shipping&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;input_parameters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;selected_shipping_method&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;overnight&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="c1"&gt;# 3) Define the Switch task to route based on shippingType
&lt;/span&gt;    &lt;span class="n"&gt;switch_shipping&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SwitchTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;task_ref_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;switch_shipping_method&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;case_expression&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;${workflow.input.shippingType}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;switch_shipping&lt;/span&gt; \
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;switch_case&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;standard&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;standard_shipping&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; \
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;switch_case&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;express&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;express_shipping&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; \
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;switch_case&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;overnight&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;overnight_shipping&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; \
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;default_case&lt;/span&gt;&lt;span class="p"&gt;([])&lt;/span&gt;

    &lt;span class="n"&gt;workflow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ConductorWorkflow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;order_processing_workflow&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;workflow_executor&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fetch_order_details&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;switch_shipping&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;workflow&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/conductor-oss/awesome-conductor-apps/blob/main/python/operator_examples/switch-workflow.py" rel="noopener noreferrer"&gt;Check out the full sample code for the Switch Workflow.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Dynamic
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Dynamic&lt;/strong&gt; task in Orkes Conductor enables workflows to determine and execute tasks at runtime based on input data, rather than defining them statically in the workflow definition. This is especially useful for cases where the number or type of tasks isn’t known in advance—such as processing a variable-length list of items or executing a dynamic sequence of operations. The task determines a llist of task(s) to be executed, allowing workflows to adapt their structure on the fly while remaining fully managed and observable within Conductor.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example implementation
&lt;/h3&gt;

&lt;p&gt;In a shipping workflow, the courier used to fulfill an order—such as FedEx or UPS—depends on the destination address, which isn’t known until runtime. A Dynamic task allows the workflow to decide which shipping task to execute on the fly, based on the result of a previous task that determines the best courier. For instance, if the &lt;code&gt;shipping_info&lt;/code&gt; task outputs "ship_via_fedex", the dynamic task will execute the &lt;code&gt;ship_via_fedex&lt;/code&gt; task; if it returns "ship_via_ups", the workflow dynamically routes to &lt;code&gt;ship_via_ups&lt;/code&gt;. This eliminates hardcoded branching and makes the workflow adaptable to real-time decision-making.&lt;/p&gt;

&lt;p&gt;Here’s the workflow visualized:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk5lc3hh4flra6z3rrugu.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk5lc3hh4flra6z3rrugu.jpg" alt="High-level diagram of the Dynamic workflow vs the actual workflow diagram in Conductor." width="800" height="500"&gt;&lt;/a&gt;Workflow using a Dynamic operator.&lt;/p&gt;

&lt;p&gt;Here’s the code snippet for creating the workflow in code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;register_workflow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;workflow_executor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;WorkflowExecutor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ConductorWorkflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# 1) Task to simulate courier selection
&lt;/span&gt;    &lt;span class="n"&gt;shipping_info&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;HttpTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;task_ref_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;shipping_info_ref&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;http_input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;uri&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://jsonplaceholder.typicode.com/posts&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;method&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;POST&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;headers&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Content-Type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;body&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;order_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;${workflow.input.order_id}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;destination&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;${workflow.input.address}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 2) Dynamic task that picks the shipping method based on workflow input
&lt;/span&gt;    &lt;span class="n"&gt;dynamic_shipping&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;DynamicTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;dynamic_task&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;${workflow.input.shipping_service}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;task_reference_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dynamic_shipping&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;workflow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ConductorWorkflow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Shipping_Flow&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;workflow_executor&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;shipping_info&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dynamic_shipping&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;overwrite&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;workflow&lt;/span&gt;


&lt;span class="c1"&gt;# Worker for FedEx
&lt;/span&gt;&lt;span class="nd"&gt;@worker_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task_definition_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ship_via_fedex&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;ship_via_fedex&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;📦 Shipping via FedEx&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;FedEx shipment created&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="c1"&gt;# Worker for UPS
&lt;/span&gt;&lt;span class="nd"&gt;@worker_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task_definition_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ship_via_ups&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;ship_via_ups&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;📦 Shipping via UPS&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;UPS shipment created&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/conductor-oss/awesome-conductor-apps/blob/main/python/operator_examples/dynamic-workflow.py" rel="noopener noreferrer"&gt;Check out the full sample code for the Dynamic Workflow.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Set Variable
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Set Variable&lt;/strong&gt; task in Orkes Conductor is used to define or update variables within the scope of a workflow execution. It allows you to store values—such as computed results, flags, or counters—that can be referenced later by other tasks. This task is especially useful for tracking workflow state, managing intermediate data, or preparing inputs for conditional logic or dynamic tasks. Variables set using this task are stored in the workflow’s context and persist throughout its execution.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example implementation
&lt;/h3&gt;

&lt;p&gt;In an e-commerce order processing workflow, the Set Variable task is used to store intermediate values like the subtotal, discount, and tax during price calculation. For instance, after the &lt;code&gt;calculate_subtotal&lt;/code&gt; task, a Set Variable task updates the &lt;code&gt;subtotal&lt;/code&gt; variable, which is then modified by the &lt;code&gt;apply_discount&lt;/code&gt; task and used in the final price calculation. These variables are passed to subsequent tasks like &lt;code&gt;process_payment&lt;/code&gt;, ensuring the correct amount is charged.&lt;/p&gt;

&lt;p&gt;Here’s the workflow visualized:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo3dalmaqrmhyturyctcc.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo3dalmaqrmhyturyctcc.jpg" alt="High-level diagram of the Set Variable workflow vs the actual workflow diagram in Conductor." width="800" height="698"&gt;&lt;/a&gt;Workflow using a Set Variable operator.&lt;/p&gt;

&lt;p&gt;Here’s the code snippet for creating the workflow in code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;register_workflow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;workflow_executor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;WorkflowExecutor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ConductorWorkflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# 1) Calculate subtotal
&lt;/span&gt;    &lt;span class="n"&gt;calc_subtotal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SimpleTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;task_def_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;calculate_subtotal&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;task_reference_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;calculate_subtotal&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 2) Store subtotal
&lt;/span&gt;    &lt;span class="n"&gt;set_subtotal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SetVariableTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task_ref_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;set_subtotal&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;set_subtotal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;input_parameters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;subtotal&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;${calculate_subtotal.output.subtotal}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="c1"&gt;# 3) Apply discount
&lt;/span&gt;    &lt;span class="n"&gt;apply_discount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SimpleTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;task_def_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;apply_discount&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;task_reference_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;apply_discount&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 4) Store discounted price
&lt;/span&gt;    &lt;span class="n"&gt;set_discounted_price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SetVariableTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task_ref_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;set_discounted_price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;set_discounted_price&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;input_parameters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;discounted_price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;${apply_discount.output.discounted_total}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="c1"&gt;# 5) Process payment
&lt;/span&gt;    &lt;span class="n"&gt;process_payment&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SimpleTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;task_def_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;process_payment&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;task_reference_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;process_payment&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;input_parameters&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;amount&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;${workflow.variables.discounted_price}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;workflow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ConductorWorkflow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ecommerce_order_processing&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;workflow_executor&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;calc_subtotal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;set_subtotal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;apply_discount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;set_discounted_price&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;process_payment&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;overwrite&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;workflow&lt;/span&gt;


&lt;span class="nd"&gt;@worker_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task_definition_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;calculate_subtotal&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;calculate_subtotal&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;🧮 Calculating subtotal...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;subtotal&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;200.0&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="nd"&gt;@worker_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task_definition_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;apply_discount&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;apply_discount&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;🏷️ Applying discount...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;discounted_total&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;180.0&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="nd"&gt;@worker_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task_definition_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;process_payment&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;process_payment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;💰 Charging customer: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;input_data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;amount&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Payment successful&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/conductor-oss/awesome-conductor-apps/blob/main/python/operator_examples/setvariable-workflow.py" rel="noopener noreferrer"&gt;Check out the full sample code for the Set Variable Workflow.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Terminate
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Terminate&lt;/strong&gt; task in Orkes Conductor allows you to immediately end a workflow, either successfully or with a failure, before all tasks are completed. This is useful for scenarios where certain conditions are met, such as an error or a manual intervention, that require halting the workflow early. The task can be configured with an optional message, like a termination reason, providing context. This helps ensure that workflows end gracefully, preventing unnecessary tasks from being executed when they are no longer needed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example implementation
&lt;/h3&gt;

&lt;p&gt;In a shipping workflow, the Terminate task ends the workflow if an invalid shipping provider is provided. During the workflow, a decision is made to ship with a specific provider based on user input. If the input does not match the available options (e.g., FedEx or UPS), the workflow enters the default case of a Switch task and triggers a Terminate task, halting the workflow with a "FAILED" status and a relevant reason.&lt;/p&gt;

&lt;p&gt;Here’s the workflow visualized:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp3em75aombip24v9a1ib.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp3em75aombip24v9a1ib.jpg" alt="High-level diagram of the Terminate workflow vs the actual workflow diagram in Conductor." width="800" height="424"&gt;&lt;/a&gt;Workflow using a Terminate operator.&lt;/p&gt;

&lt;p&gt;Here’s the code snippet for creating the workflow in code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;register_shipping_workflow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;workflow_executor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;WorkflowExecutor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ConductorWorkflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# 1) Decide based on shipping provider
&lt;/span&gt;    &lt;span class="n"&gt;switch_provider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SwitchTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;task_ref_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;switch_provider&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;case_expression&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;${workflow.input.shipping_provider}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 2a) FedEx path
&lt;/span&gt;    &lt;span class="n"&gt;fedex_task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SimpleTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;task_def_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ship_with_fedex&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;task_reference_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ship_with_fedex&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 2b) UPS path
&lt;/span&gt;    &lt;span class="n"&gt;ups_task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SimpleTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;task_def_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ship_with_ups&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;task_reference_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ship_with_ups&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 3) Default path — Terminate the workflow if the provider is invalid
&lt;/span&gt;    &lt;span class="n"&gt;terminate_task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;TerminateTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;task_ref_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;terminate_invalid_provider&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;WorkflowStatus&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;FAILED&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;termination_reason&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;${workflow.input.termination_reason}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 4) Configure Switch task cases
&lt;/span&gt;    &lt;span class="n"&gt;switch_provider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;switch_case&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;FEDEX&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;fedex_task&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;switch_provider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;switch_case&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;UPS&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ups_task&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;switch_provider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;default_case&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;terminate_task&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

    &lt;span class="n"&gt;workflow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ConductorWorkflow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;shipping_workflow_with_validation&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;workflow_executor&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;switch_provider&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;overwrite&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;workflow&lt;/span&gt;


&lt;span class="nd"&gt;@worker_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task_definition_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ship_with_fedex&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;ship_with_fedex&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;📦 Shipping with FedEx...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Shipped via FedEx&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="nd"&gt;@worker_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task_definition_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ship_with_ups&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;ship_with_ups&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;📦 Shipping with UPS...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Shipped via UPS&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/conductor-oss/awesome-conductor-apps/blob/main/python/operator_examples/terminate-workflow.py" rel="noopener noreferrer"&gt;Check out the full sample code for the Terminate Workflow.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap up
&lt;/h2&gt;

&lt;p&gt;Branching and conditionals bring workflows to life, allowing them to adapt in real time based on input, state, or external data. With tasks like &lt;code&gt;Switch&lt;/code&gt;, &lt;code&gt;Dynamic&lt;/code&gt;, &lt;code&gt;SetVariable&lt;/code&gt;, and &lt;code&gt;Terminate&lt;/code&gt;, Conductor makes decision logic clear, declarative, and maintainable. No tangled logic, no hidden conditionals—just clean, visible control flow.&lt;/p&gt;

&lt;p&gt;Next up: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/orkes/orkes-operators-loops-waits-and-human-in-the-loop-2ece"&gt;Loops, Waits, and Human-in-the-Loop&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/orkes/orkes-operators-parallelism-and-reusability-4g32"&gt;Parallelism and Reusability&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;—&lt;/p&gt;

&lt;p&gt;&lt;a href="https://orkes.io/platform?utm_campaign=operators-blog-2&amp;amp;utm_source=devto-blog&amp;amp;utm_medium=web" rel="noopener noreferrer"&gt;Orkes Conductor&lt;/a&gt; is an enterprise-grade Unified Application Platform for process automation, API and microservices orchestration, agentic workflows, and more. Check out the &lt;a href="https://orkes.io/pricing" rel="noopener noreferrer"&gt;full set of features&lt;/a&gt;, or try it yourself using our free &lt;a href="https://developer.orkescloud.com/?utm_campaign=operators-blog-2&amp;amp;utm_source=devto-blog&amp;amp;utm_medium=web" rel="noopener noreferrer"&gt;Developer Playground&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>orchestration</category>
      <category>workflows</category>
      <category>development</category>
      <category>controlflow</category>
    </item>
    <item>
      <title>Control the Flow: Building Dynamic Workflows with Orkes Operators</title>
      <dc:creator>Orkes Developers</dc:creator>
      <pubDate>Mon, 28 Apr 2025 12:09:24 +0000</pubDate>
      <link>https://dev.to/orkes/control-the-flow-building-dynamic-workflows-with-orkes-operators-2fo9</link>
      <guid>https://dev.to/orkes/control-the-flow-building-dynamic-workflows-with-orkes-operators-2fo9</guid>
      <description>&lt;p&gt;Orchestration is a powerful design framework for coordinating distributed services and systems into automated processes. Using a workflow engine, such as &lt;a href="https://orkes.io/platform?utm_campaign=operators-blog-1&amp;amp;utm_source=devto-blog&amp;amp;utm_medium=web" rel="noopener noreferrer"&gt;Orkes Conductor&lt;/a&gt;, provides a myriad of benefits like &lt;a href="https://dev.to/orkes/why-your-applications-need-durable-execution-and-best-practices-to-achieve-it-5ham"&gt;durable executions&lt;/a&gt;, state tracking, and developer productivity. &lt;/p&gt;

&lt;p&gt;A key part of this orchestration model is &lt;strong&gt;operators&lt;/strong&gt;, which are control flow primitives that resemble programming constructs. By using operators, developers can model dynamic, intelligent workflows without writing imperative control logic, making it easier to scale, maintain, and evolve complex systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are operators?
&lt;/h2&gt;

&lt;p&gt;In Conductor, &lt;strong&gt;operators&lt;/strong&gt; define the control flow, structure, and decision-making within a workflow. Operators are one of the three core task types used in workflows, alongside &lt;strong&gt;system tasks&lt;/strong&gt; and &lt;strong&gt;worker tasks&lt;/strong&gt;. While system and worker tasks focus on performing actions (like sending HTTP requests or processing data), operator tasks define the control flow.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5affhw38selqcbthyeai.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5affhw38selqcbthyeai.jpg" alt="Diagram of the three task types in Conductor: System Tasks, Operators, and Worker Tasks." width="800" height="418"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Operators act as declarative control structures, similar to constructs in traditional programming languages. For example, a &lt;code&gt;Switch&lt;/code&gt; operator mimics a switch-case statement, a &lt;code&gt;Fork&lt;/code&gt; allows for parallel task execution, and a &lt;code&gt;Do While&lt;/code&gt; enables looping logic. These constructs make it possible to express complex workflow logic (branching, looping, and conditional execution) all without writing procedural code. &lt;/p&gt;

&lt;p&gt;Operators are essential for orchestrating &lt;a href="https://orkes.io/blog/what-are-agentic-workflows/" rel="noopener noreferrer"&gt;&lt;strong&gt;agentic workflows&lt;/strong&gt;&lt;/a&gt;, where conditional or parallel logic provides a mapped space for the agent to act autonomously within bounds. Similarly, using operators, &lt;strong&gt;human-in-the-loop&lt;/strong&gt; flows can be dynamically controlled based on the manual input received mid-flow.&lt;/p&gt;

&lt;p&gt;Like &lt;a href="https://dev.to/orkes/unlocking-developer-productivity-orchestrate-workflows-with-built-in-system-tasks-4hl8"&gt;system tasks&lt;/a&gt;, operator tasks are fully managed by Conductor and do not require any external workers to run. They are evaluated and executed internally by the engine, making them lightweight and efficient building blocks for composing complex workflows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why use operators?
&lt;/h2&gt;

&lt;p&gt;Using operators in your workflows offers a range of benefits, especially when compared to managing control flow directly in code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Declarative logic:&lt;/strong&gt; Operators allow you to express branching, looping, and parallelism in a clean, declarative way. No need to write imperative control logic or orchestration code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Separation of concerns:&lt;/strong&gt; Business logic stays inside your services, while orchestration logic lives inside your workflow. This separation makes it easier to test, reason about, and maintain your applications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic execution paths:&lt;/strong&gt; You can define workflows that respond to real-time data and conditions, dynamically choosing tasks or branches to execute.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fully managed by Conductor:&lt;/strong&gt; Operators require no external workers or custom handlers. They’re executed entirely within the Conductor engine, reducing complexity and operational overhead.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By leveraging operators, you can design robust, readable, and adaptable workflows without getting bogged down by control-flow code scattered across services.&lt;/p&gt;

&lt;h2&gt;
  
  
  The power of declarative logic
&lt;/h2&gt;

&lt;p&gt;Declarative logic is all about &lt;strong&gt;describing &lt;em&gt;what&lt;/em&gt; should happen&lt;/strong&gt;, not &lt;em&gt;how&lt;/em&gt; to make it happen. In traditional code, developers must spell out the exact sequence of steps and control flow — managing state, writing loops, handling conditionals, and coordinating service calls. This imperative approach can quickly become brittle and hard to maintain as workflows grow in complexity.&lt;/p&gt;

&lt;p&gt;By contrast, declarative logic lets you &lt;strong&gt;define the intent of the workflow&lt;/strong&gt; and offload the execution details to the orchestration engine. This not only simplifies development but also makes workflows easier to read, reason about, and debug.&lt;/p&gt;

&lt;p&gt;Operators in Orkes Conductor are a perfect example of this approach. They serve as control flow declarations: you define that a workflow should loop, branch, or fork — and Conductor takes care of executing that logic under the hood. Want to repeat a task until a condition is met? Just add a &lt;code&gt;Do While&lt;/code&gt; with the right condition. Need to split work across multiple paths and rejoin later? Use &lt;code&gt;Fork&lt;/code&gt; and &lt;code&gt;Join&lt;/code&gt;. There’s no need to write a single line of plumbing code.&lt;/p&gt;

&lt;p&gt;This declarative style brings huge benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Maintainability&lt;/strong&gt;: Simply update the workflow definition to change the workflow logic. No need to rewrite service code. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Readability&lt;/strong&gt;: Declarative workflows are self-documenting. You can inspect them in the UI or JSON and instantly understand the flow.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modularity&lt;/strong&gt;: You can compose and reuse smaller workflows, using operators like &lt;code&gt;Sub Workflow&lt;/code&gt; or &lt;code&gt;Start Workflow&lt;/code&gt; as high-level building blocks.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Declarative vs imperative logic
&lt;/h3&gt;

&lt;p&gt;In this example, we demonstrate how both imperative and declarative workflows handle iterating over a list of tasks and making HTTP requests for each. The imperative workflow explicitly defines the loop, including custom error handling for each HTTP request, while the declarative workflow uses Orkes Conductor's built-in &lt;code&gt;Do While&lt;/code&gt; operator to manage iteration, with automatic error handling provided by the engine. This showcases the difference in complexity and control between the two approaches.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkxu31dz6reuwinxpf8im.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkxu31dz6reuwinxpf8im.jpg" alt="Comparision diagram of an example workflow using imperative logic vs using declarative logic." width="800" height="617"&gt;&lt;/a&gt;Imperative logic vs declarative logic.&lt;/p&gt;

&lt;p&gt;Declarative orchestration is especially valuable when building &lt;a href="https://orkes.io/blog/what-are-agentic-workflows/" rel="noopener noreferrer"&gt;agentic workflows&lt;/a&gt;, human-in-the-loop workflows, event-driven systems, or other dynamic execution paths. Operators let you adapt to changing inputs or user actions without embedding decision logic inside services.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview of Conductor’s operators
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F45dwqbnl793htc205oxl.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F45dwqbnl793htc205oxl.jpg" alt="Diagram of all Conductor operators: Switch, Dynamic, Wait, Set Variable, Do WHile, Human, Sub Workflow, Terminate Workflow, Terminate, Fork, Join, Dynamic Fork, Start Workflow, Get Workflow." width="800" height="454"&gt;&lt;/a&gt;Build workflows declaratively with operators.&lt;/p&gt;

&lt;p&gt;With over &lt;strong&gt;a dozen operators&lt;/strong&gt; and extensive SDK support, you can quickly build out and deploy powerful workflows. Let’s explore example workflows that make use of these most commonly used tasks:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Operator&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Switch&lt;/td&gt;
&lt;td&gt;Branches the workflow based on conditions, similar to a switch-case construct. Learn more: &lt;a href="https://orkes.io/blog/operators-branching-and-conditionals" rel="noopener noreferrer"&gt;Branching and Conditionals&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dynamic&lt;/td&gt;
&lt;td&gt;Dynamically evaluates conditions at runtime to determine what to do. Learn more: &lt;a href="https://orkes.io/blog/operators-branching-and-conditionals" rel="noopener noreferrer"&gt;Branching and Conditionals&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Set Variable&lt;/td&gt;
&lt;td&gt;Sets variables within the workflow, allowing for dynamic control during execution. Learn more: &lt;a href="https://orkes.io/blog/operators-branching-and-conditionals" rel="noopener noreferrer"&gt;Branching and Conditionals&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Terminate&lt;/td&gt;
&lt;td&gt;Ends the workflow execution early, often used for terminating workflows under conditions. Learn more: &lt;a href="https://orkes.io/blog/operators-branching-and-conditionals" rel="noopener noreferrer"&gt;Branching and Conditionals&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Do While&lt;/td&gt;
&lt;td&gt;Loops through tasks until a condition is no longer true, used for repeated actions. Learn more: &lt;a href="https://orkes.io/blog/" rel="noopener noreferrer"&gt;Loops, Waits, and Human-in-the-Loop&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Wait&lt;/td&gt;
&lt;td&gt;Pauses execution for a set time or until a condition is met. Learn more: &lt;a href="https://orkes.io/blog/" rel="noopener noreferrer"&gt;Loops, Waits, and Human-in-the-Loop&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Human&lt;/td&gt;
&lt;td&gt;Pauses execution until manual input is received, useful for human-in-the-loop scenarios. Learn more: &lt;a href="https://orkes.io/blog/" rel="noopener noreferrer"&gt;Loops, Waits, and Human-in-the-Loop&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fork&lt;/td&gt;
&lt;td&gt;Executes multiple tasks in parallel, enabling concurrent processing. Learn more: &lt;a href="https://orkes.io/blog/" rel="noopener noreferrer"&gt;Parallelism and Reusability&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Join&lt;/td&gt;
&lt;td&gt;Merges the results from parallel tasks, allowing the workflow to proceed together. Learn more: &lt;a href="https://orkes.io/blog/" rel="noopener noreferrer"&gt;Parallelism and Reusability&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dynamic Fork&lt;/td&gt;
&lt;td&gt;Dynamically creates parallel tasks at runtime based on conditions or data. Learn more: &lt;a href="https://orkes.io/blog/" rel="noopener noreferrer"&gt;Parallelism and Reusability&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sub Workflow&lt;/td&gt;
&lt;td&gt;Triggers another workflow within the current workflow for modularity and reusability. Learn more: &lt;a href="https://orkes.io/blog/" rel="noopener noreferrer"&gt;Parallelism and Reusability&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Start Workflow&lt;/td&gt;
&lt;td&gt;Starts another workflow asynchronously in parallel with the current workflow. Learn more: &lt;a href="https://orkes.io/blog/" rel="noopener noreferrer"&gt;Parallelism and Reusability&lt;/a&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Wrap up
&lt;/h2&gt;

&lt;p&gt;Orkes Conductor simplifies workflow orchestration by using declarative operators to manage complex logic. With tasks like Switch, Do While, and Fork/Join, you can build flexible, scalable workflows without writing imperative code. This approach accelerates development, reduces maintenance overhead, and enables collaboration across teams. Whether through the visual diagram editor or Conductor SDKs in Java, Python, or other languages, Conductor empowers developers to easily design, manage, and scale workflows.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mastering control flow with Conductor&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;With operators, you design the flow, and Conductor handles the execution logic, freeing you to focus on building the features that matter.&lt;/p&gt;

&lt;p&gt;Check out how to use Conductor’s operators with these articles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;​&lt;a href="https://dev.to/orkes/orkes-operators-branching-and-conditionals-2pe4"&gt;Branching and Conditionals&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/orkes/orkes-operators-loops-waits-and-human-in-the-loop-2ece"&gt;Loops, Waits, and Human-in-the-Loop&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/orkes/orkes-operators-parallelism-and-reusability-4g32"&gt;Parallelism and Reusability&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;a href="https://orkes.io/platform?utm_campaign=operators-blog-1&amp;amp;utm_source=devto-blog&amp;amp;utm_medium=web" rel="noopener noreferrer"&gt;Orkes Conductor&lt;/a&gt; is an enterprise-grade Unified Application Platform for process automation, API and microservices orchestration, agentic workflows, and more. Check out the &lt;a href="https://orkes.io/pricing" rel="noopener noreferrer"&gt;full set of features&lt;/a&gt;, or try it yourself using our free &lt;a href="https://developer.orkescloud.com/?utm_campaign=operators-blog-1&amp;amp;utm_source=devto-blog&amp;amp;utm_medium=web" rel="noopener noreferrer"&gt;Developer Playground&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>orchestration</category>
      <category>workflows</category>
      <category>development</category>
      <category>controlflow</category>
    </item>
    <item>
      <title>Implementing Easy-to-Build Workflows with Conductor’s System Tasks</title>
      <dc:creator>Orkes Developers</dc:creator>
      <pubDate>Mon, 14 Apr 2025 13:52:00 +0000</pubDate>
      <link>https://dev.to/orkes/implementing-easy-to-build-workflows-with-conductors-system-tasks-45ph</link>
      <guid>https://dev.to/orkes/implementing-easy-to-build-workflows-with-conductors-system-tasks-45ph</guid>
      <description>&lt;p&gt;&lt;em&gt;This is Part 2 of the series on System Tasks. Check out &lt;a href="https://dev.to/orkes/unlocking-developer-productivity-orchestrate-workflows-with-built-in-system-tasks-4hl8"&gt;Part 1&lt;/a&gt;, which discusses the pros and cons of using system tasks and alternative solutions.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;Whether you’re orchestrating a simple API flow or building complex AI-powered applications, system tasks make it easy to plug functionality into your workflows. In this post, we’ll explore the most common system tasks in Orkes Conductor and demonstrate how you can leverage them to accelerate development and unlock the full potential of Orkes Conductor.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recap: what are system tasks?
&lt;/h2&gt;

&lt;p&gt;Orkes Conductor is a workflow orchestration platform packed with developer-first features. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;System tasks&lt;/strong&gt; in Orkes Conductor represent reusable business logic components, like HTTP calls and database queries. These tasks run within the Conductor engine, allowing developers to quickly build complex and durable workflows without reinventing the wheel.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview of Conductor’s system tasks
&lt;/h2&gt;

&lt;p&gt;With over &lt;strong&gt;twenty system tasks&lt;/strong&gt; and extensive SDK support, you can quickly build out and deploy powerful workflows. Let’s explore example workflows that make use of these most commonly-used tasks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Event&lt;/li&gt;
&lt;li&gt;HTTP&lt;/li&gt;
&lt;li&gt;HTTP Poll&lt;/li&gt;
&lt;li&gt;Inline&lt;/li&gt;
&lt;li&gt;JSON JQ Transform&lt;/li&gt;
&lt;li&gt;Wait For Webhook&lt;/li&gt;
&lt;li&gt;Alerting tasks&lt;/li&gt;
&lt;li&gt;AI tasks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzr1tiqo4a0c1wi7l1xxh.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzr1tiqo4a0c1wi7l1xxh.jpg" alt="List of system tasks in Orkes Conductor that are covered in this blog: Event, HTTP, HTTP Poll, Inline, JSON JQ Transform, Wait For Webhook, Alerting Tasks, AI Tasks." width="800" height="418"&gt;&lt;/a&gt;Commonly-used &lt;a href="https://orkes.io/content/category/reference-docs/system-tasks" rel="noopener noreferrer"&gt;system tasks&lt;/a&gt; in Orkes Conductor.&lt;/p&gt;

&lt;h2&gt;
  
  
  Event
&lt;/h2&gt;

&lt;p&gt;In distributed systems, async communication is key一and that’s where the Event task comes in. It allows your workflow to publish messages to an external event queue or topic, enabling decoupled communication between services. Whether you’re using Kafka, SQS, or another messaging system, Orkes Conductor integrates with many providers, making it easy to trigger downstream processes or notify external systems as part of your workflow.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example implementation
&lt;/h3&gt;

&lt;p&gt;Imagine a payment workflow that processes a transaction and needs to notify an inventory service once completed. The workflow first makes an HTTP call to a payment API to confirm the transaction. Once confirmed, instead of directly calling the inventory service, an Event task publishes a message to a Kafka topic. The inventory service listens to the Kafka topic, consumes the event, and asynchronously updates stock levels, decoupling the processes for scalability and flexibility.&lt;/p&gt;

&lt;p&gt;Here’s the workflow visualized:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fawlbyi54ljwm5ougcyrl.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fawlbyi54ljwm5ougcyrl.jpg" alt="High-level diagram of the Event workflow vs the actual workflow diagram in Conductor." width="800" height="617"&gt;&lt;/a&gt;Workflow using an Event task.&lt;/p&gt;

&lt;p&gt;To create this workflow in Conductor, you must first integrate the&lt;a href="https://orkes.io/content/category/integrations/message-broker" rel="noopener noreferrer"&gt; required message broker&lt;/a&gt;, and then add the relevant system tasks. Here’s the code snippet for creating the workflow in code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;register_workflow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;workflow_executor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;WorkflowExecutor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ConductorWorkflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# 1) Define the HTTP task for calling the dummy JSONPlaceholder API
&lt;/span&gt;    &lt;span class="n"&gt;http_task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;HttpTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;task_ref_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fetch_order_details&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;http_input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;uri&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://jsonplaceholder.typicode.com/posts/\${workflow.input.orderId}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;method&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;GET&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;headers&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Content-Type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 2) Define the Event task using EventTaskInterface
&lt;/span&gt;    &lt;span class="n"&gt;event_task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;EventTaskInterface&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;task_ref_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;notify_inventory&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;event_prefix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;kafka&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;event_suffix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;quickstart-events&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Update input parameters for the event task using data from the HTTP task response
&lt;/span&gt;    &lt;span class="n"&gt;event_task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;input_parameters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;orderId&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\${fetch_order_details.output.response.body.id}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\${fetch_order_details.output.response.body.title}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;body&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\${fetch_order_details.output.response.body.body}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="c1"&gt;# Define the workflow and add the tasks
&lt;/span&gt;    &lt;span class="n"&gt;workflow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ConductorWorkflow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;inventory_management_workflow&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;workflow_executor&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;http_task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event_task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Register the workflow
&lt;/span&gt;    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;workflow&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/conductor-oss/awesome-conductor-apps/blob/main/python/system_task_examples/event-workflow.py" rel="noopener noreferrer"&gt;Check out the full sample code for the Event Workflow.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  HTTP
&lt;/h2&gt;

&lt;p&gt;The HTTP task is used to make calls to remote services exposed over HTTP/HTTPS, a fundamental part of most service-based applications. It provides a clean abstraction that makes it intuitive to declare API calls. This simplifies integration with external systems, eliminating the need for custom workers and manual integration..&lt;/p&gt;

&lt;h3&gt;
  
  
  Example implementation
&lt;/h3&gt;

&lt;p&gt;In a payment processing system, you need to interact with an external API to charge a customer’s credit card. It sends a POST request via an HTTP task to the payment API with the order ID and amount, along with an authorization token.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If the payment succeeds (status code 200), the workflow continues to update the order status and marks the payment as successful.&lt;/li&gt;
&lt;li&gt;If the payment fails (any status code other than 200), the workflow notifies the user of the failure.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The workflow ensures efficient handling of payment success or failure through conditional branching with the use of the Switch task.&lt;/p&gt;

&lt;p&gt;Here’s the workflow visualized:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foagsya98z4rmoukqb2ii.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foagsya98z4rmoukqb2ii.jpg" alt="High-level diagram of the HTTP workflow vs the actual workflow diagram in Conductor." width="800" height="617"&gt;&lt;/a&gt;Workflow using an HTTP task.&lt;/p&gt;

&lt;p&gt;Here’s the code snippet for creating the workflow in code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;register_workflow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;workflow_executor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;WorkflowExecutor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ConductorWorkflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# 1) Define the HTTP task for calling the payment API
&lt;/span&gt;    &lt;span class="n"&gt;http_task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;HttpTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;task_ref_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;call_payment_api&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;http_input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;uri&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://httpbin.org/status/200&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;method&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;POST&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;headers&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Content-Type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Authorization&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bearer \${workflow.input.auth_token}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;body&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;orderId&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\${workflow.input.orderId}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;amount&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\${workflow.input.amount}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 2) Define the SwitchTask with case expression
&lt;/span&gt;    &lt;span class="n"&gt;switch_task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SwitchTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;task_ref_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;check_payment_status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;case_expression&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\${call_payment_api.output.response.statusCode}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;use_javascript&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 3) Define SetVariableTask for success case
&lt;/span&gt;    &lt;span class="n"&gt;set_payment_success_variable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SetVariableTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;task_ref_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;set_payment_success_variable&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;set_payment_success_variable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;input_parameters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;payment_status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SUCCESS&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="c1"&gt;# Define SetVariableTask for failure case
&lt;/span&gt;    &lt;span class="n"&gt;set_payment_failure_variable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SetVariableTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;task_ref_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;set_payment_failure_variable&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;set_payment_failure_variable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;input_parameters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;payment_status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;FAILURE&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="c1"&gt;# Configure the decision logic for SwitchTask
&lt;/span&gt;    &lt;span class="n"&gt;switch_task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;switch_case&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;200&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;set_payment_success_variable&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;switch_task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;default_case&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;set_payment_failure_variable&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Define the workflow and add the tasks
&lt;/span&gt;    &lt;span class="n"&gt;workflow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ConductorWorkflow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;payment_workflow&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;workflow_executor&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;http_task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;switch_task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Register the workflow
&lt;/span&gt;    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;workflow&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/conductor-oss/awesome-conductor-apps/blob/main/python/system_task_examples/http-workflow.py" rel="noopener noreferrer"&gt;Check out the full sample code for the HTTP Workflow.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  HTTP Poll
&lt;/h2&gt;

&lt;p&gt;The HTTP Poll task in Orkes Conductor enables workflows to send HTTP requests to a specified endpoint at regular intervals, continuing until a defined termination condition is met. This is particularly useful for monitoring the status of long-running operations or waiting for external processes to complete.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example implementation
&lt;/h3&gt;

&lt;p&gt;Consider a scenario where a workflow needs to monitor the status of a file processing job initiated by an external service. The workflow can use the HTTP Poll task to periodically check the status endpoint of the external service until the job is completed.&lt;/p&gt;

&lt;p&gt;Here’s the workflow visualized:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3s4jlrs9py4mhqva7usb.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3s4jlrs9py4mhqva7usb.jpg" alt="High-level diagram of the HTTP Poll workflow vs the actual workflow diagram in Conductor." width="800" height="589"&gt;&lt;/a&gt;Workflow using an HTTP Poll task.&lt;/p&gt;

&lt;p&gt;Here’s the code snippet for creating the workflow in code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;register_workflow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;workflow_executor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;WorkflowExecutor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ConductorWorkflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# 1) Define the HTTP Poll input
&lt;/span&gt;    &lt;span class="n"&gt;http_poll_input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;HttpPollInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://httpbin.org/delay/10&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;GET&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;accept&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;termination_condition&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\$.output.response.statusCode == 200&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;polling_interval&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 2) Define the HTTP Poll task for checking the file processing status
&lt;/span&gt;    &lt;span class="n"&gt;http_poll_task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;HttpPollTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;task_ref_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;check_file_processing_status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;http_input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;http_poll_input&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 3) Define SetVariableTask for the success case
&lt;/span&gt;    &lt;span class="n"&gt;set_processing_complete_variable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SetVariableTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;task_ref_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;set_processing_complete_variable&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;set_processing_complete_variable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;input_parameters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;processing_status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;COMPLETED&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="c1"&gt;# Define SetVariableTask for the failure case
&lt;/span&gt;    &lt;span class="n"&gt;set_processing_failed_variable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SetVariableTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;task_ref_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;set_processing_failed_variable&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;set_processing_failed_variable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;input_parameters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;processing_status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;FAILED&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="c1"&gt;# 4) Define SwitchTask to handle success and failure cases
&lt;/span&gt;    &lt;span class="n"&gt;switch_task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SwitchTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;task_ref_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;check_processing_status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;case_expression&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\${check_file_processing_status.output.response.statusCode}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;use_javascript&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Configure the decision cases for the SwitchTask
&lt;/span&gt;    &lt;span class="n"&gt;switch_task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;switch_case&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;set_processing_complete_variable&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;switch_task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;default_case&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;set_processing_failed_variable&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Define the workflow and add the tasks
&lt;/span&gt;    &lt;span class="n"&gt;workflow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ConductorWorkflow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;file_processing_workflow&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;workflow_executor&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;http_poll_task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;switch_task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Register the workflow
&lt;/span&gt;    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;workflow&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/conductor-oss/awesome-conductor-apps/blob/main/python/system_task_examples/http-poll-workflow.py" rel="noopener noreferrer"&gt;Check out the full sample code for the HTTP Poll Workflow.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Inline
&lt;/h2&gt;

&lt;p&gt;The Inline task in Orkes Conductor allows workflows to execute custom JavaScript code during runtime, facilitating dynamic data processing and decision-making without the need for external workers. This task is particularly useful for implementing lightweight logic, such as data transformations, conditional checks, or calculations, directly within the workflow.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example implementation
&lt;/h3&gt;

&lt;p&gt;In an e-commerce platform, the Inline task can be used to dynamically calculate prices based on various factors like loyalty status and active promotions. Instead of relying on an external service, the task executes custom JavaScript within the workflow to calculate the final price.&lt;/p&gt;

&lt;p&gt;Here’s the workflow visualized:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fshh6r11vislzlawpwdvu.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fshh6r11vislzlawpwdvu.jpg" alt="High-level diagram of the Inline workflow vs the actual workflow diagram in Conductor." width="800" height="671"&gt;&lt;/a&gt;Workflow using an Inline task.&lt;/p&gt;

&lt;p&gt;Here’s the code snippet for creating the workflow in code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;register_workflow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;workflow_executor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;WorkflowExecutor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ConductorWorkflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# 1) HTTP task to fetch a random number from random.org
&lt;/span&gt;    &lt;span class="n"&gt;fetch_random_number_task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;HttpTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;task_ref_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;fetch_random_number&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;http_input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;uri&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://www.random.org/integers/?num=1&amp;amp;min=1&amp;amp;max=100&amp;amp;col=1&amp;amp;base=10&amp;amp;format=plain&amp;amp;rnd=new&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;method&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;GET&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;headers&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Content-Type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 2) Set variable for base price using the random number
&lt;/span&gt;    &lt;span class="n"&gt;set_base_price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SetVariableTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;task_ref_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;set_base_price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;set_base_price&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;input_parameters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;base_price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\${fetch_random_number.output.response.body}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="c1"&gt;# 3) Inline task to calculate the final price with discounts
&lt;/span&gt;    &lt;span class="n"&gt;calculate_price_task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;InlineTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;task_ref_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;calculate_final_price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;script&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
            (function() {
                let basePrice = \$.base_price;
                let loyaltyDiscount = \$.loyalty_discount === &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gold&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; ? 0.2 : 0;
                let promotionDiscount = \$.promotion_discount ? 0.1 : 0;
                return basePrice * (1 - loyaltyDiscount - promotionDiscount);
            })();
        &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;bindings&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;base_price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\${workflow.variables.base_price}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;loyalty_discount&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\${workflow.input.loyalty_status}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;promotion_discount&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\${workflow.input.is_promotion_active}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 4) Set the final calculated price in a workflow variable
&lt;/span&gt;    &lt;span class="n"&gt;set_price_variable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SetVariableTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;task_ref_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;set_final_price_variable&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;set_price_variable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;input_parameters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;final_price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\${calculate_final_price.output.result}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="c1"&gt;# Define the workflow and add all tasks
&lt;/span&gt;    &lt;span class="n"&gt;workflow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ConductorWorkflow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dynamic_pricing_workflow&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;workflow_executor&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fetch_random_number_task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;set_base_price&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;calculate_price_task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;set_price_variable&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Register the workflow
&lt;/span&gt;    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;overwrite&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;workflow&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/conductor-oss/awesome-conductor-apps/blob/main/python/system_task_examples/inline-workflow.py" rel="noopener noreferrer"&gt;Check out the full sample code for the Inline Workflow.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  JSON JQ Transform
&lt;/h2&gt;

&lt;p&gt;The JSON JQ Transform task in Orkes Conductor enables workflows to process and transform JSON data using JQ, a powerful command-line tool for querying and manipulating JSON. This task allows you to apply JQ expressions to input JSON, facilitating operations like filtering, mapping, and restructuring data directly within your workflow.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example implementation
&lt;/h3&gt;

&lt;p&gt;Consider a scenario where a workflow retrieves a list of user data from an external API, but only a subset of fields is required for subsequent processing. The JSON JQ Transform task can be employed to filter and format the API response efficiently.&lt;/p&gt;

&lt;p&gt;Here’s the workflow visualized:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8giokh06z4i1lfgu3slw.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8giokh06z4i1lfgu3slw.jpg" alt="High-level diagram of the JSON JQ Transform workflow vs the actual workflow diagram in Conductor." width="800" height="617"&gt;&lt;/a&gt;Workflow using an JSON JQ Transform task.&lt;/p&gt;

&lt;p&gt;Here’s the code snippet for creating the workflow in code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;register_workflow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;workflow_executor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;WorkflowExecutor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ConductorWorkflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# JQ script to transform user data
&lt;/span&gt;    &lt;span class="n"&gt;jq_script&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
      .users | map({
        username: .login,
        profile_url: .html_url,
        avatar: .avatar_url
      })
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="c1"&gt;# 1) Create the JSON JQ task to transform incoming user data
&lt;/span&gt;    &lt;span class="n"&gt;jq_task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;JsonJQTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;task_ref_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;transform_user_data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;script&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;jq_script&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;jq_task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;input_parameters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;users&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\${workflow.input.users}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="c1"&gt;# 2) Create a SetVariableTask to store the transformed result
&lt;/span&gt;    &lt;span class="n"&gt;set_variable_task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SetVariableTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;task_ref_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;store_filtered_users&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;set_variable_task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;input_parameters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;filtered_users&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\${transform_user_data.output.result}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="c1"&gt;# Define and register the workflow
&lt;/span&gt;    &lt;span class="n"&gt;workflow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ConductorWorkflow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;simple_user_data_transform&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;workflow_executor&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;input_parameters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;users&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jq_task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;set_variable_task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Register the workflow
&lt;/span&gt;    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;overwrite&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;workflow&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/conductor-oss/awesome-conductor-apps/blob/main/python/system_task_examples/jsonjq-workflow.py" rel="noopener noreferrer"&gt;Check out the full sample code for the JSON JQ Transform Workflow.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wait For Webhook
&lt;/h2&gt;

&lt;p&gt;The Wait for Webhook task in Orkes Conductor is designed to pause a workflow’s execution until a specific external event is received via a webhook. This integration enables workflows to respond dynamically to real-time events from various platforms, including GitHub, Slack, Stripe, Microsoft Teams, and SendGrid. This is best when the external system can push events out.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example implementation
&lt;/h3&gt;

&lt;p&gt;A workflow waits for a webhook event indicating that a specific comment has been posted on a GitHub issue. Using a Wait for Webhook task, the workflow pauses until it receives the event with a comment from a specific author, such as “user123”. Once triggered, the workflow stores the comment content in a mock database, allowing subsequent tasks to process the comment, such as analyzing its content or triggering automated responses.&lt;/p&gt;

&lt;p&gt;Here’s the workflow visualized:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwvd948jengc9m1u0gf3i.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwvd948jengc9m1u0gf3i.jpg" alt="High-level diagram of the Wait For Webhook workflow vs the actual workflow diagram in Conductor." width="800" height="741"&gt;&lt;/a&gt;Workflow using a Wait For Webhook task.&lt;/p&gt;

&lt;p&gt;Here’s the code snippet for creating the workflow in code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;register_workflow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;workflow_executor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;WorkflowExecutor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ConductorWorkflow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# 1) Define the WaitForWebhookTask to pause until a specific comment is received
&lt;/span&gt;    &lt;span class="n"&gt;wait_for_comment_task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;WaitForWebHookTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;task_ref_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;wait_for_comment&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;matches&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\$[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;comment&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;author&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;]&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user123&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 2) Define an HTTP task to store the received comment in a mock database
&lt;/span&gt;    &lt;span class="n"&gt;store_comment_task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;HttpTask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;task_ref_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;store_comment&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;http_input&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;uri&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://jsonplaceholder.typicode.com/posts&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;method&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;POST&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;headers&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Content-Type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;application/json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;body&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;comment_body&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;\${wait_for_comment.output.comment.body}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;author&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user123&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Define and register the workflow
&lt;/span&gt;    &lt;span class="n"&gt;workflow&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ConductorWorkflow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;comment_trigger_workflow&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;executor&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;workflow_executor&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;wait_for_comment_task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;store_comment_task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Register the workflow
&lt;/span&gt;    &lt;span class="n"&gt;workflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;overwrite&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;workflow&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/conductor-oss/awesome-conductor-apps/blob/main/python/system_task_examples/wait-for-webhook-workflow.py" rel="noopener noreferrer"&gt;Check out the full sample code for the Wait for Webhook Workflow.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before running the workflow you must &lt;a href="https://orkes.io/content/templates/examples/custom-conductor-webhook-using-curl#creating-a-webhook-in-conductor" rel="noopener noreferrer"&gt;set up a webhook in Conductor&lt;/a&gt; for the workflow &lt;code&gt;comment_trigger_workflow&lt;/code&gt; and GitHub.&lt;/p&gt;

&lt;p&gt;After running the workflow, call this curl command to complete the workflow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -H "Content-Type:application/json" -H "Accept:application/json" \
-H 'key: value' \
-X POST '[INSERT_WEBHOOK_URL]' \
-d '{"comment": {"body": "This is my comment.", "author": "user123"}}'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Alerting Tasks
&lt;/h2&gt;

&lt;p&gt;Alerting tasks are specialized system tasks designed to monitor workflows and trigger alerts based on specific conditions. These tasks enhance observability and enable proactive incident management within your workflows, helping teams stay informed and act quickly when systems deviate from expected behavior. Explore how to use Alerting tasks with our &lt;a href="https://orkes.io/content/category/templates/alerting" rel="noopener noreferrer"&gt;suite of tutorials&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI Tasks
&lt;/h2&gt;

&lt;p&gt;Orkes Conductor offers a suite of AI tasks that facilitate seamless integration of Large Language Models (LLMs) and vector databases into workflows. These tasks enable functionalities such as text generation, embedding creation, document indexing, and retrieval, allowing developers to build both AI-driven applications and &lt;a href="https://orkes.io/blog/what-are-agentic-workflows/" rel="noopener noreferrer"&gt;agentic workflows&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;By incorporating these AI tasks, users can effectively orchestrate complex AI processes within their workflows, enhancing automation and intelligence in their applications. Explore how to use AI tasks with our &lt;a href="https://orkes.io/content/tutorials/ai" rel="noopener noreferrer"&gt;suite of tutorials&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap up
&lt;/h2&gt;

&lt;p&gt;Using system tasks in Conductor speeds up development cycles, bringing processes and products from paper to reality in no time at all. In this post, we’ve demonstrated building workflows using system tasks through Python. As a developer-first platform, Orkes Conductor is built for creating workflows in any programming language (Java, Python, JavaScript, C#, Go, Clojure), or even using a visual diagram editor. Learn more about how exactly system tasks make developing workflows so much faster in &lt;a href="https://dev.to/orkes/unlocking-developer-productivity-orchestrate-workflows-with-built-in-system-tasks-4hl8"&gt;Part 1&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://orkes.io/platform" rel="noopener noreferrer"&gt;Orkes Conductor&lt;/a&gt; is an enterprise-grade Unified Application Platform for process automation, API and microservices orchestration, agentic workflows, and more. Check out the &lt;a href="https://orkes.io/pricing" rel="noopener noreferrer"&gt;full set of features&lt;/a&gt;, or try it yourself using our free &lt;a href="https://developer.orkescloud.com/?utm_campaign=system-task-blog-2&amp;amp;utm_source=devto-blog&amp;amp;utm_medium=web" rel="noopener noreferrer"&gt;Developer Playground&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>orchestration</category>
      <category>productivity</category>
      <category>softwaredevelopment</category>
      <category>developer</category>
    </item>
    <item>
      <title>Unlocking Developer Productivity: Orchestrate Workflows with Built-in System Tasks</title>
      <dc:creator>Orkes Developers</dc:creator>
      <pubDate>Mon, 14 Apr 2025 11:20:55 +0000</pubDate>
      <link>https://dev.to/orkes/unlocking-developer-productivity-orchestrate-workflows-with-built-in-system-tasks-4hl8</link>
      <guid>https://dev.to/orkes/unlocking-developer-productivity-orchestrate-workflows-with-built-in-system-tasks-4hl8</guid>
      <description>&lt;p&gt;&lt;em&gt;This is Part 1 of the series on System Tasks. Check out &lt;a href="https://dev.to/orkes/implementing-easy-to-build-workflows-with-conductors-system-tasks-45ph"&gt;Part 2&lt;/a&gt;, which dives into all the use cases and implementation details for Conductor’s most popular system tasks.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;Orchestration is a powerful design framework for coordinating distributed services and systems into automated processes. Using a workflow engine, such as &lt;a href="https://orkes.io/platform" rel="noopener noreferrer"&gt;Orkes Conductor&lt;/a&gt;, provides a myriad of benefits like &lt;a href="https://dev.to/orkes/durable-execution-explained-how-conductor-delivers-resilient-systems-out-of-the-box-3i1p"&gt;durable executions&lt;/a&gt;, state tracking, and developer productivity. &lt;/p&gt;

&lt;p&gt;Orchestration-driven development can slash time-to-launch into half, especially when combined with built-in, reusable tasks for common cases, like calling an LLM, publishing events to a message broker, or even just calling an HTTP endpoint. Let’s dive deeper into Orkes Conductor’s system tasks and what makes them so powerful in unlocking developer productivity.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a workflow engine?
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;workflow engine&lt;/strong&gt; orchestrates complex processes by defining tasks in a declarative format (such as JSON). Unlike traditional in-code approaches, where developers handle retries, logging, and error management, workflow engines like Orkes Conductor automate task execution, abstracting these concerns.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftaa9dyucwhukenio67hn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftaa9dyucwhukenio67hn.png" alt="Code comparison of calling a HTTP task using traditional in-code vs Orkes Conductor SDK." width="800" height="608"&gt;&lt;/a&gt;Conductor abstracts away error management and plumbing code, making it effortless to build durable, stateful applications.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;How to write workflows using system tasks? Check out our &lt;a href="https://orkes.io/blog/using-system-tasks-in-conductor/" rel="noopener noreferrer"&gt;code implementation guide&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;A workflow engine decouples execution code from business logic. This yields two time-saving advantages: one, the business logic of tasks and workflows are now reusable, scalable, and more easily maintainable. Two, developers can focus on task dependencies without having to worry about resilience and execution guarantees, which are managed by the engine.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3g2j0o9txvfw6tcf0yc6.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3g2j0o9txvfw6tcf0yc6.jpg" alt="High-level diagram of orchestration pattern abstracting execution concerns from business logic." width="800" height="418"&gt;&lt;/a&gt;Clear separation of concerns: the workflow engine handles execution, error management, and state tracking; while the business logic resides in the tasks.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Interested to learn more about how Conductor works under the hood? Check out the in-depth blog on &lt;a href="https://dev.to/orkes/durable-execution-explained-how-conductor-delivers-resilient-systems-out-of-the-box-3i1p"&gt;durable execution&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;Over time, common patterns emerge across applications, like data transformation, webhook integrations, and HTTP calls. This is where &lt;strong&gt;system tasks&lt;/strong&gt; come in to automate business logic into reusable components, further speeding up development time for common use cases.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are system tasks?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;System tasks&lt;/strong&gt; in Orkes Conductor represent reusable business logic components that combine to form orchestration patterns. These tasks run within the engine, allowing developers to quickly build complex workflows without reinventing the wheel, leading to a flexible, maintainable automation process.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdkml6rkbglmgggg4o6qc.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdkml6rkbglmgggg4o6qc.jpg" alt="List of all system tasks in Orkes Conductor: Event, HTTP, HTTP Poll, Inline, JSON JQ Transform, Business Rule, Wait For Webhook, JDBC, Update Secret, Get Signed JWT, Update Task, Alerting Tasks, AI Tasks." width="800" height="418"&gt;&lt;/a&gt;All &lt;a href="https://orkes.io/content/category/reference-docs/system-tasks" rel="noopener noreferrer"&gt;system tasks&lt;/a&gt; in Orkes Conductor.&lt;/p&gt;

&lt;p&gt;When building workflows in Orkes Conductor, system tasks are your go-to tools for getting things done—fast. These are built-in, ready-to-use tasks that handle common operations like making HTTP calls, waiting for external events, or even running AI tasks一all without the need to write custom worker tasks. Since they run within Conductor’s JVM, system tasks help streamline development and remove the overhead of managing the custom infrastructure.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7olepcy1dc5we7ye3u5q.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7olepcy1dc5we7ye3u5q.jpg" alt="Architecture overview of system tasks vs worker tasks in Conductor." width="800" height="418"&gt;&lt;/a&gt;System tasks vs worker tasks in Conductor.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why use system tasks?
&lt;/h2&gt;

&lt;p&gt;System tasks bring clarity and consistency to workflows. Their standardized structure makes it easy to share, read, and reason about workflows across teams一no guesswork, no surprises.&lt;/p&gt;

&lt;p&gt;They also make complex operations easier to express, with less boilerplate. Since Conductor handles the execution, you get enterprise-grade resilience without lifting a single finger. With Conductor’s built-in monitoring and debugging tools, it’s easier to track failures, inspect state, and keep things running smoothly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Benefits
&lt;/h3&gt;

&lt;p&gt;System tasks offer a declarative, reliable way to build workflows. By abstracting common logic into reusable components, they reduce development effort, enhance clarity, and ensure consistent behavior—making them ideal for predictable, maintainable workflow design.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Time to Market&lt;/strong&gt;: Eliminate the need for custom code, accelerating development for tasks like HTTP calls, database updates, and event handling.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Standardization&lt;/strong&gt;: Offer consistency across workflows, making them easier to understand than custom worker task implementations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability&lt;/strong&gt;: Workflows using system tasks are inherently easier to scale, since execution is managed by Orkes Conductor itself.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What about custom business logic?
&lt;/h2&gt;

&lt;p&gt;Conductor offers all the benefits of workflow orchestration, even for custom business logic. This can be done through two approaches: &lt;strong&gt;Inline tasks&lt;/strong&gt; and &lt;strong&gt;Worker tasks&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Inline tasks let you execute lightweight JavaScript code directly within the workflow without the need for external workers. For more complex tasks, you can deploy custom worker tasks. Worker tasks provide full flexibility to implement advanced logic, such as API calls and long-running operations, while still benefiting from Conductor’s automated retries, status updates, and monitoring.&lt;/p&gt;

&lt;h3&gt;
  
  
  Inline task approach
&lt;/h3&gt;

&lt;p&gt;An &lt;strong&gt;Inline task&lt;/strong&gt; is a type of system task that allows you to execute custom JavaScript code directly within the workflow. It’s ideal for lightweight operations like simple data transformations, conditional checks, or small calculations. Inline tasks are executed within the Conductor JVM, which means they benefit from low latency, no network overhead, and easier debugging. &lt;/p&gt;

&lt;p&gt;Find out how to use Inline tasks in &lt;a href="https://dev.to/orkes/implementing-easy-to-build-workflows-with-conductors-system-tasks-45ph"&gt;Part Two of this blog series&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Features&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Executes directly within the Conductor JVM.&lt;/li&gt;
&lt;li&gt;Best for lightweight logic and transformations.&lt;/li&gt;
&lt;li&gt;No network calls or external dependencies.&lt;/li&gt;
&lt;li&gt;Easier to implement and debug but limited to JavaScript.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Worker task approach
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;Worker task&lt;/strong&gt; (also known as Simple task) is an external custom function or service that performs a specific task in a workflow. Written in any language of choice (Python, Java, etc.), it can execute complex business logic, custom algorithms, or long-running operations. Worker tasks run outside the Conductor server, meaning they require additional infrastructure set-up and logging mechanisms.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Features&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;External execution (outside the Conductor JVM).&lt;/li&gt;
&lt;li&gt;Full flexibility to implement complex logic.&lt;/li&gt;
&lt;li&gt;Requires task-level logging within the worker code.&lt;/li&gt;
&lt;li&gt;Typically involves network calls (e.g., HTTP requests).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  System tasks vs Worker tasks
&lt;/h2&gt;

&lt;p&gt;Both system tasks and Worker tasks offer different advantages, and the choice to use one over the other depends on your requirements. Here’s a comparison between the two.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;System tasks&lt;/th&gt;
&lt;th&gt;Worker tasks&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Advantages&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Speed&lt;/strong&gt;: System tasks run within the Conductor JVM, enabling fast, low-latency execution without network overhead, serialization processing, or external polling.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Availability Guarantees&lt;/strong&gt;: System tasks are always guaranteed to be available and operate within Conductor’s JVM.&lt;/li&gt;
&lt;/ul&gt;&lt;/td&gt;
&lt;td&gt;&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Full Control&lt;/strong&gt;: You can implement more complex or specialized logic that may not be easily achievable using system tasks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexibility&lt;/strong&gt;: Workers can be deployed, restarted, and updated independently from the workflow.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Decoupling&lt;/strong&gt;: Worker crashes are isolated and will not bring the entire system down.&lt;/li&gt;
&lt;/ul&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Trade-offs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tight Coupling&lt;/strong&gt;: System tasks are harder to scale, redeploy, or maintain independently.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Limited Customizability&lt;/strong&gt;: There is limited leeway for using custom libraries, frameworks, or stacks in system tasks.&lt;/li&gt;
&lt;/ul&gt;&lt;/td&gt;
&lt;td&gt;&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Increased Development Effort&lt;/strong&gt;: Customizing each worker adds development overhead for writing, testing, deploying, and maintaining more code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitoring &amp;amp; Debugging Complexity:&lt;/strong&gt; With workers, you need to implement your own task-level logging within the worker code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Infrastructure Overhead&lt;/strong&gt;: Workers rely on the availability and health of the external environment in which they're running, which has to be self-maintained.&lt;/li&gt;
&lt;/ul&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Wrap up
&lt;/h2&gt;

&lt;p&gt;Orkes Conductor is a workflow engine that offers the best of both worlds: low-code agility when you need to build out common use cases, and full customization control when you need to dive deep into building unique solutions. It’s a development platform made to empower developers in a fast-paced world. In &lt;a href="https://dev.to/orkes/implementing-easy-to-build-workflows-with-conductors-system-tasks-45ph"&gt;Part Two of this blog series&lt;/a&gt;, discover how to use system tasks in Conductor, as we spill the full implementation details. &lt;/p&gt;




&lt;p&gt;&lt;a href="https://orkes.io/platform" rel="noopener noreferrer"&gt;Orkes Conductor&lt;/a&gt; is an enterprise-grade Unified Application Platform for process automation, API and microservices orchestration, agentic workflows, and more. Check out the &lt;a href="https://orkes.io/pricing" rel="noopener noreferrer"&gt;full set of features&lt;/a&gt;, or try it yourself using our free &lt;a href="https://developer.orkescloud.com/?utm_campaign=system-task-blog-1&amp;amp;utm_source=devto-blog&amp;amp;utm_medium=web" rel="noopener noreferrer"&gt;Developer Playground&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>orchestration</category>
      <category>productivity</category>
      <category>softwaredevelopment</category>
      <category>developer</category>
    </item>
    <item>
      <title>Building Agentic Workflows with Conductor: Implementation Guide</title>
      <dc:creator>Orkes Developers</dc:creator>
      <pubDate>Thu, 10 Apr 2025 11:10:57 +0000</pubDate>
      <link>https://dev.to/orkes/building-agentic-workflows-with-conductor-implementation-guide-3hf1</link>
      <guid>https://dev.to/orkes/building-agentic-workflows-with-conductor-implementation-guide-3hf1</guid>
      <description>&lt;p&gt;By: Ram Durbha&lt;/p&gt;




&lt;p&gt;AI agents are autonomous, but unpredictable and difficult to thoroughly test and audit. How can we introduce governance into agentic systems? Simple: use agentic workflows. An &lt;a href="https://orkes.io/blog/what-are-agentic-workflows/" rel="noopener noreferrer"&gt;agentic workflow&lt;/a&gt; is a structured yet dynamic sequence of tasks, where the key decision-making points are executed by AI agents, with minimal human intervention.&lt;/p&gt;

&lt;p&gt;Agentic workflows combine the autonomy of AI agents with the traceability of workflows, bringing the best of both worlds. In highly regulated industries like finance, healthcare, and cybersecurity, agentic workflows provide a safer alternative to AI agents.&lt;/p&gt;

&lt;p&gt;In this article, let’s build an agentic workflow using Orkes Conductor, a modern platform for workflow orchestration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example: an agentic cybersecurity monitoring system
&lt;/h2&gt;

&lt;p&gt;In cybersecurity, alert fatigue can be catastrophic. The high-volume bombardment of alerts from multiple sources can lead to delays, missed responses, and ultimately, an increased risk of security breaches.&lt;/p&gt;

&lt;p&gt;Let’s build an agentic workflow to combat alert fatigue. This workflow should be able to reconstruct attack narratives from disparate sources of IOCs (indicators of compromise). Before we begin building in Conductor, let’s map out the requirements. The agentic cybersecurity process has to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Collect alerts from multiple sources&lt;/li&gt;
&lt;li&gt;Collate related events for reconstructing the chain of events&lt;/li&gt;
&lt;li&gt;Prioritize choose follow-up actions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In sum, the agentic system should help paint a picture of the patterns in how an attack developed over time across devices, users, and services so that human reviewers can allocate their energy to understanding and combating threats rather than drowning in alerts. Let’s use an LLM to provide a human-readable timeline of events that constitute a complex attack. &lt;/p&gt;

&lt;p&gt;Here’s the high-level flow of the agentic system on the left, and the actual workflow built in Orkes Conductor on the right:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuitegxxl5brxy4xnuu1t.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuitegxxl5brxy4xnuu1t.jpg" alt="High-level diagram of the agentic cybersecurity workflow vs the actual workflow diagram in Conductor." width="800" height="883"&gt;&lt;/a&gt;Orkes’ visual workflow editor makes it intuitive to transition from a napkin-top or whiteboard-sketch idea to a production-ready workflow.&lt;/p&gt;

&lt;p&gt;Now, here’s how you can create an agentic cybersecurity workflow on your own.&lt;/p&gt;

&lt;h3&gt;
  
  
  Getting started
&lt;/h3&gt;

&lt;p&gt;Before you begin, make sure you have the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An account on Orkes’ &lt;a href="https://developer.orkescloud.com/?utm_campaign=build-agentic-wf-blog&amp;amp;utm_source=devto-blog&amp;amp;utm_medium=web" rel="noopener noreferrer"&gt;Developer Playground&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;An &lt;a href="https://platform.openai.com/api-keys" rel="noopener noreferrer"&gt;OpenAI API key&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The resources to build the agentic cybersecurity workflow are located in this &lt;a href="https://github.com/conductor-oss/awesome-conductor-apps/tree/main/examples/agentic_security_workflow" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt;. Note that all the task workers are mocked in this workflow example but use representative schemas from real-world cyber security tools like those provided by Netscope and TrendMicro.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Import workflow definitions
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://github.com/conductor-oss/awesome-conductor-apps/tree/main/examples/agentic_security_workflow" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt; contains five workflows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Agentic_Security_Example&lt;/li&gt;
&lt;li&gt;Notify-Channels-x-mocked&lt;/li&gt;
&lt;li&gt;Security_get_device_id&lt;/li&gt;
&lt;li&gt;Vision_one_deep_visibility_hunt&lt;/li&gt;
&lt;li&gt;vision_one_device_scan&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For each workflow, copy the JSON definition from the repository and add it to your Orkes Developer Playground account in &lt;strong&gt;Definitions&lt;/strong&gt; &amp;gt; &lt;strong&gt;Workflow&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Configure the OpenAI integration
&lt;/h3&gt;

&lt;p&gt;We will be using OpenAI’s LLMs to power the AI and agentic components of the workflow. In the Developer Playground, go to &lt;strong&gt;Integrations&lt;/strong&gt; and add the OpenAI integration and models. For this workflow, you should add:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;gpt-4o (required)&lt;/li&gt;
&lt;li&gt;gpt-4o-mini (recommended)&lt;/li&gt;
&lt;li&gt;Any other &lt;a href="https://platform.openai.com/docs/models" rel="noopener noreferrer"&gt;OpenAI models&lt;/a&gt; you wish to use&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Repeat this procedure for other providers and models you want to use and compare.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Add the AI prompt
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://github.com/conductor-oss/awesome-conductor-apps/tree/main/examples/agentic_security_workflow" rel="noopener noreferrer"&gt;GitHub repository&lt;/a&gt; also contains the ​​llm_alert_analysis prompt, which analyzes the detected alerts to form an attack narrative. Copy its JSON definition from the repository and add it to your Developer Playground account in &lt;strong&gt;AI Prompts&lt;/strong&gt;. If you are using models other than gpt-4o, make sure to edit your AI prompt and workflow accordingly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Run the workflow
&lt;/h3&gt;

&lt;p&gt;Finally, with the workflow and supporting resources ready, let’s run it to see how it works. By default, the workflow comes baked with sample mock alerts, so it can be directly run without having to configure its inputs.&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;Definitions&lt;/strong&gt; &amp;gt; &lt;strong&gt;Workflow&lt;/strong&gt;, select the Agentic_Security_Example workflow and run it. As each task completes, you can review its output in real time. &lt;/p&gt;

&lt;h3&gt;
  
  
  Breaking down the workflow
&lt;/h3&gt;

&lt;p&gt;As we track the steps of the Agentic_Security_Example workflow, let's see how Orkes Conductor makes it easy to map the needs of our solution to actual tasks and design patterns:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo6fecso6339dc6xl6b53.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo6fecso6339dc6xl6b53.jpg" alt="Infographic of the cybersecurity flow across Conductor features: Parallel Alert Ingestion, Alert Processing, AI-Powered Analysis, Dynamic Follow-Up Actions, and Scalable Remediation." width="800" height="418"&gt;&lt;/a&gt;Conductor's suite of features makes it seamless to build agentic workflows.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Parallel Alert Ingestion:&lt;/strong&gt; 
The workflow starts by concurrently fetching malware and malsite alerts using a Fork/Join task, which is Conductor's built-in task for handling parallel data processing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Alert Processing:&lt;/strong&gt; 
Once the raw alert data is ingested, the workflow extracts relevant details from both malware and malsite alerts using JSON JQ Transform tasks. These tasks parse and filter the data, ensuring that only meaningful alert information is passed on in a structured manner for efficient downstream analysis and decision-making.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI-Powered Analysis:&lt;/strong&gt; 
The intelligence core lies in the llm_alert_analysis task, which utilizes Conductor's LLM Text Complete task to send the raw alert data to an LLM (like gpt-4o-mini). The LLM, guided by a sophisticated prompt, analyzes the alerts for threat classification, correlation, context, and risk assessment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic Follow-Up Actions:&lt;/strong&gt; 
Based on the LLM's output, a Switch task directs the workflow to initiate follow-up actions only if a deep scan is deemed necessary. This demonstrates the agentic nature of the workflow, where the AI's analysis directly influences the subsequent flow of control.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalable Remediation:&lt;/strong&gt; 
The workflow then uses Dynamic Fork tasks to initiate deep visibility threat hunts and device scans on all potentially affected devices identified by the LLM. This highlights Conductor's ability to scale the response based on the AI's findings.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Notification and Reporting:&lt;/strong&gt; 
Finally, the workflow generates a summary and sends notifications through a sub-workflow, ensuring that security teams are informed of the intelligent analysis and any initiated actions.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Going beyond&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now that you know how the workflow works, you can customize it for your own use case. Tweak it, replace the mocks with real data sources, or try creating your own agentic systems in &lt;a href="https://orkes.io/platform" rel="noopener noreferrer"&gt;Orkes Conductor&lt;/a&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  Advantages of Orkes Conductor for agentic workflows
&lt;/h2&gt;

&lt;p&gt;Orkes Conductor offers several key advantages that make it particularly well-suited for building agentic workflows.  It provides all the necessary building blocks and orchestration capabilities to create sophisticated agentic workflows.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Native LLM integration with LLM Text Complete Task:&lt;/strong&gt; 
Conductor provides a dedicated LLM Text Complete task that simplifies the integration with various LLM providers like OpenAI. This built-in functionality eliminates the need for complex custom integrations and allows developers to seamlessly incorporate AI-powered text analysis and generation into their workflows. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Text Complete task is just one of the many &lt;a href="https://orkes.io/content/category/reference-docs/ai-tasks" rel="noopener noreferrer"&gt;system LLM tasks&lt;/a&gt; provided in Conductor. The flexibility to choose from these system tasks, built and thoroughly tested for AI use cases, makes it easy to prototype and scale to production.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Dynamic task creation with Dynamic Forks:&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For agentic workflows that need to take action based on AI insights, Conductor's Dynamic Fork task is invaluable. It allows the workflow to dynamically create and manage parallel tasks based on the output of previous steps, like the LLM's analysis output in the cybersecurity example. This is crucial for scenarios like initiating scans on multiple affected devices identified by the AI.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Robust workflow versioning:&lt;/strong&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Building intelligent agents often involves experimentation and iteration. Conductor's robust workflow versioning and management capabilities allow teams to track changes, roll back to previous versions, and maintain complex agentic workflows effectively over time.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scalability and reliability for critical operations:&lt;/strong&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Conductor is designed for high-throughput and mission-critical applications. Its architecture ensures the scalability and reliability needed to power agents that operate continuously and handle potentially large volumes of data and events. This is enhanced further by the suite of Security, Governance and Auditing capabilities like &lt;a href="https://www.orkes.io/content/category/access-control-and-security" rel="noopener noreferrer"&gt;RBAC&lt;/a&gt;, Open Telemetry and &lt;a href="https://www.orkes.io/content/developer-guides/metrics-and-observability" rel="noopener noreferrer"&gt;Grafana&lt;/a&gt; support.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Flexibility and extensibility:&lt;/strong&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Conductor's open architecture enables easy integration with a wide range of tools and systems through its various task types (HTTP, Sub Workflow, Event, and more) and ability to execute custom code. This flexibility is essential for building agentic workflows that interact with diverse security ecosystems.  Simple workers allow for complex logic, while Inline tasks and JSON JQ Transform tasks allow for well-organized, clean glue code.&lt;/p&gt;

&lt;p&gt;Orkes Conductor is a robust and developer-friendly platform made for building and managing the complexities of agentic workflows. Its architecture and features make it ideal for orchestrating complex processes involving AI-driven decision-making.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;Agentic workflows, driven by the reasoning and language processing abilities of LLMs, offer a significant leap forward compared to traditional, static workflows. By integrating LLMs into automated processes, systems can be built to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Intelligently analyze and correlate diverse sources of information:&lt;/strong&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;LLMs can process and understand natural language descriptions from various sources, enabling sophisticated correlation based on semantic understanding rather than just pattern matching.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Provide rich contextual analysis:&lt;/strong&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;LLMs can leverage their vast knowledge base to provide context around the input content.  More importantly, Conductor makes it easier to provide the LLM with additional context through built-in AI Prompts, which can be crafted with placeholder variables that are dynamically replaced during a workflow run.&lt;/p&gt;

&lt;p&gt;In the above example, LLMs are used to provide context on detected threats, including information on malware families, attack vectors, and potential impact.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Dynamically adapt to current circumstances:&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Agentic workflows enable dynamic decision-making, as shown above, providing automatic adaption to macro and micro changes.&lt;/p&gt;

&lt;p&gt;With dozens of one-click-switch AI/LLM integrations, input/output schema enforcement, native human-in-the-loop features, and enterprise RBAC controls, you can seamlessly build agentic workflows in &lt;a href="https://orkes.io/platform" rel="noopener noreferrer"&gt;Orkes Conductor&lt;/a&gt; for any enterprise use case. &lt;/p&gt;

&lt;p&gt;Stay tuned for more agentic examples and tutorials. In the meantime, check out &lt;a href="https://github.com/conductor-oss/awesome-conductor-apps/tree/main" rel="noopener noreferrer"&gt;Conductor’s Examples repository&lt;/a&gt; for other projects or get hands-on with our free &lt;a href="https://developer.orkescloud.com/?utm_campaign=build-agentic-wf-blog&amp;amp;utm_source=devto-blog&amp;amp;utm_medium=web" rel="noopener noreferrer"&gt;Developer Playground&lt;/a&gt;. As always, join the &lt;a href="https://orkes-conductor.slack.com/join/shared_invite/zt-2vdbx239s-Eacdyqya9giNLHfrCavfaA#/shared-invite/email" rel="noopener noreferrer"&gt;Slack community&lt;/a&gt; to connect with fellow developers and the Conductor team.&lt;/p&gt;

</description>
      <category>agentic</category>
      <category>agenticworkflows</category>
      <category>orchestration</category>
      <category>ai</category>
    </item>
    <item>
      <title>Orchestrating Long-Running APIs | A Step-by-Step Guide to Asynchronous Execution</title>
      <dc:creator>Orkes Developers</dc:creator>
      <pubDate>Fri, 04 Apr 2025 15:04:37 +0000</pubDate>
      <link>https://dev.to/orkes/orchestrating-long-running-apis-a-step-by-step-guide-to-asynchronous-execution-4n9c</link>
      <guid>https://dev.to/orkes/orchestrating-long-running-apis-a-step-by-step-guide-to-asynchronous-execution-4n9c</guid>
      <description>&lt;p&gt;Handling &lt;strong&gt;long-running APIs&lt;/strong&gt; is a common challenge in modern applications. Whether you’re processing large datasets, generating reports, or interacting with third-party services, some API calls exceed the 30–60 second timeout window allowed by most systems. When an API takes too long to respond, workflows can break—resulting in failed tasks, degraded user experiences, or unnecessary retries.&lt;/p&gt;

&lt;p&gt;To address this, we’ll implement a solution using &lt;a href="https://orkes.io/blog/orchestrating-asynchronous-workflow/" rel="noopener noreferrer"&gt;asynchronous orchestration&lt;/a&gt;. Instead of waiting for the long-running task to complete, the workflow triggers it asynchronously, stores its progress in an external database, and uses polling to track its status until completion.&lt;/p&gt;

&lt;p&gt;In this blog, we’ll walk through a scalable solution using &lt;strong&gt;Orkes Conductor&lt;/strong&gt;—a Unified Application Platform—along with &lt;strong&gt;AWS Lambda&lt;/strong&gt;, &lt;strong&gt;Amazon API Gateway&lt;/strong&gt;, and &lt;strong&gt;Amazon DynamoDB&lt;/strong&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  Why are long-running APIs difficult?
&lt;/h2&gt;

&lt;p&gt;APIs that take several minutes to complete are not uncommon, especially in systems that rely on compute-heavy workloads or external services. However, traditional synchronous API calls aren’t equipped to handle extended processing delays.&lt;/p&gt;

&lt;p&gt;Let’s consider a simple HTTP task in Orkes Conductor or any workflow engine. These tasks typically expect a response within a certain timeout window (e.g., 60 seconds). If the external API takes longer than that, the task fails. This limitation affects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;User-facing features&lt;/strong&gt;–UI elements may hang or fail without feedback.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;System performance&lt;/strong&gt;–Workflow fails, and retries kick in, increasing the load on compute resources and downstream services.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Observability&lt;/strong&gt;–There’s no clear visibility into the task’s state if the response never arrives.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Stretching timeout windows or blocking workflows isn’t a scalable solution. A better approach is a more resilient workflow architecture pattern—one that embraces asynchronous execution and decouples task initiation from task completion.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution: Use asynchronous HTTP invocation with polling
&lt;/h2&gt;

&lt;p&gt;To reliably handle long-running APIs, we’ll implement an &lt;strong&gt;asynchronous invocation with a polling&lt;/strong&gt; pattern using Orkes Conductor and AWS services. This avoids timeouts while maintaining full control and visibility over the process. &lt;/p&gt;

&lt;p&gt;At a high level, the pattern involves:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Triggering the long-running task asynchronously&lt;/li&gt;
&lt;li&gt;Tracking its execution state in an external store&lt;/li&gt;
&lt;li&gt;Polling the task status until it is completed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwh56mfv7egmcmx2h2wfz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwh56mfv7egmcmx2h2wfz.png" alt="Architecture for implementing synchronous HTTP invocation with polling" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;
Implementing asynchronous HTTP invocation with polling



&lt;p&gt;We’ll implement this orchestration pattern using:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://aws.amazon.com/pm/lambda/" rel="noopener noreferrer"&gt;AWS Lambda&lt;/a&gt;&lt;/strong&gt;–A serverless computing service that simulates the long-running task.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://aws.amazon.com/dynamodb/" rel="noopener noreferrer"&gt;Amazon DynamoDB&lt;/a&gt;&lt;/strong&gt;–A NoSQL database to store and track the status of each request.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://aws.amazon.com/api-gateway/" rel="noopener noreferrer"&gt;Amazon API Gateway&lt;/a&gt;&lt;/strong&gt;–A REST API layer to expose Lambda endpoints for invocation and polling.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://orkes.io/platform" rel="noopener noreferrer"&gt;Orkes Conductor&lt;/a&gt;&lt;/strong&gt;–The orchestration platform that orchestrates the asynchronous flow.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  How Asynchronous Orchestration Works
&lt;/h3&gt;

&lt;p&gt;The core idea behind this pattern is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Trigger the long-running task asynchronously&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The workflow initiates the long-running process using an HTTP task configured to perform a non-blocking request (e.g., invoking a Lambda function asynchronously via API Gateway). The task immediately returns a &lt;code&gt;requestId&lt;/code&gt;, which is used as a unique reference for tracking progress.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Track task progress externally&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The Lambda function logs the execution state (e.g., PROCESSING or COMPLETED) in a NoSQL database like &lt;strong&gt;Amazon DynamoDB&lt;/strong&gt;, which serves as a persistent data store for tracking task progress externally.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Poll the task status until completion&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Conductor workflow periodically queries the status of the request using an HTTP Poll task. The polling continues until the task is marked as completed in the external system.&lt;/p&gt;

&lt;p&gt;This model allows the workflow to remain active and aware of the task’s progress without exceeding timeout thresholds or blocking system resources.&lt;/p&gt;

&lt;p&gt;Now that we understand the pattern conceptually, let’s walk through how to implement this using Orkes Conductor and AWS services.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building a long-running API workflow
&lt;/h2&gt;

&lt;p&gt;In this section, we’ll implement the long-running API orchestration pattern using Orkes Conductor. To follow along, sign in to the free &lt;a href="https://developer.orkescloud.com/?utm_campaign=long-running-apis-blog&amp;amp;utm_source=devto-blog&amp;amp;utm_medium=web" rel="noopener noreferrer"&gt;Developer Playground&lt;/a&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  Part 1: Set up AWS resources
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Step 1: Create an Amazon DynamoDB table for status tracking
&lt;/h4&gt;

&lt;p&gt;Start by &lt;a href="https://orkes.io/content/tutorials/long-running-apis#step-1-create-an-amazon-dynamodb-table-to-track-task-status" rel="noopener noreferrer"&gt;creating a table&lt;/a&gt; in DynamoDB named &lt;code&gt;lambda-invocation-status&lt;/code&gt; with &lt;code&gt;requestId&lt;/code&gt; as the partition key.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa8r48osv5wj6hkedir4g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa8r48osv5wj6hkedir4g.png" alt="Creating table in Amazon DynamoDB" width="800" height="356"&gt;&lt;/a&gt;&lt;/p&gt;
Creating a table in Amazon DynamoDB



&lt;p&gt;This table stores the execution status of each request.&lt;/p&gt;

&lt;h4&gt;
  
  
  Step 2: Set up a long-running task in AWS Lambda
&lt;/h4&gt;

&lt;p&gt;Next, we’ll create a Lambda function that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Accepts a &lt;code&gt;requestId&lt;/code&gt; and an &lt;code&gt;action&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Simulates a long-running task&lt;/li&gt;
&lt;li&gt;Updates the task’s status in DynamoDB&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://orkes.io/content/tutorials/long-running-apis#step-2-set-up-a-long-running-task-in-aws-lambda" rel="noopener noreferrer"&gt;Create an AWS Lambda function&lt;/a&gt; using the Python code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import json
import time
import boto3

dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('lambda-invocation-status')

def lambda_handler(event, context):
    request_id = event['requestId']
    action = event.get("action")

    if action == "invoke":
        table.put_item(Item={'requestId': request_id, 'status': 'PROCESSING'})

        # Simulate long processing time
        time.sleep(2)
        process_long_running_task(request_id)

        return {
            "statusCode": 202,
            "body": json.dumps({"requestId": request_id, "status": "PROCESSING"})
        }

    elif action == "status":
        response = table.get_item(Key={'requestId': request_id})
        item = response.get('Item')
        if item:
            return {"statusCode": 200, "body": json.dumps(item)}
        else:
            return {"statusCode": 404, "body": json.dumps({"status": "NOT_FOUND"})}

def process_long_running_task(request_id):
    time.sleep(25)  # Simulate processing time
    table.update_item(
        Key={'requestId': request_id},
        UpdateExpression='SET #s = :val',
        ExpressionAttributeNames={'#s': 'status'},
        ExpressionAttributeValues={':val': 'COMPLETED'}
    )
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Adjust the Lambda timeout to &lt;strong&gt;1 minute&lt;/strong&gt; and attach an IAM role with complete access to DynamoDB.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3q2ga698txs0kyi7vhlk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3q2ga698txs0kyi7vhlk.png" alt="Creating a Lambda function in Python" width="800" height="390"&gt;&lt;/a&gt;&lt;/p&gt;
Creating an AWS Lambda function



&lt;h4&gt;
  
  
  Step 3: Set up API Gateway endpoints
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://orkes.io/content/tutorials/long-running-apis#step-3-set-up-api-gateway-endpoints" rel="noopener noreferrer"&gt;Create a REST API in Amazon API Gateway&lt;/a&gt; and expose the Lambda function with two endpoints:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;POST /invoke-lambda&lt;/strong&gt;–Triggers the task.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0hji792t3fnoao9rtxcm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0hji792t3fnoao9rtxcm.png" alt="API for invoking Lambda function" width="800" height="343"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GET /{requestId}&lt;/strong&gt;–Returns the current task status.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fafdt6ersakuw8lbxoxea.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fafdt6ersakuw8lbxoxea.png" alt="API for getting the long running API task status" width="800" height="616"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Deploy the API and note the endpoint URL—they’ll be used in the workflow definition.&lt;/p&gt;

&lt;h3&gt;
  
  
  Part 2: Build the Orkes Conductor workflow
&lt;/h3&gt;

&lt;p&gt;With your AWS resources ready, it’s time to orchestrate the flow in Orkes Conductor. Let’s build a workflow that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Invokes the Lambda function using an HTTP task.&lt;/li&gt;
&lt;li&gt;Polls the status endpoint until the task is completed using the HTTP Poll task.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Step 1: Invoke Lambda asynchronously
&lt;/h4&gt;

&lt;p&gt;Use an &lt;a href="https://orkes.io/content/reference-docs/system-tasks/http" rel="noopener noreferrer"&gt;HTTP task&lt;/a&gt; in Conductor to call the Lambda endpoint via API Gateway, passing a &lt;code&gt;requestId&lt;/code&gt; in the body. The Lambda will start the task and return a 202 response.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4sppq2kla4hpps5p4wpn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4sppq2kla4hpps5p4wpn.png" alt="Calling Lambda endpoint using HTTP task in Orkes Conductor" width="800" height="402"&gt;&lt;/a&gt;&lt;/p&gt;
Calling Lambda endpoint using HTTP task



&lt;h4&gt;
  
  
  Step 2: Poll for task completion
&lt;/h4&gt;

&lt;p&gt;Use an &lt;a href="https://orkes.io/content/reference-docs/system-tasks/http-poll" rel="noopener noreferrer"&gt;HTTP Poll task&lt;/a&gt; to query the status endpoint at regular intervals. The polling continues until the external system returns a "COMPLETED" status.&lt;/p&gt;

&lt;p&gt;This behavior is configured using the following termination condition in the HTTP Poll task:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(function(){
  return $.output.response.statusCode == 200 &amp;amp;&amp;amp;
         $.output.response.body.body.status == "COMPLETED";
})();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fagueaq98z9bwe2abi9xs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fagueaq98z9bwe2abi9xs.png" alt="Querying long running task status at regular intervals using HTTP Poll task in Orkes Conductor" width="800" height="402"&gt;&lt;/a&gt;&lt;/p&gt;
Querying long running task status at regular intervals using HTTP Poll task



&lt;h4&gt;
  
  
  Creating Conductor Workflow
&lt;/h4&gt;

&lt;p&gt;Create a workflow in Developer Playground by navigating to &lt;a href="https://developer.orkescloud.com/workflowDef" rel="noopener noreferrer"&gt;&lt;strong&gt;Definitions&lt;/strong&gt; &amp;gt; &lt;strong&gt;Workflow&lt;/strong&gt;&lt;/a&gt;. In the Code tab, paste the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
 "name": "LongRunningAPIWorkflow",
 "description": "Sample workflow",
 "version": 1,
 "tasks": [
   {
     "name": "InvokeLambdaTask",
     "taskReferenceName": "invokeLambda",
     "inputParameters": {
       "http_request": {
         "uri": "https://&amp;lt;your-api-gateway-id&amp;gt;.execute-api.&amp;lt;your-region&amp;gt;.amazonaws.com/test/invoke-lambda",
         "method": "POST",
         "headers": {
           "Content-Type": "application/json",
           "X-Amz-Invocation-Type": "Event"
         },
         "body": {
           "requestId": "${workflow.input.requestId}"
         },
         "accept": "application/json",
         "contentType": "application/json"
       }
     },
     "type": "HTTP"
   },
   {
     "name": "http_poll",
     "taskReferenceName": "http_poll_ref",
     "inputParameters": {
       "http_request": {
         "uri": "https://&amp;lt;your-api-gateway-id&amp;gt;.execute-api.&amp;lt;your-region&amp;gt;.amazonaws.com/test/${workflow.input.requestId}",
         "method": "GET",
         "accept": "application/json",
         "contentType": "application/json",
         "terminationCondition": "(function(){ return $.output.response.statusCode == 200 &amp;amp;&amp;amp; $.output.response.body.body.status == \"COMPLETED\";})();",
         "pollingInterval": "10",
         "pollingStrategy": "FIXED",
         "encode": true
       }
     },
     "type": "HTTP_POLL"
   }
 ],
 "inputParameters": [
   "requestId"
 ],
 "schemaVersion": 2
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your workflow will look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqhskms83p4d25ypepgvm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqhskms83p4d25ypepgvm.png" alt="Long Running API workflow" width="800" height="956"&gt;&lt;/a&gt;&lt;/p&gt;
Long Running API workflow in Orkes Conductor



&lt;p&gt;Before running the workflow, update the URLs in your task definitions with your actual deployed API Gateway endpoints.&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;InvokeLambdaTask&lt;/strong&gt; (HTTP task), replace the URL with your deployed API endpoint for invoking the Lambda:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://&amp;lt;your-api-gateway-id&amp;gt;.execute-api.&amp;lt;your-region&amp;gt;.amazonaws.com/&amp;lt;stage&amp;gt;/invoke-lambda
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the &lt;strong&gt;http_poll&lt;/strong&gt; task, replace the polling URL with the endpoint for checking Lambda status:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://&amp;lt;your-api-gateway-id&amp;gt;.execute-api.&amp;lt;your-region&amp;gt;.amazonaws.com/&amp;lt;stage&amp;gt;/${workflow.input.requestId}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once configured, test the workflow with a sample input:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "requestId": "12345"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;requestId&lt;/code&gt; serves as a unique identifier for each task instance. It is passed into the workflow, forwarded to the Lambda function, and used to poll the task’s status from DynamoDB.&lt;/p&gt;

&lt;p&gt;When the workflow is run, the &lt;strong&gt;InvokeLambdaTask&lt;/strong&gt; triggers the Lambda function. The &lt;strong&gt;http_poll&lt;/strong&gt; task continuously checks the status until it is completed. &lt;/p&gt;

&lt;p&gt;Congratulations—&lt;strong&gt;you’ve successfully orchestrated a long-running API using Orkes Conductor and AWS&lt;/strong&gt;. For a complete implementation walkthrough, refer to the &lt;a href="https://orkes.io/content/tutorials/long-running-apis" rel="noopener noreferrer"&gt;tutorial on orchestrating long-running APIs&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Long-running APIs can easily break synchronous workflows, but with exemplary architecture, you can handle them reliably and at scale. &lt;/p&gt;

&lt;p&gt;By combining asynchronous invocation, external status tracking, and polling using Orkes Conductor, you can build resilient and timeout-proof workflows. This pattern can be adapted for a wide range of real-world scenarios, from third-party service orchestration to internal background processing. &lt;/p&gt;

&lt;p&gt;Ready to build scalable workflows that can handle long-running operations without breaking? Try out using Orkes Conductor.&lt;/p&gt;

&lt;p&gt;–&lt;/p&gt;

&lt;p&gt;&lt;a href="https://orkes.io/platform" rel="noopener noreferrer"&gt;Orkes Conductor&lt;/a&gt; is an enterprise-grade Unified Application Platform for process automation, API and microservices orchestration, agentic workflows, and more. Check out the &lt;a href="https://orkes.io/pricing" rel="noopener noreferrer"&gt;full set of features&lt;/a&gt;, or try it yourself using our free &lt;a href="https://developer.orkescloud.com/?utm_campaign=long-running-apis-blog&amp;amp;utm_source=devto-blog&amp;amp;utm_medium=web" rel="noopener noreferrer"&gt;Developer Playground&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>orchestration</category>
      <category>api</category>
      <category>asynchronous</category>
      <category>microservices</category>
    </item>
  </channel>
</rss>
