Build deterministic, production-ready workflows that orchestrate agents, teams, and functions with predictable execution patterns. This comprehensive guide covers all workflow types, from simple sequential processes to complex branching logic with parallel execution and dynamic routing. Unlike free-form agent interactions, these patterns provide structured automation with consistent, repeatable results ideal for production systems.

Building Blocks

The core building blocks of Agno Workflows are:
ComponentPurpose
StepBasic execution unit
AgentAI assistant with specific role
TeamCoordinated group of agents
FunctionCustom Python logic
ParallelConcurrent execution
ConditionConditional execution
LoopIterative execution
RouterDynamic routing

Workflow Patterns

1. Sequential Workflows

When to use: Linear, deterministic processes where each step depends on the output of the previous step. Example Flow: Research → Data Processing → Content Creation → Final Review Sequential workflows ensure predictable execution order and clear data flow between steps.
from agno.workflow import Step, Workflow, StepOutput

def data_preprocessor(step_input):
    # Custom preprocessing logic

    # Or you can also run any agent/team over here itself
    # response = some_agent.run(...)
    return StepOutput(content=f"Processed: {step_input.input}") # <-- Now pass the agent/team response in content here

workflow = Workflow(
    name="Mixed Execution Pipeline",
    steps=[
        research_team,      # Team
        data_preprocessor,  # Function
        content_agent,      # Agent
    ]
)

workflow.print_response("Analyze the competitive landscape for fintech startups", markdown=True)
For more information on how to use custom functions, refer to the Advanced page.
See Example:
StepInput and StepOutput provides standardized interfaces for data flow between steps: So if you make a custom function as an executor for a step, make sure that the input and output types are compatible with the StepInput and StepOutput interfaces. This will ensure that your custom function can seamlessly integrate into the workflow system.Take a look at the schemas for StepInput and StepOutput.

2. Fully Python Workflow

Keep it Simple with Pure Python: If you prefer the Workflows 1.0 approach or need maximum flexibility, you can still use a single Python function to handle everything. This approach gives you complete control over the execution flow while still benefiting from workflow features like storage, streaming, and session management. Replace all the steps in the workflow with a single executable function where you can control everything.
from agno.workflow import Workflow, WorkflowExecutionInput

def custom_workflow_function(workflow: Workflow, execution_input: WorkflowExecutionInput):
    # Custom orchestration logic
    research_result = research_team.run(execution_input.message)
    analysis_result = analysis_agent.run(research_result.content)
    return f"Final: {analysis_result.content}"

workflow = Workflow(
    name="Function-Based Workflow",
    steps=custom_workflow_function  # Single function replaces all steps
)

workflow.print_response("Evaluate the market potential for quantum computing applications", markdown=True)
See Example: For migration from 1.0 style workflows, refer to the page for Migrating to Workflows 2.0

3. Step-Based Workflows

You can name your steps for better logging and future support on the Agno platform. This also changes the name of a step when accessing that step’s output inside a StepInput object.

Parameters

ParameterTypeDefaultDescription
nameOptional[str]NoneName of the step for identification
agentOptional[Agent]NoneAgent to execute for this step
teamOptional[Team]NoneTeam to execute for this step
executorOptional[StepExecutor]NoneCustom function to execute for this step
step_idOptional[str]NoneUnique identifier for the step (auto-generated if not provided)
descriptionOptional[str]NoneDescription of the step's purpose
max_retriesint3Maximum number of retry attempts on failure
timeout_secondsOptional[int]NoneTimeout for step execution in seconds
skip_on_failureboolFalseWhether to skip this step if it fails after all retries

Example

from agno.workflow import Step, Workflow

# Named steps for better tracking
workflow = Workflow(
    name="Content Creation Pipeline",
    steps=[
        Step(name="Research Phase", team=researcher),
        Step(name="Analysis Phase", executor=custom_function),
        Step(name="Writing Phase", agent=writer),
    ]
)

workflow.print_response(
    "AI trends in 2024",
    markdown=True,
)
See Examples:

4. Conditional Workflows

When to use: Deterministic branching based on input analysis or business rules. Example Use-Cases: Content type routing, topic-specific processing, quality-based decisions Conditional workflows provide predictable branching logic while maintaining deterministic execution paths. Workflows condition steps diagram

Parameters

ParameterTypeDefaultDescription
evaluatorUnion[Callable[[StepInput], bool], Callable[[StepInput], Awaitable[bool]], bool]RequiredFunction or boolean to evaluate the condition
stepsWorkflowStepsRequiredSteps to execute if the condition is met
nameOptional[str]NoneName of the condition step
descriptionOptional[str]NoneDescription of the condition step

Example

from agno.workflow import Condition, Step, Workflow

def is_tech_topic(step_input) -> bool:
    topic = step_input.input.lower()
    return any(keyword in topic for keyword in ["ai", "tech", "software"])

workflow = Workflow(
    name="Conditional Research",
    steps=[
        Condition(
            name="Tech Topic Check",
            evaluator=is_tech_topic,
            steps=[Step(name="Tech Research", agent=tech_researcher)]
        ),
        Step(name="General Analysis", agent=general_analyst),
    ]
)

workflow.print_response("Comprehensive analysis of AI and machine learning trends", markdown=True)
More Examples:

5. Parallel Workflows

When to use: Independent, concurrent tasks that can execute simultaneously for improved efficiency. Example Use-Cases: Multi-source research, parallel analysis, concurrent data processing Parallel workflows maintain deterministic results while dramatically reducing execution time for independent operations. Workflows parallel steps diagram

Parameters

ParameterTypeDefaultDescription
*steps*WorkflowStepsRequiredVariable number of steps to execute in parallel
nameOptional[str]NoneName of the parallel execution block
descriptionOptional[str]NoneDescription of the parallel execution

Example

from agno.workflow import Parallel, Step, Workflow

workflow = Workflow(
    name="Parallel Research Pipeline",
    steps=[
        Parallel(
            Step(name="HackerNews Research", agent=hn_researcher),
            Step(name="Web Research", agent=web_researcher),
            Step(name="Academic Research", agent=academic_researcher),
            name="Research Step"
        ),
        Step(name="Synthesis", agent=synthesizer),  # Combines the results and produces a report
    ]
)

workflow.print_response("Write about the latest AI developments", markdown=True)
More Examples:

6. Iterative Workflows

When to use: Quality-driven processes requiring repetition until specific conditions are met. Example Use-Cases: Quality improvement loops, retry mechanisms, iterative refinement Iterative workflows provide controlled repetition with deterministic exit conditions, ensuring consistent quality standards. Workflows loop steps diagram

Parameters

ParameterTypeDefaultDescription
stepsWorkflowStepsRequiredSteps to execute in each loop iteration
nameOptional[str]NoneName of the loop step
descriptionOptional[str]NoneDescription of the loop step
max_iterationsint3Maximum number of iterations for the loop
end_conditionOptional[Union[Callable[[List[StepOutput]], bool], Callable[[List[StepOutput]], Awaitable[bool]]]]NoneFunction to evaluate if the loop should end

Example

from agno.workflow import Loop, Step, Workflow

def quality_check(outputs) -> bool:
    # Return True to break loop, False to continue
    return any(len(output.content) > 500 for output in outputs)

workflow = Workflow(
    name="Quality-Driven Research",
    steps=[
        Loop(
            name="Research Loop",
            steps=[Step(name="Deep Research", agent=researcher)],
            end_condition=quality_check,
            max_iterations=3
        ),
        Step(name="Final Analysis", agent=analyst),
    ]
)

workflow.print_response("Research the impact of renewable energy on global markets", markdown=True)
More Examples:

7. Branching Workflows

When to use: Complex decision trees requiring dynamic path selection based on content analysis. Example Use-Cases: Expert routing, content type detection, multi-path processing Dynamic routing workflows provide intelligent path selection while maintaining predictable execution within each chosen branch. Workflows router steps diagram

Parameters

ParameterTypeDefaultDescription
selectorUnion[Callable[[StepInput], Union[WorkflowSteps, List[WorkflowSteps]]], Callable[[StepInput], Awaitable[Union[WorkflowSteps, List[WorkflowSteps]]]]]RequiredFunction to select steps dynamically (supports both sync and async functions)
choicesWorkflowStepsRequiredAvailable steps for selection
nameOptional[str]NoneName of the router step
descriptionOptional[str]NoneDescription of the router step

Example

from agno.workflow import Router, Step, Workflow

def route_by_topic(step_input) -> List[Step]:
    topic = step_input.input.lower()

    if "tech" in topic:
        return [Step(name="Tech Research", agent=tech_expert)]
    elif "business" in topic:
        return [Step(name="Business Research", agent=biz_expert)]
    else:
        return [Step(name="General Research", agent=generalist)]

workflow = Workflow(
    name="Expert Routing",
    steps=[
        Router(
            name="Topic Router",
            selector=route_by_topic,
            choices=[tech_step, business_step, general_step]
        ),
        Step(name="Synthesis", agent=synthesizer),
    ]
)

workflow.print_response("Latest developments in artificial intelligence and machine learning", markdown=True)
More Examples:

8. Grouped Step Workflows

When to use: Organize multiple steps into reusable, logical sequences for complex workflows with clean separation of concerns. Key Benefits: Reusable sequences, cleaner branching logic, modular workflow design Grouped steps enable modular workflow architecture with reusable components and clear logical boundaries.

Parameters

ParameterTypeDefaultDescription
nameOptional[str]NoneName of the steps group for identification
descriptionOptional[str]NoneDescription of the steps group's purpose
stepsOptional[List[Any]][]List of steps to execute sequentially (empty list if not provided)

Basic Example

from agno.workflow import Steps, Step, Workflow

# Create a reusable content creation sequence
article_creation_sequence = Steps(
    name="ArticleCreation",
    description="Complete article creation workflow from research to final edit",
    steps=[
        Step(name="research", agent=researcher),
        Step(name="writing", agent=writer),
        Step(name="editing", agent=editor),
    ],
)

# Use the sequence in a workflow
workflow = Workflow(
    name="Article Creation Workflow",
    steps=[article_creation_sequence]  # Single sequence
)

workflow.print_response("Write an article about renewable energy", markdown=True)

Steps with Router

This is where Steps really shines - creating distinct sequences for different content types or workflows:
from agno.workflow import Steps, Router, Step, Workflow

# Define two completely different workflows as Steps
image_sequence = Steps(
    name="image_generation",
    description="Complete image generation and analysis workflow",
    steps=[
        Step(name="generate_image", agent=image_generator),
        Step(name="describe_image", agent=image_describer),
    ],
)

video_sequence = Steps(
    name="video_generation",
    description="Complete video production and analysis workflow",
    steps=[
        Step(name="generate_video", agent=video_generator),
        Step(name="describe_video", agent=video_describer),
    ],
)

def media_sequence_selector(step_input) -> List[Step]:
    """Route to appropriate media generation pipeline"""
    if not step_input.input:
        return [image_sequence]

    message_lower = step_input.input.lower()

    if "video" in message_lower:
        return [video_sequence]
    elif "image" in message_lower:
        return [image_sequence]
    else:
        return [image_sequence]  # Default

# Clean workflow with clear branching
media_workflow = Workflow(
    name="AI Media Generation Workflow",
    description="Generate and analyze images or videos using AI agents",
    steps=[
        Router(
            name="Media Type Router",
            description="Routes to appropriate media generation pipeline",
            selector=media_sequence_selector,
            choices=[image_sequence, video_sequence],  # Clear choices
        )
    ],
)

# Usage examples
media_workflow.print_response("Create an image of a magical forest", markdown=True)
media_workflow.print_response("Create a cinematic video of city timelapse", markdown=True)
More Examples:

9. Advanced Workflow Patterns

Combine multiple workflow patterns to build sophisticated, production-ready automation systems. Pattern Combination: Conditional Logic + Parallel Execution + Iterative Loops + Custom Processing + Dynamic Routing This example demonstrates how deterministic patterns can be composed to create complex yet predictable workflows.
from agno.workflow import Condition, Loop, Parallel, Router, Step, Workflow

def research_post_processor(step_input) -> StepOutput:
    """Post-process and consolidate research data from parallel conditions"""
    research_data = step_input.previous_step_content or ""

    try:
        # Analyze research quality and completeness
        word_count = len(research_data.split())
        has_tech_content = any(keyword in research_data.lower()
                              for keyword in ["technology", "ai", "software", "tech"])
        has_business_content = any(keyword in research_data.lower()
                                  for keyword in ["market", "business", "revenue", "strategy"])

        # Create enhanced research summary
        enhanced_summary = f"""
            ## Research Analysis Report

            **Data Quality:** {"✓ High-quality" if word_count > 200 else "⚠ Limited data"}

            **Content Coverage:**
            - Technical Analysis: {"✓ Completed" if has_tech_content else "✗ Not available"}
            - Business Analysis: {"✓ Completed" if has_business_content else "✗ Not available"}

            **Research Findings:**
            {research_data}
        """.strip()

        return StepOutput(
            content=enhanced_summary,
            success=True,
        )

    except Exception as e:
        return StepOutput(
            content=f"Research post-processing failed: {str(e)}",
            success=False,
            error=str(e)
        )

# Complex workflow combining multiple patterns
workflow = Workflow(
    name="Advanced Multi-Pattern Workflow",
    steps=[
        Parallel(
            Condition(
                name="Tech Check",
                evaluator=is_tech_topic,
                steps=[Step(name="Tech Research", agent=tech_researcher)]
            ),
            Condition(
                name="Business Check",
                evaluator=is_business_topic,
                steps=[
                    Loop(
                        name="Deep Business Research",
                        steps=[Step(name="Market Research", agent=market_researcher)],
                        end_condition=research_quality_check,
                        max_iterations=3
                    )
                ]
            ),
            name="Conditional Research Phase"
        ),
        Step(
            name="Research Post-Processing",
            executor=research_post_processor,
            description="Consolidate and analyze research findings with quality metrics"
        ),
        Router(
            name="Content Type Router",
            selector=content_type_selector,
            choices=[blog_post_step, social_media_step, report_step]
        ),
        Step(name="Final Review", agent=reviewer),
    ]
)

workflow.print_response("Create a comprehensive analysis of sustainable technology trends and their business impact for 2024", markdown=True)
More Examples: