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

# Conditional Edges

> Implement dynamic routing and control flow in your multi-agent workflows based on agent outputs and state

Conditional edges enable dynamic routing in your agent workflows. Instead of following a fixed path, agents can route to different next steps based on their output, state, or structured data.

## Overview

Conditional edges allow you to:

* **Route based on classification**: Send content to different agents based on categories
* **Implement quality gates**: Retry or revise work that doesn't meet standards
* **Create decision trees**: Branch workflows based on agent decisions
* **Build adaptive systems**: Change behavior based on runtime conditions

<Info>
  Conditional edges enable dynamic routing in workflows, allowing agents to make runtime decisions about which path to take next.
</Info>

## How Conditional Edges Work

In a standard workflow, edges are static:

```yaml theme={null}
edges:
  - from: "agent_a"
    to: "agent_b"  # Always goes to agent_b
```

With conditional edges, the next step is determined at runtime:

```yaml theme={null}
edges:
  - from: "classifier"
    condition: "Route to the appropriate team based on {{classifier.output.category}}"
    condition_type: "literal"
    possible_outputs: ["tech_support", "billing_support", "general_support"]
```

## Conditional Edge Types

There are two types of conditional edges:

### 1. Boolean Edges

For binary yes/no decisions (quality gates, approvals):

````yaml theme={null}
edges:
  - from: "agent_name"
    condition: "Your decision prompt with {{agent_name.output.field}}"
    condition_type: "boolean"
    routing:
      yes: "success_agent"
      no: "failure_agent"
    llm_model: "gemini-1.5-pro"  # Optional: specific model for evaluation

**Required fields:**
- `condition`: Template string with variable substitution
- `condition_type`: Must be `"boolean"`
- `routing`: Dict with `yes` and `no` keys mapping to agent names

**Optional fields:**
- `llm_model`: Specific model to use for this routing decision. Must be compatible with BAML (e.g., `gemini-1.5-pro`, `mistral-large-latest`).

### 2. Literal Edges

For multi-way routing based on specific values:

```yaml
edges:
  - from: "agent_name"
    condition: "Route based on {{agent_name.output.category}}"
    condition_type: "literal"
    possible_outputs: ["agent_a", "agent_b", "agent_c"]
    llm_model: "gemini-1.5-pro"  # Optional override
````

**Required fields:**

* `condition`: Template string with variable substitution
* `condition_type`: Must be `"literal"`
* `possible_outputs`: List of valid agent names to route to

**Optional fields:**

* `llm_model`: Specific model to use for this routing decision. Must be compatible with BAML.

## Basic Conditional Routing

### Boolean Routing (Quality Gates)

Route based on true/false conditions:

```yaml theme={null}
name: "Content Quality Gate"
description: "Review and revise content until it meets quality standards"
architecture: "workflow"

agents:
  - name: "writer"
    agent_type: "llm_agent"
    system_prompt: "Write a blog post on the given topic."
  
  - name: "quality_checker"
    agent_type: "llm_agent"
    
    system_prompt: |
      Review the blog post for quality. Check for:
      - Clear and engaging writing
      - Proper grammar and spelling
      - Logical structure
      - Appropriate length
      
      Determine if it passes quality standards.
    
    structured_output:
      enabled: true
      schema:
        passes_quality:
          type: "bool"
          description: "Whether the content meets quality standards"
        
        issues:
          type: "list[str]"
          description: "List of quality issues found"
        
        suggestions:
          type: "list[str]"
          description: "Suggestions for improvement"
  
  - name: "reviser"
    agent_type: "llm_agent"
    system_prompt: |
      Revise the blog post based on the quality feedback provided.
      Address all issues and implement suggestions.
  
  - name: "publisher"
    agent_type: "llm_agent"
    system_prompt: "Format and publish the approved blog post."

edges:
  - from: "__start__"
    to: "writer"
  
  - from: "writer"
    to: "quality_checker"
  
  # Conditional edge based on quality check
  - from: "quality_checker"
    condition: "Does the content pass quality standards? Check {{quality_checker.output.passes_quality}}"
    condition_type: "boolean"
    routing:
      yes: "publisher"      # If passes_quality = true
      no: "reviser"         # If passes_quality = false
  
  - from: "reviser"
    to: "quality_checker"    # Re-check after revision
  
  - from: "publisher"
    to: "__end__"

entry_point: "writer"
```

### Multi-Way Routing (Classification)

Route to different agents based on categories:

```yaml theme={null}
name: "Customer Support Router"
description: "Route support tickets to appropriate departments"
architecture: "workflow"

agents:
  - name: "ticket_classifier"
    agent_type: "llm_agent"
    
    system_prompt: |
      Analyze the customer support ticket and classify it into one of these categories:
      - technical: Technical issues, bugs, errors
      - billing: Payment, invoices, subscription questions
      - general: General inquiries, feedback, other
    
    structured_output:
      enabled: true
      schema:
        category:
          type: "str"
          description: "Support ticket category (technical, billing, or general)"
        
        priority:
          type: "str"
          description: "Ticket priority level (low, medium, high, or urgent)"
        
        summary:
          type: "str"
          description: "Brief summary of the issue"
  
  - name: "tech_support"
    agent_type: "react_agent"
    tools: ["knowledge_base_search", "bug_tracker"]
    system_prompt: "Handle technical support issues. Search knowledge base and create bug reports if needed."
  
  - name: "billing_support"
    agent_type: "react_agent"
    tools: ["payment_system", "invoice_generator"]
    system_prompt: "Handle billing and payment inquiries. Access payment history and generate invoices."
  
  - name: "general_support"
    agent_type: "llm_agent"
    system_prompt: "Handle general customer inquiries with friendly, helpful responses."

edges:
  - from: "__start__"
    to: "ticket_classifier"
  
  # Multi-way conditional routing
  - from: "ticket_classifier"
    condition: "Route to the appropriate support team based on {{ticket_classifier.output.category}}"
    condition_type: "literal"
    possible_outputs: ["tech_support", "billing_support", "general_support"]
  
  - from: "tech_support"
    to: "__end__"
  
  - from: "billing_support"
    to: "__end__"
  
  - from: "general_support"
    to: "__end__"

entry_point: "ticket_classifier"
```

## Using with Structured Output

For reliable routing, use structured output to control conditional edges:

```yaml theme={null}
agents:
  - name: "classifier"
    agent_type: "llm_agent"
    
    structured_output:
      enabled: true
      schema:
        category:
          type: "str"
          description: "Category: technical, billing, or general"
        priority:
          type: "str"
          description: "Priority: low, medium, or high"

edges:
  - from: "classifier"
    condition: "Route by category: {{classifier.output.category}}"
    condition_type: "literal"
    possible_outputs: ["tech_team", "billing_team", "general_team"]
```

<Tip>
  Structured output ensures consistent, predictable routing decisions
</Tip>

## Loop-Back Edges

Conditional edges can route back to a previous agent, creating loops for iterative refinement. Use `recursion_limit` at the system level to prevent infinite cycles:

```yaml theme={null}
name: "Iterative Refinement"
architecture: "workflow"
recursion_limit: 20

agents:
  - name: "drafter"
    agent_type: "llm_agent"
    prompt_config:
      system_prompt: "Draft a response based on the user's request."

  - name: "reviewer"
    agent_type: "llm_agent"
    structured_output:
      enabled: true
      schema:
        approved:
          type: "bool"
          description: "Whether the draft meets quality standards"

edges:
  - from: "__start__"
    to: "drafter"
  - from: "drafter"
    to: "reviewer"
  - from: "reviewer"
    condition: "Is the draft approved? {{reviewer.output.approved}}"
    condition_type: "boolean"
    routing:
      yes: "__end__"
      no: "drafter"     # Loop back to drafter for revision

entry_point: "drafter"
```

<Warning>
  Always set `recursion_limit` when using loop-back edges. The default limit is 5 steps (configurable via environment variables). Without a sufficient limit, the workflow may terminate early.
</Warning>

## Conditional Routing from START

You can use a conditional edge from `__start__` to dynamically select the first agent based on user input. Set `entry_point` to `"START"` to enable this:

```yaml theme={null}
name: "Dynamic Entry Router"
architecture: "workflow"
entry_point: "START"

agents:
  - name: "simple_handler"
    agent_type: "llm_agent"
    prompt_config:
      system_prompt: "Handle simple questions directly."

  - name: "research_handler"
    agent_type: "react_agent"
    tools: ["tavily_search"]
    prompt_config:
      system_prompt: "Research complex questions using web search."

edges:
  - from: "__start__"
    condition: "Based on the user's question: {{user_input}}, determine if this is a simple question or requires research."
    condition_type: "literal"
    possible_outputs: ["simple_handler", "research_handler"]
  - from: "simple_handler"
    to: "__end__"
  - from: "research_handler"
    to: "__end__"
```

<Info>
  When `entry_point` is `"START"`, no automatic edge from `__start__` to an agent is created. You must define your own edge from `__start__` (either static or conditional).
</Info>

## How Evaluation Works

Under the hood, conditional edges use a multi-step evaluation pipeline:

1. **Variable substitution**: Template variables like `{{agent.output.field}}` are replaced with actual values from the workflow state
2. **LLM evaluation**: The substituted condition is sent to an LLM via [BAML](https://docs.boundaryml.com/) structured output for reliable parsing. This uses the default model unless overridden by `llm_model`.
3. **Validation**: The LLM's response is validated (against `possible_outputs` for literal, or `yes`/`no` for boolean)
4. **Retry logic**: If the response is invalid, the evaluation is retried up to 3 times with a 1-second delay
5. **Fallback**: If all retries fail, the edge routes to `__end__` to terminate the workflow gracefully

<Info>
  The BAML evaluation returns both a routing decision and a reasoning explanation. The reasoning is included in observability events for debugging.
</Info>

## Template Variables in Conditions

Condition templates support the same `{{ }}` syntax as agent prompts:

| Variable                          | Description                                           |
| --------------------------------- | ----------------------------------------------------- |
| `{{agent_name.output.field}}`     | Structured output field from a previous agent         |
| `{{agent_name.output}}`           | Full text output from a previous agent (last message) |
| `{{user_input}}`                  | The current user message                              |
| `{{history}}` or `{{history[N]}}` | Conversation history (all or last N messages)         |
| `{{variables.var_name}}`          | Global workflow variable                              |

## Special Node Names

Both `__start__`/`__end__` and `START`/`END` are valid node names in edges. They are normalized internally:

```yaml theme={null}
# These are equivalent:
- from: "__start__"
  to: "agent_a"

- from: "START"
  to: "agent_a"
```

## Best Practices

<Tip>
  **Use Structured Output**: Always use structured output with `str` fields for conditional routing. Specify allowed values clearly in descriptions and system prompts to ensure reliable, predictable routing decisions.
</Tip>

<Tip>
  **Clear Conditions**: Make routing conditions explicit and mutually exclusive. Avoid ambiguous categories.
</Tip>

<Tip>
  **Limit Iterations**: Set `recursion_limit` when using loop-back edges. The default is 5 steps, which may be too low for iterative workflows.
</Tip>

<Warning>
  **Handle All Cases**: Ensure every possible output value has a corresponding route. If the LLM returns an invalid value, the edge will retry up to 3 times, then fall back to `__end__`.
</Warning>

<Tip>
  **Test Edge Cases**: Test your conditional logic with edge cases and unexpected inputs.
</Tip>

## Common Use Cases

**Quality Gates**: Check if work meets standards → approve or send for revision

**Classification**: Categorize inputs → route to specialized handlers

**Escalation**: Try automated solution → escalate to human if needed

**Iterative Refinement**: Generate → evaluate → improve until acceptable

<Warning>
  Conditional edges only work with `workflow` architecture, not with `supervisor` or single agents
</Warning>

<Warning>
  For literal edges, every value in `possible_outputs` must be a valid agent name defined in the `agents` list
</Warning>

## Next Steps

<CardGroup cols={2}>
  <Card title="Structured Output" icon="table" href="/documentation/advanced/structured-output">
    Learn how to define schemas for reliable conditional routing
  </Card>

  <Card title="Sequential Patterns" icon="arrow-right" href="/documentation/advanced/sequential-patterns">
    Build linear pipelines with static edges
  </Card>

  <Card title="Supervisor Pattern" icon="users" href="/documentation/advanced/supervisor-pattern">
    Use dynamic routing without explicit edges
  </Card>

  <Card title="YAML Configuration" icon="file-code" href="/documentation/yaml-configuration">
    Complete guide to workflow and edge configuration
  </Card>
</CardGroup>
