# Langgraph Routing

> LangGraph conditional routing patterns. Use when implementing dynamic routing based on state, creating branching workflows, or building retry loops with conditional edges.

- Skill: `majiayu000/langgraph-routing-2` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add majiayu000/langgraph-routing-2`
- Raw SKILL.md: https://api.skillmd.com/api/skills/majiayu000/langgraph-routing-2/raw
- Safety review: pending (external: skill-scanner PASS, skillspector PASS)
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: majiayu000 (https://skillmd.com/u/majiayu000)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/majiayu000/langgraph-routing-2

---


# LangGraph Conditional Routing

Route workflow execution dynamically based on state.

## When to Use

- Dynamic branching based on results
- Retry loops with backoff
- Quality gates with pass/fail paths
- Multi-path workflows

## Basic Conditional Edge

```python
from langgraph.graph import StateGraph, END

def route_based_on_quality(state: WorkflowState) -> str:
    """Decide next step based on quality score."""
    if state["quality_score"] >= 0.8:
        return "publish"
    elif state["retry_count"] < 3:
        return "retry"
    else:
        return "manual_review"

workflow.add_conditional_edges(
    "quality_check",
    route_based_on_quality,
    {
        "publish": "publish_node",
        "retry": "generator",
        "manual_review": "review_queue"
    }
)
```

## Quality Gate Pattern

```python
def route_after_quality_gate(state: AnalysisState) -> str:
    """Route based on quality gate result."""
    if state["quality_passed"]:
        return "compress_findings"
    elif state["retry_count"] < 2:
        return "supervisor"  # Retry
    else:
        return END  # Return partial results

workflow.add_conditional_edges(
    "quality_gate",
    route_after_quality_gate,
    {
        "compress_findings": "compress_findings",
        "supervisor": "supervisor",
        END: END
    }
)
```

## Retry Loop Pattern

```python
def llm_call_with_retry(state):
    """Retry failed LLM calls."""
    try:
        result = call_llm(state["input"])
        state["output"] = result
        state["retry_count"] = 0
        return state
    except Exception as e:
        state["retry_count"] += 1
        state["error"] = str(e)
        return state

def should_retry(state) -> str:
    if state.get("output"):
        return "success"
    elif state["retry_count"] < 3:
        return "retry"
    else:
        return "failed"

workflow.add_conditional_edges(
    "llm_call",
    should_retry,
    {
        "success": "next_step",
        "retry": "llm_call",  # Loop back
        "failed": "error_handler"
    }
)
```

## Routing Patterns

```
Sequential:    A → B → C              (simple edges)
Branching:     A → (B or C)           (conditional edges)
Looping:       A → B → A              (retry logic)
Convergence:   (A or B) → C           (multiple inputs)
Diamond:       A → (B, C) → D         (parallel then merge)
```

## State-Based Router

```python
def dynamic_router(state: WorkflowState) -> str:
    """Route based on multiple state conditions."""
    if state.get("error"):
        return "error_handler"
    if not state.get("validated"):
        return "validator"
    if state["confidence"] < 0.5:
        return "enhance"
    return "finalize"
```

## Key Decisions

| Decision | Recommendation |
|----------|----------------|
| Max retries | 2-3 for LLM calls |
| Fallback | Always have END fallback |
| Routing function | Keep pure (no side effects) |
| Edge mapping | Explicit mapping for clarity |

## Common Mistakes

- No END fallback (workflow hangs)
- Infinite loops (no max retry)
- Side effects in router (hard to debug)
- Missing edge mappings (runtime error)

## Related Skills

- `langgraph-state` - State design for routing
- `langgraph-supervisor` - Supervisor routing pattern
- `agent-loops` - ReAct loop patterns

