![]() |
| https://www.pexels.com/photo/red-and-blue-industrial-exhaust-fans-416423/ |
Implementing Fan-In and Fan-Out Workflow Patterns with MAF
Introduction
In my previous blog post, I demonstrated how to make concurrent calls to multiple agents using MAF's `ConcurrentBuilder`. While powerful for parallel execution, there are scenarios where you need more control over workflow structure and data flow. That's where the fan-in and fan-out pattern comes in.
In this post, I'll show you how to implement this pattern using MAF's `WorkflowBuilder`, enabling you to distribute tasks to multiple executors and elegantly aggregate their results.
Understanding Fan-In and Fan-Out
The fan-in and fan-out pattern is a classic workflow architecture that consists of three key components:
- Dispatcher (Fan-Out): Receives the initial input and distributes it to multiple executors
- Executors: Process the input in parallel, each performing specialized tasks
- Aggregator (Fan-In): Collects and combines the outputs from all executors into a unified response
This pattern is particularly useful when you need to apply multiple transformations or analyses to the same input simultaneously, then merge the results into a coherent output.
ConcurrentBuilder vs. WorkflowBuilder
Before diving into the implementation, let's clarify when to use each approach:
ConcurrentBuilder
- Best for simple parallel execution without complex workflow structures
- Ideal when you just need to run multiple independent tasks and collect results
- Minimal overhead and setup
WorkflowBuilder
- Provides structured workflow definition with explicit data flow
- Supports sophisticated patterns like fan-in/fan-out, conditional routing, and sequential steps
- Better for complex orchestration where tasks need coordination in specific sequences or structures
- Offers more control over how executors communicate and share data
- Better for complex orchestration where tasks need coordination in specific sequences or structures
Building a Fan-In/Fan-Out Workflow
Let's build an example that demonstrates this pattern. Our workflow will process a user query about travel destinations by generating both factual information and creative content:
Workflow Components
1. Dispatcher: The entry point that receives the user query and broadcasts it to multiple executors:
class Dispatcher(Executor): @handler async def handle(self, user_query: str, ctx: WorkflowContext[str]): await ctx.send_message(user_query)
2. Specialized Executors
- FactExecutor: Generates concise, accurate factual information about the destination
- PoemExecutor: Creates an engaging poem that captures the essence of the location
Both executors process the query simultaneously, leveraging parallelism for faster response times.
3. Aggregator; Collects outputs from both executors and combines them into a unified response:
class Aggregator(Executor):
@handler
async def handle(self, results: list[str], ctx: WorkflowContext[Never, str]):
combined = "\n\n".join(results)
await ctx.yield_output(combined)Note: The aggregator receives a list[str] containing outputs from all upstream executors.
Constructing the Workflow
Here's how we wire everything together using WorkflowBuilder:
workflow = (
WorkflowBuilder()
.set_start_executor(dispatcher)
.add_fan_out_edges(dispatcher, [fact_executor, poem_executor])
.add_fan_in_edges([fact_executor, poem_executor], aggregator)
.build()
)
output = await workflow.run("We are planning a trip to Japan.")The workflow execution follows this path:
1. Dispatcher receives the query
2. Query fans out to both FactExecutor and PoemExecutor (runs in parallel)
3. Results fan in to the Aggregator
4. Aggregator produces the final combined output
Demo
Check out the complete implementation: https://github.com/dennisseah/maf-workflow/blob/main/samples/fan_in_fan_out.py
Video Walkthrough (view in fullscreen, no audio)
In the video, I step through the code to demonstrate:
- How agents are defined with specific instructions
- Workflow construction using MAF's API
- The fan-out and fan-in edge definitions
- Runtime execution with a sample query
Conclusion
The fan-in and fan-out pattern with WorkflowBuilder gives you powerful control over complex workflow orchestration. Whether you're building AI assistants that need to consult multiple specialists or data pipelines that require parallel processing with aggregation, this pattern provides a clean, maintainable solution.
Key takeaways
- Use `add_fan_out_edges()` to distribute input to multiple executors
- Use `add_fan_in_edges()` to aggregate results from multiple sources
- Remember that fan-in aggregators receive a `list` of outputs, not individual values
- Choose `WorkflowBuilder` when you need structured, coordinated workflows

Comments
Post a Comment