Welcome back! In the previous lessons, you learned how to create Mastra workflows and chain multiple agents together. Now, you are ready to make your workflows even smarter by adding conditional logic through branching.
Imagine you are building an email assistant. You want to first classify an email's intent, then summarize it, and finally decide whether to draft a reply or simply acknowledge that no reply is needed. Not every email requires a response! Branching allows your workflow to make intelligent decisions and take different paths based on the data it processes.
In this lesson, you will learn how to create conditional workflows in Mastra using branching. This is a key skill for building intelligent, real-world automations that can adapt to different scenarios.
Let's quickly remind ourselves how linear workflows work. In previous lessons, you saw how to connect multiple agents in a sequence where every step always runs:
Each then adds a new step that always executes. But what if you want your workflow to make decisions? What if some emails need replies and others don't? This is where branching comes in.
Branching in Mastra workflows allows you to create conditional paths. Instead of always executing the same sequence of steps, your workflow can evaluate conditions and choose which step to run next.
Think of branching like a decision tree:
- Condition 1: If the email needs a reply → go to the "draft reply" step
- Condition 2: If the email doesn't need a reply → go to the "no reply needed" step
This makes your workflows much more intelligent and efficient.
To create branches in a Mastra workflow, you use the branch() method. This method takes an array of condition-step pairs, where each pair consists of:
- A condition function that returns
trueorfalse - A step to execute if the condition is
true
Here's the basic syntax:
For example, with simple comparison conditions:
The workflow evaluates each condition in order and executes the first step whose condition returns true.
Let's break down how branching works in our email processing workflow.
First, we classify the email's intent:
This step analyzes the email and determines what the sender wants.
Next, we summarize the email and decide if a reply is needed:
Key Point: This step returns a replyNeeded boolean that will be used for branching decisions. Notice how we use a schema (z.object({ summary: z.string(), replyNeeded: z.boolean(), draftReply: z.string() })) to force the agent to return data in a specific structure, ensuring we get the boolean value needed for our branching logic.
Now comes the branching logic:
How this works:
- First condition:
async ({ inputData: { replyNeeded } }) => replyNeeded- If
replyNeededistrue, executeprintReplyStep
- If
- Second condition:
async ({ inputData: { replyNeeded } }) => !replyNeeded- If
replyNeededisfalse, executenoReplyStep
- If
Print Reply Step (when reply is needed):
No Reply Step (when no reply is needed):
Key observations about these branch steps:
Both steps share the same inputSchema because they receive identical data from summarizeEmailStep. However, their outputSchema definitions differ based on what data they need to pass forward: printReplyStep includes draftReply while noReplyStep omits it.
You might notice that noReplyStep destructures fields like replyNeeded and draftReply even though they're not used in the function body. While you don't strictly need to access these fields (the branching condition has already evaluated ), they're included in the input schema and often destructured for code clarity or potential future use.
One of the powerful features of Mastra's branching system is that it's automatic. You don't need to manually check conditions or write complex if-else logic in your steps. The workflow engine:
- Evaluates conditions in order - It checks each condition function in the branch array
- Executes the first matching step - As soon as a condition returns
true, it runs that step - Continues the workflow - After the branch step completes, the workflow continues with any subsequent steps
This automatic branching makes your workflows clean, readable, and easy to maintain.
Here's how the complete workflow looks:
What happens here?
- The workflow always runs
classifyIntentStepfirst - Then it always runs
summarizeEmailStep - Based on the
replyNeededvalue, it branches to either:printReplyStepif a reply is needednoReplyStepif no reply is needed
Note: In the outputSchema, draftReply is marked as optional (z.string().optional()). This is important because if no reply is needed, the workflow will not generate a draft reply, so this field may be absent in those cases.
Example Scenarios:
Scenario 1 - Reply Needed:
- Email: "Can you send me the quarterly report?"
- Intent: "Request"
- Summary: "User requesting quarterly report"
replyNeeded:
In this lesson, you learned how to create conditional workflows in Mastra using the branch() method. Branching allows your workflows to make intelligent decisions and take different paths based on the data they process, making them much more powerful and efficient.
Key takeaways:
- Use
branch()to create conditional paths in your workflows - Each branch consists of a condition function and a step to execute
- Mastra automatically evaluates conditions and executes the appropriate step
- Branching makes workflows more intelligent and adaptable to different scenarios
Congratulations on reaching the end of the course! You now have the skills to build smart, conditional workflows in Mastra. Up next, try out the practice exercises to reinforce what you've learned. Great job making it this far — keep experimenting and building!
