> ## Documentation Index
> Fetch the complete documentation index at: https://praison.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Workflow Diagram

> Render a workflow's definition as a mermaid diagram before it runs

See your workflow before it runs.

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent, AgentFlow

researcher = Agent(name="Researcher", instructions="Research the topic.")
writer     = Agent(name="Writer",     instructions="Write a summary.")

flow = AgentFlow(steps=[researcher, writer], name="review flow")
print(flow.to_mermaid())
```

`flow.to_mermaid()` reads the step list and returns a mermaid `graph TD` string — no execution, no cost.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    F[🧩 AgentFlow] -->|to_mermaid| S[📝 mermaid string]
    S --> P[🖼️ rendered picture]

    classDef flow    fill:#8B0000,stroke:#7C90A0,color:#fff
    classDef process fill:#189AB4,stroke:#7C90A0,color:#fff
    classDef result  fill:#10B981,stroke:#7C90A0,color:#fff
    class F flow
    class S process
    class P result
```

## Quick Start

**1. Print a diagram**

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent, AgentFlow

researcher = Agent(name="Researcher", instructions="Research the topic.")
writer     = Agent(name="Writer",     instructions="Write a summary.")

flow = AgentFlow(steps=[researcher, writer], name="review flow")
print(flow.to_mermaid())
```

Output:

```
graph TD
  n0(["review flow"])
  n1["Researcher"]
  n0 --> n1
  n2["Writer"]
  n1 --> n2
  n3([" end "])
  n2 --> n3
```

**2. Preview a branching flow**

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent, AgentFlow, Parallel, If

flow = AgentFlow(
    name="review flow",
    steps=[
        Agent(name="research"),
        Parallel(steps=[Agent(name="summarise"), Agent(name="fact-check")]),
        If(
            condition="{{score}} > 80",
            then_steps=[Agent(name="approve")],
            else_steps=[Agent(name="revise")],
        ),
    ],
)

print(flow.to_mermaid())
```

The string renders inline on GitHub and in docs:

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph TD
  n0(["review flow"])
  n1["research"]
  n0 --> n1
  n2(("fork"))
  n1 --> n2
  n3["summarise"]
  n2 --> n3
  n4["fact-check"]
  n2 --> n4
  n5(("join"))
  n3 --> n5
  n4 --> n5
  n6{"{{score}} > 80"}
  n5 --> n6
  n7["approve"]
  n6 -->|"true"| n7
  n8["revise"]
  n6 -->|"false"| n8
  n9(("join"))
  n7 --> n9
  n8 --> n9
  n10([" end "])
  n9 --> n10
```

***

## How It Works

The renderer walks the step list — no run, no LLM calls.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    Steps[📋 steps] --> Renderer[⚙️ renderer]
    Renderer --> Str[📝 mermaid string]

    classDef input   fill:#6366F1,stroke:#7C90A0,color:#fff
    classDef process fill:#189AB4,stroke:#7C90A0,color:#fff
    classDef result  fill:#10B981,stroke:#7C90A0,color:#fff
    class Steps input
    class Renderer process
    class Str result
```

A step's label resolves in order: `step.name` → `step.__name__` → `step.agent.name` → the string itself → the class name. Special characters are handled for you — a `"` becomes `'` and newlines become spaces, so a name can never break the graph.

***

## How Each Step Type Renders

Each step type maps to a mermaid shape.

| Step type | How it renders |
| - | - |
| Plain step (Agent, Task, callable, or string) | Rectangle node `["name"]` |
| `Parallel(steps=[...])` | `(("fork"))` → one edge per branch → `(("join"))` |
| `If(condition=..., then_steps=..., else_steps=...)` | Decision diamond `{"condition"}` with `\|"true"\|` and (if present) `\|"false"\|` edges, joined by `(("join"))` |
| `Route(routes={...})` | Router diamond `{"route"}` with one labelled edge per route key, joined by `(("join"))` |
| `Loop(...)` / `Repeat(...)` | Inner steps, then a labelled back-edge to the first inner node — `"over {items}"`, `"up to {n}x"`, or `"repeat"` |
| `Include(workflow=<Workflow>)` | Workflow inlined — its steps render in place |
| `Include(recipe="...")` | Stays a single opaque node — the recipe resolves only at runtime |

A control nested inside a branch (an `If` inside another `If`) enters at its own decision, not at its parent's exit, so it is never bypassed.

Full example combining `Parallel`, `If`, and `Repeat`:

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent, AgentFlow, Parallel, If, Repeat

flow = AgentFlow(
    name="review flow",
    steps=[
        Agent(name="research"),
        Parallel(steps=[Agent(name="summarise"), Agent(name="fact-check")]),
        If(
            condition="{{score}} > 80",
            then_steps=[Agent(name="approve")],
            else_steps=[Agent(name="revise")],
        ),
        Repeat(Agent(name="polish"), max_iterations=3),
    ],
)

print(flow.to_mermaid())
```

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph TD
  n0(["review flow"])
  n1["research"]
  n0 --> n1
  n2(("fork"))
  n1 --> n2
  n3["summarise"]
  n2 --> n3
  n4["fact-check"]
  n2 --> n4
  n5(("join"))
  n3 --> n5
  n4 --> n5
  n6{"{{score}} > 80"}
  n5 --> n6
  n7["approve"]
  n6 -->|"true"| n7
  n8["revise"]
  n6 -->|"false"| n8
  n9(("join"))
  n7 --> n9
  n8 --> n9
  n10["polish"]
  n9 --> n10
  n10 -->|"up to 3x"| n10
  n11([" end "])
  n10 --> n11
```

***

## Common Patterns

Sanity-check a flow before running it:

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
print(flow.to_mermaid())
flow.start("Latest breakthroughs in AI agents")
```

Save the diagram to a file:

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from pathlib import Path

Path("flow.mmd").write_text(flow.to_mermaid())
```

Embed in a README — paste the output inside a fenced `mermaid` block and GitHub renders it inline:

````markdown theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
```mermaid
graph TD
  n0(["review flow"])
  n1["Researcher"]
  n0 --> n1
```
````

***

## Best Practices

> [accordion] Name your steps
>
> Give each step a `name=` so labels read cleanly. The fallback chain is `name` → `__name__` → `agent.name` → string → class name, so unnamed callables show up as their function or class name.

> [accordion] Prefer to\_mermaid() over the telemetry trace for unrun flows
>
> Telemetry diagrams need a captured execution — they only exist after a flow has run. `to_mermaid()` works on the definition alone, so use it to check a flow you haven't run yet.

> [accordion] Nested controls stay connected
>
> An `If` inside an `If`, or a `Parallel` inside a route branch, works. The renderer wires each control through its own decision or fork, so nothing is bypassed.

> [accordion] Expand includes with a workflow, not a recipe
>
> `Include(workflow=...)` inlines the included steps because they are known at definition time. `Include(recipe="...")` stays a single node — the recipe resolves only at runtime. Use `workflow=` if you want it expanded in the picture.

***

## Related

> [card] [Workflows](https://praison.ai/docs/features/workflows.md)
>
> Build sequential, parallel, routed, and looped pipelines with AgentFlow.

> [card] [Workflow Patterns](https://praison.ai/docs/features/workflow-patterns.md)
>
> Reusable shapes for common orchestration scenarios.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.