build-action-flows

Configure Action Flows

21 páginasver na Celonis Academy

Tuning the Instruments [03:00]

Welcome!

Welcome to Configuring Action Flows! If you’ve already built a basic Action Flow, you know the thrill of seeing a "Success" message in your execution history. Now, it’s time to move beyond the basics and master the advanced logic required for professional-grade automations.

In this course, we move from simple, linear "Point A to Point B" connections to multidimensional flows. You will learn how to handle complex data scenarios, transform information on the fly, and ensure your flows are robust enough to handle real-world irregularities.

Course Overview

We will explore the tools that give you full control over how data moves through Celonis, allowing you to build intelligent and flexible Action Flows.

By the end of this course, you’ll be able to:

Build Decision Logic: Use Routers and Filters to create "logical forks" in the road, allowing your flow to take different actions based on the data it finds. Master Data Transformation: Use Functions to clean, format, and calculate data (like changing date formats or modifying text) directly within your modules. Design for Resilience: Use foundational techniques to ensure your flows handle missing or unexpected data gracefully. Expand your Connectivity: Discover how to interact with external services and APIs to bring more power to your automations.

Prerequisites

To get the most out of these lessons, you should be comfortable with the Celonis Studio interface, basic module mapping, and the concept of data pills.

If this is news to you, please consider taking the following courses first:

Introduction to Celonis Studio

Introduction to Studio Assets

Introduction to Action Flows

All set? Then let's go!

Prepare your Training Team

Next Lesson Prepare your Training Team

To follow along with the exercises in this course, you will need to access to a central Training Team environment. This is a workspace where you can build and test advanced logic safely.

Add me or check my access

Create your Course package

Staying organized is key when building complex automations. If you have taken the "Introduction to Action Flows" course before, you can simply reuse or duplicate your already existing package and Action Flow - more on how we're going to evolve it later.

Otherwise, please make sure you have a dedicated package (optionally a space) ready in Celonis Studio.

Pro-Tip: Using a clear naming convention now makes it much easier to locate your assets as your library of Action Flows grows.

---

Recap (optional) [06:30]

Action Flows vs. Process Orchestrations

As you explore the Celonis Platform, you will encounter two primary ways to drive action: Action Flows and the Orchestration Engine (referred to in Studio as a Process Orchestration asset). While they often work together, they serve different purposes.

The easiest way to understand the difference is through the analogy of an Orchestra 🎷:

TOPIC ACTION FLOW PROCESS ORCHESTRATION Analogy

The Musician

Think of an Action Flow as a specialized musician. A violinist is an expert at one specific task: playing the violin. They are fast, precise, and transactional.

The Conductor

The Orchestration Engine (or Process Orchestration asset in Studio) is the Conductor. The Conductor doesn’t play an instrument; instead, they manage the entire performance. They know which musician should play and when.

State

Stateless

When the song ends, the musician doesn't need to "remember" the notes to perform the next task.

Stateful

The Conductor must remember the "state" of the entire symphony - where we are in the music and what happens next.

Focus

Action Flows are built for Task Automation. They execute a specific system update or notification in seconds and then finish their job.

The Orchestration Engine is built, as the name implies, for Process Orchestration. It manages long-running processes that span days or weeks, coordinating multiple Action Flows and human tasks over time.

While it is important to understand how these two engines complement each other, this course focuses exclusively on Action Flows. If you are completing this as part of the "Build Action Flows" training track, you will find a deeper dive into the relationship between these assets in a later asset.

If you're eager to learn all the details about the "Conductor", you can explore the "Orchestration Engine Fundamentals" course in the Academy at any time.

Action Flow Configuration Basics

Before we dive into advanced logic, let’s quickly revisit the fundamental building blocks of an Action Flow. Professional configuration starts with a solid understanding of how data moves from the starting signal to the final output.

The Core Components Recap

Every Action Flow is built on three essential elements:

The Trigger: This is the starting signal. Whether it is a Schedule (running at specific times) or a Webhook (reacting to a specific event), the trigger defines when the flow begins. Modules: These are the individual steps in your Action Flow. Each module performs a specific task, such as fetching data from an app, processing text with AI, or sending a notification. Connections: The secure "bridge" (using API keys or OAuth) that allows Celonis to communicate with your external applications like Outlook, Slack, or Jira.

The Flow of Data

The intelligence of your flow depends on how you move data between these components:

Mapping: This is the process of connecting the output of one module to the input of another. Data Pills: These represent individual pieces of information (like an Order ID or a Customer Email) that you drag and drop into module fields. Bundles: Data is processed in "bundles." If a trigger finds multiple items, the flow will process each bundle through the subsequent modules individually.

Moving Beyond Linear Paths

So far, you’ve likely built Linear Flows - where every step follows a straight line. In this course, we are going to break that line. We will introduce Advanced Logic that allows the flow to evaluate data, transform it on the fly, and decide which path to take based on specific conditions.

Evolving the Sports Consultant

In the Introduction to Action Flows course, we built a Sports Consultant: a simple, linear flow that fetched the weather for a specific city and used AI to recommend whether it was a good day for doing sports outside.

The New Mission: Introducing the Rest Day

Professional athletes know that recovery is just as important as the workout. For our project, we are introducing a new rule: Mondays are Rest Days 🛋️

Our flow needs to evolve from a simple linear sequence into an intelligent system that makes a decision based on the day of the week:

On Training Days (Tuesday-Sunday): The flow should continue to fetch the weather and provide a sports recommendation. On Rest Days (Monday): The flow should bypass the weather entirely. Instead, it will connect to an open API to retrieve a recipe for a healthy, non-alcoholic drink to help us recover.

To achieve this, we are going to break the "straight line" of our original flow by introducing Routers and Filters.

New to this project? Use the Blueprint!

If you didn't build the original Action Flow (as we did in the course Introduction to Action Flows) or want to ensure your starting point is clean, you can use the Course Blueprint to bring the base logic onto your canvas.

How to upload and configure the Blueprint: Download the "Sports_Consultant_Base.json" file (if the link doesn't work, you find it in the course resources). Create a New Flow: In your Studio Package, create a new Action Flow and give it a name of your choice (e.g., Sports Consultant). Import Blueprint: Find the option to import a blueprint in the top menu bar. Choose the JSON that you've just downloaded. Update Connections: Look for modules with red warning icons. Click into them and select your existing connections (Weather, AI, and Email) to re-establish the link. Save & Run: Click the Save icon. Hit the Run button to make sure everything's working fine.

Note that the blueprint does not contain the Error Handling Route to keep things a little cleaner.

With our Rest Day strategy in place, we are ready to move from theory to implementation. Our first task is to teach the flow to distinguish between a training day and a recovery day (or: Mondays vs. all other days of the week). In the next chapter, we will introduce the Router - the central traffic controller of your Action Flow - and use Filters to ensure our data always takes the correct path based on the day of the week.

---

Add Routers and Filters to an Action Flow [09:00]

Add and Connect a Router Module

In our original Sports Consultant flow, the Weather module was the first step. To build a more intelligent system, we need to change that. We will now place a Router at the very beginning of our flow so that the first thing Celonis does is decide which path to follow.

Adding the Router as the first Module

There are two ways to add the Router:

Click the green Tools icon in the bottom menu and select Router, or Right-click into the canvas and select Add a module. Then add the Router. Drag the clock icon from the Weather module and drop it on the Router module. This marks the Router as the starting module. Now, connect the router module and the Weather module, establishing the connection from the Weather module. Optionally, if your flow now looks a little "messy", click the Auto-Align button in the top menu bar.

Building the Branch Architecture

Now that the Router is the head of the flow, we need to create our two different paths:

The Training Path: Our current path, including the Weather. This path will eventually be filtered to run on Tuesday through Sunday. The Rest Day Path: Click the center of the Router to create a second branch. At the end of this new path, add another Email module. Specify the connection you've used before and add your email address and a subject (e.g., "Try this drink recipe today!"). Leave the body empty for now.

Your canvas should now show a clear "Y-shape" split. The Router sits at the far left, with one path leading to your existing weather and AI logic, and a second path leading to your new email module.

Architect's Note: By making the Router the first module, you ensure that no "operations" (like fetching weather data) are wasted if the condition for that path isn't met. The flow makes the decision first, then executes the work.

Tip: You now see two email modules in your Action Flow. As a best practice, it is common to rename the modules to clearly distinguish their purpose at a glance. To do so, just right-click the respective module and select "Rename".

Adding Filters and Conditions

Next Lesson Adding Filters and Conditions

Did you already give it a try and run the new version of the flow? If not, go ahead and try! Watch your inbox to see what's happening…

… exactly! You're receiving two emails, one for each path available. This is how routing works if you don't add filters and conditions to it.

A filter sits on the connecting line between the Router and the next module, acting as a gatekeeper that only opens if specific conditions are met.

Setting the Training Day Filter

First, let’s ensure the Weather path only runs from Tuesday to Sunday.

To add a filter to this route, simply right-click the dotted line between the modules and click Set up a filter. This opens the filter configuration screen.

Label: The label is, as the name suggests, a visual cue on your flow that describes under which conditions this route is executed. We can, for example, call it Training Days, or, to be more precise Training Days (Tue - Sun). Fallback route: Based on the definition of fallback routes in the editor, we can keep the default setting, i.e., “No”. Condition: The condition consists of multiple elements: the incoming value, the operator, and the criterion to be fulfilled. We basically want to ensure that the current day is not "Monday". We, therefore, need a Text Operator, and select the one that says Not equal to. For the condition, we simply add Monday.

What is still missing is identifying the current workday. And this is where something else comes into play: Functions, more precisely Date and Time functions. Let's give you some time to experiment a bit on your own! We give you a tip, though:

What you need are the formatDate and the now functions… Good luck!

Solution: Define Filter Condition

Granted, this was a bit of a tricky one since you need to know about the so-called "Date Tokens" that can be leveraged in the formatDate function. You can find a full list of tokens for date/time parsing here. The token we need for the full name of the weekday is dddd.

Therefore, the complete and correct condition is:

👉 With our condition set, give the Action Flow another run. Depending on the day that you're taking this course, what do you notice? Anything expected or also unexpected?

If it is any day other than a Monday that you are taking this course, both routes are likely still executed. And that makes sense: The upper route's condition is fulfilled, but the lower route is also still executed since no condition or filter are yet defined for it.

👉 Go ahead and add a "gatekeeper" for that lower route!

Solution: Add a Filter and Condition for Rest Days

Adding the filter for rest days works analogously to the training days. All you need to change is the operator, which ideally now says "Equal to".

Note that you can combine multiple filter conditions by adding either an AND-type or OR-type rule!

---

Working with Arrays and Collections [28:00]

Make a Get Request via the HTTP Module

Now that our flow can distinguish between a training day and a rest day, it’s time to give our "Rest Day" path some actual purpose. Instead of an empty email, we want to provide a refreshing, non-alcoholic drink recipe to try out.

Instead of doing an online search for a recipe every time on a rest day, we want to truly rest and let the Action Flow do the job. We plan to have it send a recipe directly to our inbox, instead of the daily sports recommendation.

The Cocktail DB 🍷

To retrieve recipes for drinks, we will leverage the open, crowd-sourced database "TheCocktailDB", or more precisely its open API.

👉🏼 Think about it: How likely will we need to adjust our current Action Flow to receive a recipe from the CocktailDB and integrate it into our email?

Solution

What we're aiming for is adding a module in between our router and the (lower) email module that pings the CocktailDB to retrieve a non-alcoholic drinks recipe:

Our first intuition might be to add a "CocktailDB" module… but: the CocktailDB seems not to be part of the apps that Action Flows natively offer. However, there is an API available for the CocktailDB, and perhaps you remember what we have learned before:

As long as there is an API, we can connect to it!

How? Via the HTTP module…

Perhaps the heading of this lesson already gave you a hint on how to solve the riddle we posed to you above. Let's get back into the works now and add the HTTP module to our flow!

Step 1

To add a new module to an existing flow, just right-click the connection between the modules where you'd like to add the new module. Select "Add module".

Step 2

We're looking for a module called Make a request (HTTP). Add it.

Step 3

You should now see the configuration panel of the HTTP module.

We will not go into a lot of details of HTTP right now, but rather focus on making the logic for our drinks request work. There is a variety of resources on the internet available if you need them.

🕵️ Here's your next quest: A typical first step if you want to connect to a service via the HTTP module (i.e., there is no preconfigured app that will intuitively guide you) is taking a look at the respective API's documentation and the available endpoints.

You already know what we're aiming for: A single, random, non-alcoholic drink recipe.

Check out the API documentation and see how far you get in configuring the HTTP module yourself. Open the hints below one by one to either check in on your progress or, in case you need help.

Hint #1

From inspecting the available API endpoints, multiple ones may have caught your attention:

Look up a random cocktail Look up full cocktail details by ID Filter by alcoholic Hint #2

We need to build a multi-step logic. Our first step is to retrieve a list of available non-alcoholic drinks (note we're choosing this path given the number of drinks is rather low; otherwise, we may need a different approach).

Hint #3

Your configuration should look something like this:

Note that instead of specifying the query string item, you could also have appended ?a=Non_Alcoholic to the URL (just like in the API documentation). It is, however, cleaner to configure it in the way shown in the screenshot.

Hint #4

The output of running this request (hint #4a: right click the module and 'run this module only') returns a loooong list of drinks, wrapped in and separated by curly { and square [ brackets. This structure is referred to as JSON format and is the universal language for sending and receiving data over the internet.

Since raw JSON is a nightmare for the human eye to read, we need to leverage a specific setting in the HTTP module: Parse response (set it to 'Yes').

By doing this, you are giving the HTTP module a clear instruction: "Hey, the data you're about to receive is in a structured format. Please break it down into individual pieces—or data pills—so I can actually use them in my flow."

Running the module again will now result in a nicely formatted output that clearly shows how the response from the CocktailDB is structured:

Hint #5

Is this the end? No, not quite. If you look at the output of your HTTP module, you’ll see we have a bit of a "good news, not-so-good news" situation.

The Good News: We have a list of every non-alcoholic drink in the database. The Not-So-Good News: We have too many. We only want one. Plus, this list only gives us the names and IDs—the actual instructions (the recipe) are still missing.

We'll look at how to solve this on the next page… And what exactly those "Collections" and "Arrays" mean..

Set a Variable and Leverage Functions

To solve our "long-list-of-available-drinks-problem", we need to pick a random drink from our list of non-alcoholic drinks and save it so we can request its recipe in a second HTTP request.

Before we can pick a random item, we need to know how many drinks are actually in the list. In Action Flows, this "list" is called an Array.

What is an Array?

Think of an Array as a container.

The Square Brackets [ ] are the walls of the container.

Everything inside those brackets are the Collections { } (i.e., the individual drinks).

👉 Take a look at the available functions again.. Anything that looks like it could help to count the items (or collections) inside an array?

Solution

The function you're looking for is the length() function which is part of array functions.

Now that you know which function to use to solve at least a part of your problem, the next question is: Where to save the length of the array?

To answer this, it is time for you to get acquainted with the unofficial Swiss Army knife of Action Flows: Variables!

Variables in Action Flows can serve a variety of purposes, and their usage varies from being an integral part of the Action Flow to just a temporary solution to understand the outputs of one or multiple other preceding modules and operations better.

In our case, we choose the former: the Set variable module will become an integral part of our flow. However, not to just store the length of our array…

🕵️ It is time again for a quest! You've received a multitude of hints so far on how to proceed, and we'd like to put it again into your hands to figure out the solution. As before, multiple hints build on each other, and which you can expand as you need them.

Good luck!

Hint #1

The first step is to add the variable module to your flow. As before, right-click the dotted lines in between the HTTP module and the email module and add a new module - in this case, the "Set variable" module, which is part of Tools.

Hint #2

How did you name the variable that should be set through the new module?

We called it “Random non-alcoholic drink array index”.

(Pretty long name, we know, but it's supposed to be a hint 🤷)

Hint #3

We don't just want to save the length of the array (the total count of drinks) to a variable. Instead, we want to generate a random number within that range.

Why? Because our next goal is to make a second HTTP request to retrieve the full recipe for just one single drink. That request requires a Drink ID as an input. To get that ID, we have to "reach into" the list and grab it from a randomly chosen array position (also known as an Index).

We need to combine the length function with the random function. This tells the flow: "Count how many drinks we have, and then pick a random 'seat number' between 1 and that total."

Why only save the Index? Think of the Index as a coordinate. By saving this random number to a variable, we create a steady "pointer" that we can use in the next step to reach into our array and say: "Give me the ID of the drink sitting at exactly this position."

We know this sounds a bit complicated, but you're nearly there!

Hint #4

Always make sure to hover over the functions in the Action Flow editor to read the info on how exactly the respective function works and what parameters it requires.

random, for example, generates a floating-point number between 0 and 1, e.g. 0.45.

How would you need to combine it with the array's length to obtain a random number that's between 0 and the array's length?

Hint #5

You need to multiply random by the length() function to obtain a random index. Since random generates floating-point numbers, you need to wrap your entire construct into another round() function. Otherwise, the next step, to obtain the idDrink value at a specific array index, will not work.

Here is the (almost) final version of what your variable value should look like:

round( random * length( data: drinks[] ) )

There is a tiny but vital detail to remember: in Action Flows, Array indices start at 1 rather than 0. If our random generator picks 0.000, the calculation becomes 0.000 * 58, which equals 0. Since there is no "Seat 0" in our array, the module would return an empty response. To prevent this, we might be tempted to simply add +1 to our formula—but that creates a new problem at the other end of the spectrum.

Imagine the random number is 0.999. Multiplied by 58, it returns 57.942. The round() function would push this up to 58, and adding our +1 would suddenly result in an index of 59—another non-existent position! So, how do we keep our "pointer" perfectly within the lines?

Mastering Floor and Ceil

The secret lies in swapping out round() for a more precise pair of functions: floor() and ceil().

While the floor function "drops" a decimal down to the nearest whole integer (like hitting the ground), the ceil function (short for ceiling) always "pushes" it up to the next whole integer.

By using floor(random * length) + 1, we ensure that even a 0.999 result only ever reaches 57, which the +1 then corrects to a perfect 58. Our logic is now officially "bulletproof."

Your final result looks like this:

Make sure you've mapped the correct array item from the HTTP module inside the length function.

Did you get it right?

Our Set Variable module now outputs a randomly chosen index of the drinks array.

The next step is to retrieve the recipe for our chosen drink. Bottoms up!

Access Nested Objects

You’ve already mastered a rather complex "nested" function in the previous step - combining round, random, and length is no small feat! Now, it's time to put that randomly generated index to work.

We are going to bridge the gap between our long list of drinks and the specific recipe we want to send to our inbox.

The Second HTTP Request

First, we need to add the module that actually fetches the ingredients and instructions.

Add a second HTTP module (Make a request) after your Variable module.

The Goal: We need the endpoint that looks up a cocktail by its ID. The URL: 👉 Take a look at the documentation again. The Parameter: Instead of appending the ID to the URL, let's keep it clean. Add an item under Query String: This is where the magic happens...

In the Value field for the query item, we need to reach back to our very first HTTP module (the one with the big list) and use our Index variable to pull out exactly one idDrink.

🕵️ Your Quest: Construct a function that does the following:

Uses your Random non-alcoholic drink array index variable as the position. Extracts the idDrink property from that specific position.

You know the drill… use the hints below as you need them!

Hint #1

The URL, or rather the endpoint we need, is called Lookup full cocktail details by id:

https://www.thecocktaildb.com/api/json/v1/1/lookup.php

As instructed before, let's not append our drink ID directly to the URL but transmit it via the query parameters. You should have one query item called i (as per the API documentation). The value of the query parameter is exactly where the challenge truly begins.

Hint #2

To get the recipe, we need to reach into the big box of drinks and grab one specific ID. Every drink in that list is a "Collection" (a folder) holding details like Name and ID. We need to tell the flow: "Go to seat number [X] in the list, open that folder, and grab the ID inside."

Hint #3

To do this, you need the get() function. This function asks: "Which array should I look at, and which position should I grab?"

Hovering this function in the Action Flow editor will tell you what the different options are for using the function properly.

We will use dot notation to point to the specific property we want. The structure looks like this: get ( Array ; Index . PropertyName )

Let's deconstruct it:

The Array: data: drinks[] (from your first HTTP module). The Index: Random non-alcoholic array index (your Swiss Army knife variable). The Property: .idDrink (the specific key we want to extract; you'll need to type this out).

The final formula should look like this:

get ( data: drinks [] ; [Random non-alcoholic array index].idDrink )

This tells the module: "Find the drink at my random position and give me its ID number."

If everything is configured correctly, you should now get an output similar to the one below from your second HTTP module (run the entire flow once to test and make sure to adjust the filter conditions if required):

Note that we again activated the "Parse response" option to format the returned instructions nicely.

We now have all the info we need to send our email, including the recipe! If you look at the output carefully, you may notice one or another hurdle to that still… Let's tackle it.

Map Complex Data

You’ve (almost) done it! Our last hurdle is that the API provides 15 slots for ingredients (strIngredient1 through strIngredient15) and also measures, but our chosen drink may only use three or four ingredients (and measures).

If we map all 15 fields directly into our email, the result will look like a messy shopping list with multiple empty lines.

The "If" Function: Your Quality Filter

To keep our email professional, we only want to show ingredients that actually exist. For this, we use the if() function.

The logic works like this: "If Ingredient 4 exists, show it. If not, show nothing."

In a professional, large-scale project - with 100 possible ingredients - an architect would use an Iterator to handle this automatically. However, because this specific API sends data in a "flat" format (Ingredient 1, Ingredient 2, etc.) rather than a clean list, we would have to build a complex transformation to loop through them.

To keep our focus on mastering Conditional Logic, we are going to map only the first five ingredients. Since most non-alcoholic drinks are relatively simple, this covers 95% of our recipes without turning our email module into a construction site!

💡 Don't worry—as you progress through the Build Action Flows Training Track, we’ll show you the "Pro" way to collapse hundreds of fields into a single list using Iterators and Array Aggregators. For now, let’s focus on getting these five looking perfect.

Building the Recipe Body

In your Email module, find the Content field. We want to structure it nicely using HTML (or plain text) and our new data pills.

Your Quest: Map the strInstructions first. Then, for the ingredients, use the following pattern for the first five ingredients and measures:

if(strIngredient1 ; strMeasure1 + strIngredient1 ; )

Solution | Deconstructing the "If" Formula strIngredient1: This is the "condition." The function checks if this pill has any data. strMeasure1 + strIngredient1: This is what happens if the condition is true. It combines the measurement (e.g., 1/2 cup) and the name (e.g., Coffee). (empty): This is what happens if the condition is false. It tells the email to stay completely empty for that line rather than showing an error or a "null" text.

After an optional intro in your email body and adding the instructions (in the language of your choice) to the end, the list of ingredients should look more or less like this:

Hi there! Time to test a new drink recipe! Here's today's challenge:

<b>{{10.data.drinks[].strDrink}}</b>

<b>Ingredients: </b>

{{if(10.data.drinks[].strIngredient1; (10.data.drinks[].strMeasure1 + 10.data.drinks[].strIngredient1) + " "; )}} {{if(10.data.drinks[].strIngredient2; (10.data.drinks[].strMeasure2 + 10.data.drinks[].strIngredient2) + " "; )}} {{if(10.data.drinks[].strIngredient3; (10.data.drinks[].strMeasure3 + 10.data.drinks[].strIngredient3) + " "; )}} {{if(10.data.drinks[].strIngredient4; (10.data.drinks[].strMeasure4 + 10.data.drinks[].strIngredient4) + " "; )}} {{if(10.data.drinks[].strMeasure5; (10.data.drinks[].strMeasure5 + 10.data.drinks[].strIngredient5) + " "; )}}

<b>How to mix it: </b>

{{10.data.drinks[].strInstructions}}

Cheers!

When the email arrives, it won't matter if the drink has 2 ingredients or 5—it will always look perfectly formatted!

Victory Lap Save your Action Flow. Run the entire flow one last time. Check your inbox.

If you see a refreshing non-alcoholic recipe waiting for you, congratulations! You’ve mastered Routers, Filters, HTTP Requests, Variables, and Nested Functions; all very important tools and skills on your road to successfully architecting Action Flows.

You will find a beautified HTML example in the course resources, which will give you a nicely formatted email that looks like this:

You'll furthermore find a blueprint of the final Action Flow in the course resources to retrace any details if needed!

Reviewing Action Flow Architecture Choices

Congratulations! You’ve built a complex, dynamic engine that handles data like a pro. But before we cross the finish line, let’s pull back the curtain on why we built it this way. In the world of Action Flows, there is rarely only one "right" way—only the most elegant one for your specific goal.

Why dynamic over static?

You might wonder: "Why bother counting the array length every single time? Why not just count once and hard-code '58' into the random function?"

The Dynamic Reality: In a real-world scenario, database content changes. Recipes are added or removed irregularly. A static flow (hard-coded at 58) would quickly break or miss new data. The Principle: Scalability. A great architect builds flows that adapt to the data, not the other way around. Where does the logic live?

We chose to store the Index in our variable and then perform the get() function inside the second HTTP module. But we had other options! We could have:

Constructed a variable that outputs the Drink ID directly. Constructed a variable that outputs the entire Drink Collection.

So, why the Index? Keeping the Index as our variable makes the flow easier to maintain. If another person looks at your flow, seeing "Selected_Index" makes the mathematical logic clear. If you hide the entire get() function inside a variable, the next person might struggle to troubleshoot where the data is coming from.

Architecting Principles

As you move forward, keep these three principles in mind when choosing your design path:

Maintenance: Can a teammate understand what this module does in 30 seconds? Computational Efficiency: Are you calling the same data three times, or could you save it to a variable once? Flexibility: If a teammate asks to send this recipe to Slack instead of Email tomorrow, how much of the flow would you have to rebuild?

"An elegant solution isn't just one that works; it's one that is easy to read, hard to break, and simple to scale."

---

Deployment and Stability [06:00]

Deployment and Activation Recap

You’ve officially built a sophisticated, data-driven engine. It calculates indices, fetches specific API records, and formats clean, professional emails. But right now, this engine is sitting in your "garage" (the editor). To make it a live service that delivers value every single day, we need to revisit the Action Flow Activation.

From Draft to Production

As you might recall from your first steps in Action Flows, a flow doesn't just "start" once you finish the logic. There is a specific "Launch Sequence" required to move from a working draft to an active asset…

Which order of steps do you need to follow? Click the option you think is correct down below:

Activating → Versioning → Deploying

Not quite! You’re trying to start the engine before the car even rolled out of the production hall. In Action Flows, you cannot toggle a flow to "Active" until a version has been officially deployed to the Studio. Try again!

Deploying → Versioning → Activating

Close, but you’ve got the first two steps reversed. The Studio needs a specific Version to "grab" before it can Deploy it. You have to save the snapshot before you can move it into the deployment phase. Give it another shot!

Versioning → Deploying → Activating

Spot on! First, you take a snapshot of your work (Versioning), then you publish it so the Studio can see it (Deploying), and finally, you turn it on (Activating). This sequence ensures your production environment remains stable and professional.

What do we not do in our training teams, though? Exactly, we don't activate Action Flows nor keep them active. After all, this is a training, not a productive environment, and we want to save our resources.

Check out this video on Versioning and Deployment, if you need a refresher!

Polling vs. On-Demand

For our Sports Consultant, we’ve focused on a Scheduled approach.

The Polling Interval: By setting a schedule (e.g., every 24 hours), you are telling the system to "Poll" the data. Every morning at your specified time, the flow wakes up, runs through its logic, and sends the recipe. A Look Ahead: While we are using a clock to trigger our flow today, keep in mind that many professional flows are On-Demand. This means they sit silently until a specific event - like a user clicking a button in a Celonis View or a Webhook receiving data from an outside system - triggers them instantly.

🌍 The "UTC" Constraint

Unlike some other tools, Action Flows exclusively follow UTC (Atlantic/Reykjavik) time. There is no setting to change the flow's internal clock to your local time.

If you want your recipe or sports recommendation to land in a user's inbox at 8:00 AM in New York (EST), you’ll need to schedule your flow for 1:00 PM UTC. Always perform the "UTC Offset" calculation manually to ensure your flow hits the mark!

The reason we emphasize the differences between development and 'live' phases isn't just for organization - it's for stability. By separating your "Drafting" area from your "Active" area, you ensure that your end-users never see a "Work in Progress." Even if you are currently rewriting the entire drink logic, the previously deployed version continues to send out recipes every rest day without a hitch.

Handling External Constraints

Next Lesson Handling External Constraints

Even the most perfectly designed Action Flow is only as fast as the APIs it communicates with. Most professional APIs have a "Rate Limit" - a maximum number of requests they will allow within a specific timeframe. If your flow sends requests faster than the API can process them, the server will block you with a 429 Error: Too Many Requests.

In the world of automated flows, being "too fast" is a common cause of unexpected (or rather expected?) crashes. To prevent this, we use a simple but effective tool to pace our execution: The Sleep Tool.

Adding the "Breather"

By inserting a Sleep module, you are building resilience into your design. It ensures that your flow "takes a breath" before hitting the next module.

While our drinks route only makes two rapid requests - a volume that most APIs handle easily - the Sleep tool is a mandatory skill for an Action Flow architect's toolkit. It becomes a lifesaver in high-volume scenarios, such as Mass Data Migrations, where you might be updating hundreds of records in a CRM and need to stay under a strict "requests-per-second" limit to avoid a system-wide failure.

Let's, for illustrative purposes, still add a sleeper module to our flow (optional to follow this in your training team):

Step 1

Open the Tools menu (the purple icon in your lower toolbar).

Step 2

Search for and select the Sleep module.

Step 3

Place it on the path directly before your second HTTP module (the one fetching the specific drink details).

Step 4

Set the Delay to 2 seconds.

Step 5

Hit the "Auto-Align" button to make the flow look nice again.

Now, when you run the flow, you’ll notice a deliberate 2-second pause. You have successfully designed a flow that respects external boundaries—a hallmark of a stable production asset.

---

Quality Assurance and Root Cause Analysis [05:00]

Testing beyond the Green Checkmark

Even with perfect logic and a resilient schedule, things can go wrong. The most dangerous errors aren't the ones that make the flow "explode" with a red error icon; it is the Silent Failures - where the flow completes successfully, but the output is empty or incorrect.

The "Empty Email" Mystery 🕵️

When we first designed this course, we ran into a mystery. Our flow executed perfectly. All the bubbles turned green. The email was sent. But when we opened the inbox, the email body was empty. No ingredients, no instructions - just a blank message.

According to the Action Flow, everything was a success. So, how did we find the culprit?

The Art of Backtracking

We didn't start at the beginning of the flow; we started at the end. We looked at the Simple Log of the final execution:

Check the Email Module: We saw the input was empty. Conclusion: The data didn't reach the email. Check the 2nd HTTP Module: We looked at the "Output" and saw it was empty. Conclusion: The API didn't return a recipe. Check the Variable: This is where we found it. The Variable had generated an index of 59, but our drink list was only 58 long.

Because we added +1 to a round() function, we occasionally overshot the boundary of the array. The API looked for a drink at index 59, found nothing, and sent back a "null" response. The flow didn't crash because "finding nothing" isn't technically a system error—it's just empty data.

Testing for Edge Cases

This is why your job when architecting Action Flows is never done after the first successful run. You must test for Edge Cases—those rare moments where your logic hits a boundary (like the very first or very last item in a list).

Architect’s Mindset: If your email is empty but the flow is green, don't panic. Backtrack. Follow the data trail module-by-module until you find the exact point where the data "vanished." Usually, the Simple Log provides all the clues you need to solve the mystery.

Advanced Logs and Auditability

While the Simple Log is your go-to for checking the data inputs and outputs, the Advanced Log provides a technical play-by-play of the execution's lifecycle.

It reveals the operational phases of each module, such as when a module is initialized, when the data commit begins, and exactly when the process completes.

While you usually won't need this for daily troubleshooting, it is invaluable when a flow "hangs" or stops unexpectedly, as it allows you to see exactly which phase of the processing was the last to successfully fire.

Searching the History

You don't have to scroll through hundreds of "Success" bubbles to find one specific failure. Within the History tab of your Action Flow, you can use the Search and Filter tools to narrow down the list. You can filter by:

Status: Quickly isolate only the "Error" states. Date Range: Focus on a specific window of time. Specific Data: Search for executions containing a specific keyword.

Packing Your Bags: The Audit Log

You may eventually need to export your data for compliance or long-term troubleshooting. Because execution logs in the history tab eventually expire, Celonis provides a central hub for your records in the Admin & Settings section.

Step 1

Navigate to Audit Logs: Go to the Admin Section and select Audit Logs.

Step 2

Define a Period: Before downloading, use the Define Period calendar tool to select the specific timeframe you are interested in.

Step 3

Download the Evidence: Click the blue Download button. Here, you have the specific option to Download Action Flow Execution Logs (.csv).

This CSV file serves as your permanent "Black Box" recorder, ensuring that even after the history is cleared from the Studio, you still have a searchable, auditable record of every move your flow made.

---

From Learning to Building [06:00]

Leverage the Training Environment

You’ve finished the formal blueprints, but the best way to solidify your skills is to start "breaking" things in a safe space. The Training Environment isn’t just where this course lives - it’s your personal sandbox for experimentation.

The "What-If" Challenge

Don’t delete your Sports (and Wellness) flow just yet. Instead, use it as a base to test new ideas. A great Action Flow builder is always asking "What if?"

Try these modifications to see how the logic holds up:

The Notification Swap: What if you replaced the Email module with a Slack or Microsoft Teams module? The Personal Touch: What if you used String Functions to ensure the drink name is always in UPPERCASE, or tried to parse the "Instructions" text to highlight the ingredients in bold within the email? The Logic Pivot: What if you changed the logic to fetch two random drinks instead of one, and compared their calorie counts? Your Library of Blueprints

You don't always have to start with a blank canvas. The Celonis Marketplace is filled with Action Flow Templates. These are pre-built flows designed for common business scenarios - like clearing credit blocks in SAP or updating records in Salesforce.

Exploring these templates is one of the fastest ways to see how Master Architects structure their logic and handle complex data mappings.

The Golden Rule: Training vs. Production

As you start exploring, always keep the Architect’s Guardrail in mind:

Training Environment

Use this for learning, testing "crazy" ideas, and exploring new modules. Keep in mind, though, that you don't have any of your "own" data available here.

Production Environment

This is for live business processes. Never "test" a new idea in a production flow. Build it in Training first, verify the data, and only then migrate your design to the live environment.

Architect's Mindset: Separation of environments is the first step toward system stability. Treat your Production flows like a high-speed highway - no construction allowed while traffic is moving!

Identifying Your Use Case

Now that you have the technical skills, the question is: What should I build first? Not every manual task is a good candidate for an Action Flow. As an Architect, you want to focus your energy on "Automation Gold" - tasks where the effort to build the flow is far outweighed by the time saved and errors avoided.

The "Three R's" Framework

When looking at your own business processes, evaluate potential ideas against the Three R's:

Repetitive: Does this task happen frequently (daily or weekly)? If you only do it once a quarter, it might not be worth automating. If it’s a daily recommendation style task, it’s a prime candidate. Rule-Based: Can you describe the logic using "If/Then" statements? Action Flows thrive on clear rules. If a task requires "gut feeling" or subjective human intuition, it’s likely not ready for an Action Flow - other than the Action Flow creating a task for a human, perhaps! Reach: Does the task require moving data between different systems? Action Flows are the "bridges" of the Celonis world. If you find yourself manually copy-pasting data from a Celonis Analysis into an Excel sheet, an Email, or a CRM like Salesforce, you’ve found a high-value use case. Start Small, Scale Fast

The most successful Architects don't try to automate an entire department on day one. They start with a Micro-Automation:

The Alert: "If a high-priority invoice is overdue by 10 days, send a Ping to the account owner." The Data Sync: "When a status changes in SAP, update the corresponding record in our tracking spreadsheet." Best Practices for Design

As you identify your first project, keep these principles in mind:

Keep it Modular

It’s better to have three small, simple flows than one "Mega-Flow" that is impossible to troubleshoot.

Name Your Modules

Don't leave them as "HTTP 1" and "HTTP 2." Rename them to "Fetch Random ID" and "Get Drink Details." Your future self (and your teammates) will thank you.

Plan for Failure

Always assume an API might go down or a field might be empty. Use the error-handling skills we practiced before and will still practice a lot in a dedicated module!

Architect's Tip: Think of your first Action Flow as a "Minimum Viable Product" (MVP). Solve one specific pain point perfectly before adding the next ten features!

Personal and Dynamic Connections

Next Lesson Personal and Dynamic Connections

As you start exploring new modules, you will notice that almost every one of them requires a Connection. If Action Flows are the "engine," then Connections are the "Keys."

Think of it as "Logging In"

Creating a connection is essentially logging into that specific system through Celonis.

When you set up an Outlook module, you are authorizing Celonis to send emails from your account. When you connect to SAP, you are granting the Action Flow the power to read or write data using your credentials. Your Rights are the Flow's Rights

An Action Flow cannot do what you cannot do. If your user profile in a target system doesn't have the permission to delete a record or approve an invoice, the Action Flow will fail with a "401 Unauthorized" or "403 Forbidden" error if it tries to perform those tasks.

Architect’s Note: Always verify your permissions in the target system before building a complex flow. If the flow needs to perform an action your personal user shouldn't have (like high-level financial approvals), you may need to speak with your Admin about using a "Service Account" connection.

The Paper Trail

Because the connection is tied to an account, every action the flow takes is logged under that name.

If your flow updates 500 invoices in SAP, the SAP audit log will show that [Your Name] modified those invoices at 4:00 AM.

This is why "naming" your modules and using the Change History is so important - it ensures that when people see your name in the system logs, they know it was part of a carefully designed automation.

---

Wrap Up [05:00]

Your Learning Journey - Continued

Congratulations - mission accomplished! You have officially transitioned from an Action Flow spectator to a builder. Over the course of these lessons, you haven’t just learned how to click buttons; you’ve developed the Architect’s Mindset. You are now equipped to handle the three pillars of professional automation:

Navigating Data Structures: You’ve mastered the "Box-within-a-Box" nature of API responses. You now know how to peel back the layers of Nested Collections and Arrays, pinpointing exactly where a piece of data lives so you can map it with precision. Dynamic Item Selection: You’ve moved beyond hard-coding. By using math and index pointers, you can now instruct a flow to intelligently pick a single specific item out of a massive list - no matter how many items that list contains. Building for the Real World: You understand that systems have limits. By using the Sleep tool and respecting rate limits, you’ve learned to build "polite" automations that don't crash when they talk to external APIs. Data Verification: You’ve learned to look "Beyond the Green Checkmark," using logs to verify that the data arriving at the end of your flow is exactly what you expected.

The learning doesn't stop here! The world of automation moves fast, and the best architects are those who stay connected to the latest blueprints and strategies.

Action Flows Community: Your hub for technical deep-dives. If you hit a wall or find a clever workaround, this is where you’ll find your peers. Celonis Academy Group: Stay updated on new modules and platform features to keep your skills sharp and your flows efficient. The most successful Architects share one trait: Curiosity. Don't be afraid to take a template apart to see how it works, or to "break" a flow in the training environment to find its limits. Every error you encounter today is a more stable system you'll build tomorrow.

We hope to see you again soon at the next course of the "Build Action Flows" Training Track!

Your Celonis Academy team

Knowledge Check — 4 questões
1. You are building a dynamic flow to pick a random item from a list (array) of 100 items. Which formula ensures your "pointer" always stays within the valid range of 1 to 100, even with extreme decimal results?
2. Your "Daily Recipe" flow ran successfully with all green checkmarks. However, the email arrived with instructions, but is missing the specific drink name. What is the most efficient architectural step to take?
3. A teammate needs to troubleshoot a flow you built six months ago. Which design choices would help them understand your logic in under 30 seconds? (Select TWO correct answers)
4. You are designing a flow that will update 5,000 inventory records in an external ERP. The ERP's API has a rate limit and will block you with a 429 Error if you are too fast. Which strategies build resilience into this flow? (Select TWO correct answers)