26 minute read

LangGraph Conditional Edges Example: If-Else Logic for AI Workflows

Imagine you have a super smart robot friend. This robot needs to make choices, just like you do every day! For example, if you ask it a question, it should answer. But if you tell it a joke, it should laugh! How does the robot know what to do?

This is where something called “if-else logic” comes in. It’s like telling the robot: “IF the user asks a question, THEN answer it. ELSE (otherwise), IF the user tells a joke, THEN laugh.” This is how computers make decisions.

Now, imagine building a super smart AI that’s like a big, complex robot brain. We want this brain to make many choices and follow different paths based on what happens. LangGraph helps us build these complex AI brains, and its langgraph if-else conditional edges are like the special decision points that guide our AI.

Making Decisions: Why Our AI Needs Choices

Think about your daily life. You make tiny decisions all the time, right? If it’s sunny, you might go outside; else, if it’s rainy, you stay inside. AI systems also need to make these kinds of choices to be truly helpful.

Without choices, an AI would always do the same thing, no matter what. This would be like a toy car that only drives straight – not very fun or useful! Our AI needs to be flexible and smart about what to do next.

For example, a customer service AI might need to decide: “Is the customer asking about an order, or are they complaining?” Each choice leads to a different path for the AI to follow. These decision points are crucial for a truly dynamic and helpful AI.

The Problem with Fixed Paths

Imagine you have a simple game where your character can only walk forward. It’s not much of a game, is it? Most real games, and real-world AI, need many different paths.

If an AI always followed a straight line, it couldn’t adapt to new information. It wouldn’t know how to handle different user requests or unexpected situations. This is why we need tools to create converting if-else to graphs, making decisions clear.

We want our AI to be like a choose-your-own-adventure book. Every time it gets new information, it should be able to pick the best next chapter. LangGraph helps us draw these adventure maps with clear decision points.

How We Usually Make Decisions in Code

When you first learn to code, you learn about if statements. It looks something like this in Python:

1
2
3
4
5
6
user_mood = "happy"

if user_mood == "happy":
    print("Let's tell a happy story!")
else:
    print("Let's try to cheer you up.")

This is simple and works great for small programs. But what if your AI has many steps and many possible decisions? What if these decisions depend on things that happened many steps ago?

Putting all these if and else statements inside one big piece of code can get messy. It’s hard to see the whole picture of how your AI will behave. We need a clearer, more organized way to show these decisions, especially for big AI brains.

Introducing LangGraph: Drawing Your AI’s Brain

LangGraph is like a drawing board for your AI’s brain. You draw “nodes” which are like little tasks or actions your AI can do. Then you draw “edges” which are the lines connecting these tasks, showing how the AI moves from one task to the next.

Think of a node as a small worker. One worker might “understand the question,” another might “search for an answer,” and a third might “tell a joke.” Each worker does one specific job.

Normally, an edge just says, “After worker A finishes, go straight to worker B.” But what if we want to add a decision point? This is where langgraph if-else conditional edges come in, making our AI much smarter.

Nodes: The Actions of Your AI

In LangGraph, a “node” is just a step your AI takes. It could be anything! For example, one node might be called check_user_mood. Another node might be generate_happy_response.

Each node has a job, and it does that job when it’s its turn. When a node finishes its job, it passes along any information it gathered to the next step. This information is called the “state” of our AI.

Edges: The Paths Between Actions

Edges are the connections that guide your AI from one node to another. They are like roads on a map. A simple edge might say, “Always go from Node A to Node B.”

But what if we don’t always want to go from A to B? What if we want to go from A to B sometimes and from A to C other times? This is where conditional edges make LangGraph super powerful. They let our AI choose its path dynamically.

The Magic of Conditional Edges

Conditional edges are the secret sauce for making your LangGraph AI smart and flexible. Instead of just drawing a line from A to B, you draw a line that says, “Go from A, but THEN, based on some choice, go to B OR C OR D.” This is like a traffic light that decides which way cars should go.

How does it work? You tell LangGraph to use a special decision-making function. This function looks at the “state” (what’s happened so far in your AI’s journey) and decides where to go next. It’s like a little brain inside your big AI brain!

This function needs to return the name of the next node (or nodes) your AI should visit. If it returns “node_B”, then the AI goes to node B. If it returns “node_C”, it goes to node C. This is the core idea behind boolean condition routing.

Simple Conditional Examples: Making One Choice

Let’s start with a very simple example. Imagine your AI needs to decide if a user is happy or sad.

A Basic Yes/No Question

Suppose your AI has a node that figures out the user’s mood. After this check_mood node, we want to go to a happy_response node if they are happy, or a sad_response node if they are sad.

First, we need to define our “state.” The state is like a shared memory for all our AI’s steps. Let’s say our state will remember the mood.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
from typing import Literal
from langgraph.graph import StateGraph, START, END

# Define the state for our AI
class MoodState:
    mood: Literal["happy", "sad"] | None = None
    response: str = ""

# Define our nodes (the actions our AI can take)
def check_user_mood(state: MoodState) -> MoodState:
    # In a real AI, this would analyze user input
    # For this example, let's just pretend we detected "happy"
    print("AI checked user mood.")
    state.mood = "happy" # Or "sad" for another test
    return state

def generate_happy_response(state: MoodState) -> MoodState:
    print("AI is generating a happy response.")
    state.response = "That's great to hear! Let me tell you a happy story."
    return state

def generate_sad_response(state: MoodState) -> MoodState:
    print("AI is generating a sad response.")
    state.response = "Oh no, I'm sorry to hear that. How can I help?"
    return state

Now, here’s the magic conditional function. It looks at the mood in the state and decides where to go. This is a perfect example of binary decision workflows.

1
2
3
4
5
6
7
# This is our conditional function
def decide_next_path(state: MoodState) -> str:
    print(f"Deciding next path based on mood: {state.mood}")
    if state.mood == "happy":
        return "happy_response"
    else:
        return "sad_response"

Now we build our LangGraph using these parts:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# Build the graph
workflow = StateGraph(MoodState)

# Add our nodes
workflow.add_node("check_mood", check_user_mood)
workflow.add_node("happy_response", generate_happy_response)
workflow.add_node("sad_response", generate_sad_response)

# Set the entry point
workflow.set_entry_point("check_mood")

# Add the conditional edge!
# From "check_mood", we use "decide_next_path" to choose.
# The choices are "happy_response" or "sad_response".
# After these responses, we go to END.
workflow.add_conditional_edges(
    "check_mood",
    decide_next_path,
    {
        "happy_response": "happy_response",
        "sad_response": "sad_response",
    },
)

# After the response nodes, we want to stop
workflow.add_edge("happy_response", END)
workflow.add_edge("sad_response", END)

# Compile the graph
app = workflow.compile()

# Let's run it!
initial_state = MoodState(mood=None, response="")
final_state = app.invoke(initial_state)
print("--- Final Result ---")
print(final_state.response)

In this example, after check_mood runs, the decide_next_path function looks at the mood variable in the state. If mood is “happy,” it tells LangGraph to go to happy_response. If mood is “sad” (or anything else), it tells LangGraph to go to sad_response. This is how we implement langgraph if-else conditional edges very simply.

Checking User Input Type

Let’s try another one. What if your AI needs to know if the user gave it a number or just text? This is a great example of using condition function patterns.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import re # For checking numbers
from typing import Literal

# Define state to hold user input and type
class InputState:
    user_input: str = ""
    input_type: Literal["number", "text"] | None = None
    processed_message: str = ""

# Nodes
def get_user_input(state: InputState) -> InputState:
    print("AI is getting user input.")
    # In a real app, you'd get this from the user
    state.user_input = "12345" # Test with "hello world" too
    return state

def identify_input_type(state: InputState) -> InputState:
    print(f"AI is identifying input type for: '{state.user_input}'")
    if re.match(r"^\d+$", state.user_input): # Checks if it's only digits
        state.input_type = "number"
    else:
        state.input_type = "text"
    return state

def process_number(state: InputState) -> InputState:
    print("AI is processing a number.")
    num = int(state.user_input)
    state.processed_message = f"You gave me the number: {num}. Double it: {num * 2}!"
    return state

def process_text(state: InputState) -> InputState:
    print("AI is processing text.")
    state.processed_message = f"You gave me the text: '{state.user_input}'. I can make it uppercase: {state.user_input.upper()}."
    return state

# Conditional function
def route_by_input_type(state: InputState) -> str:
    print(f"Routing based on input type: {state.input_type}")
    if state.input_type == "number":
        return "number_path"
    else:
        return "text_path"

# Build the graph
workflow = StateGraph(InputState)

workflow.add_node("get_input", get_user_input)
workflow.add_node("identify_type", identify_input_type)
workflow.add_node("process_number_node", process_number)
workflow.add_node("process_text_node", process_text)

workflow.set_entry_point("get_input")
workflow.add_edge("get_input", "identify_type")

workflow.add_conditional_edges(
    "identify_type",
    route_by_input_type,
    {
        "number_path": "process_number_node",
        "text_path": "process_text_node",
    },
)

workflow.add_edge("process_number_node", END)
workflow.add_edge("process_text_node", END)

app = workflow.compile()

# Run with a number
print("--- Running with a number ---")
result_number = app.invoke(InputState(user_input="")) # user_input will be set by get_user_input
print(result_number.processed_message)

print("\n--- Running with text ---")
# To test with text, we need to modify get_user_input or set initial state
# For simplicity, let's modify get_user_input for the second run or directly set input_type
# A cleaner way would be to have different initial states for invoke
test_text_state = InputState(user_input="hello world", input_type="text") # Bypass get_user_input for this test
# Or, if get_user_input needs to run:
# Modify get_user_input temporarily to set text:
# def get_user_input_text(state: InputState) -> InputState:
#     state.user_input = "hello world"
#     return state
# workflow_for_text = StateGraph(InputState)
# workflow_for_text.add_node("get_input", get_user_input_text)
# ... rest of the graph ...
# app_text = workflow_for_text.compile()
# result_text = app_text.invoke(InputState(user_input=""))
# print(result_text.processed_message)

# For simpler demo, let's manually invoke from 'identify_type' after setting a text input
# In real scenarios, you might have different initial inputs leading to the same graph.
manual_text_state = InputState(user_input="hello world")
# Simulate running get_user_input and identify_input_type
manual_text_state = get_user_input(manual_text_state)
manual_text_state = identify_input_type(manual_text_state)
# Now invoke from the decision point onwards
result_text = app.invoke(manual_text_state, config={"recursion_limit": 100}) # Start from identify_type
print(result_text.processed_message)

# To truly run two different paths from START:
# We would modify the get_user_input function for each test or pass the initial input directly if the graph was designed for it.
# Let's update get_user_input to accept an input parameter for better testing

Let’s refine the get_user_input for better testing:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
from typing import TypedDict, Literal
import re
from langgraph.graph import StateGraph, START, END

# Define state to hold user input and type
class InputState(TypedDict):
    user_input: str
    input_type: Literal["number", "text"] | None
    processed_message: str

# Nodes
def get_user_input_node(state: InputState) -> InputState:
    print(f"AI is getting user input. Current input: {state.get('user_input')}")
    # This node could get input from an external source or use initial state
    # For testing, we'll assume 'user_input' is already in the initial state
    return state # Just passes the state along

def identify_input_type_node(state: InputState) -> InputState:
    user_input = state["user_input"]
    print(f"AI is identifying input type for: '{user_input}'")
    if re.match(r"^\d+$", user_input):
        state["input_type"] = "number"
    else:
        state["input_type"] = "text"
    return state

def process_number_node(state: InputState) -> InputState:
    print("AI is processing a number.")
    num = int(state["user_input"])
    state["processed_message"] = f"You gave me the number: {num}. Double it: {num * 2}!"
    return state

def process_text_node(state: InputState) -> InputState:
    print("AI is processing text.")
    state["processed_message"] = f"You gave me the text: '{state['user_input']}'. I can make it uppercase: {state['user_input'].upper()}."
    return state

# Conditional function
def route_by_input_type_func(state: InputState) -> str:
    print(f"Routing based on input type: {state.get('input_type')}")
    if state["input_type"] == "number":
        return "number_path"
    else:
        return "text_path"

# Build the graph
workflow = StateGraph(InputState)

workflow.add_node("get_input_from_state", get_user_input_node)
workflow.add_node("identify_type", identify_input_type_node)
workflow.add_node("process_number_node", process_number_node)
workflow.add_node("process_text_node", process_text_node)

workflow.set_entry_point("get_input_from_state")
workflow.add_edge("get_input_from_state", "identify_type")

workflow.add_conditional_edges(
    "identify_type",
    route_by_input_type_func,
    {
        "number_path": "process_number_node",
        "text_path": "process_text_node",
    },
)

workflow.add_edge("process_number_node", END)
workflow.add_edge("process_text_node", END)

app = workflow.compile()

# Run with a number
print("--- Running with a number ---")
initial_number_state: InputState = {"user_input": "12345", "input_type": None, "processed_message": ""}
result_number = app.invoke(initial_number_state)
print(result_number["processed_message"])

print("\n--- Running with text ---")
initial_text_state: InputState = {"user_input": "hello world", "input_type": None, "processed_message": ""}
result_text = app.invoke(initial_text_state)
print(result_text["processed_message"])

In this revised example, the initial state user_input determines the path. The identify_type node then runs, setting input_type in the state. Finally, route_by_input_type_func reads input_type and directs the flow to either process_number_node or process_text_node. This clearly shows true/false routing based on a specific condition.

Building More Complex Choices: Multiple Paths

Sometimes, you need more than just a “yes” or “no” decision. What if your AI needs to choose from three, four, or even more options? LangGraph handles this beautifully with the same conditional edge idea.

More Than Two Options

Imagine a chatbot that needs to understand what a user wants. Are they asking a question, giving a command, or just saying hello? This requires more than two options.

Your conditional function can return different strings, and each string matches a different path in your graph. This is where condition function patterns become very useful, allowing for flexible routing.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
from typing import TypedDict, Literal
from langgraph.graph import StateGraph, START, END

class UserIntentState(TypedDict):
    user_message: str
    intent: Literal["question", "command", "greeting", "unknown"] | None
    response: str

# Nodes for different actions
def analyze_intent(state: UserIntentState) -> UserIntentState:
    message = state["user_message"].lower()
    print(f"AI analyzing intent for: '{message}'")
    if "hello" in message or "hi" in message:
        state["intent"] = "greeting"
    elif "?" in message:
        state["intent"] = "question"
    elif "please" in message or "do this" in message:
        state["intent"] = "command"
    else:
        state["intent"] = "unknown"
    return state

def handle_greeting(state: UserIntentState) -> UserIntentState:
    print("AI handling greeting.")
    state["response"] = "Hello there! How can I help you today?"
    return state

def handle_question(state: UserIntentState) -> UserIntentState:
    print("AI handling question.")
    state["response"] = f"That's a great question about '{state['user_message']}'! Let me find an answer."
    return state

def handle_command(state: UserIntentState) -> UserIntentState:
    print("AI handling command.")
    state["response"] = f"Okay, I'll try to execute the command: '{state['user_message']}'. Give me a moment."
    return state

def handle_unknown(state: UserIntentState) -> UserIntentState:
    print("AI handling unknown intent.")
    state["response"] = "I'm not sure how to respond to that. Could you please rephrase or tell me what you need?"
    return state

# Conditional function for multiple choices
def route_by_intent(state: UserIntentState) -> str:
    print(f"Routing based on intent: {state.get('intent')}")
    if state["intent"] == "greeting":
        return "greet"
    elif state["intent"] == "question":
        return "ask"
    elif state["intent"] == "command":
        return "command"
    else:
        return "unknown" # Fallback for anything else

Now, let’s build the graph with this multi-choice conditional edge.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
workflow = StateGraph(UserIntentState)

workflow.add_node("analyze_intent_node", analyze_intent)
workflow.add_node("greet_node", handle_greeting)
workflow.add_node("ask_node", handle_question)
workflow.add_node("command_node", handle_command)
workflow.add_node("unknown_node", handle_unknown)

workflow.set_entry_point("analyze_intent_node")

workflow.add_conditional_edges(
    "analyze_intent_node",
    route_by_intent,
    {
        "greet": "greet_node",
        "ask": "ask_node",
        "command": "command_node",
        "unknown": "unknown_node",
    },
)

# All handling nodes lead to the end
workflow.add_edge("greet_node", END)
workflow.add_edge("ask_node", END)
workflow.add_edge("command_node", END)
workflow.add_edge("unknown_node", END)

app = workflow.compile()

# Test cases
test_messages = [
    "Hello there!",
    "What is the capital of France?",
    "Please tell me a joke.",
    "I like cats.",
    "Hi, how are you?",
    "What time is it?"
]

for msg in test_messages:
    print(f"\n--- Testing with message: '{msg}' ---")
    initial_state: UserIntentState = {"user_message": msg, "intent": None, "response": ""}
    final_state = app.invoke(initial_state)
    print(f"AI's final response: {final_state['response']}")

Here, the route_by_intent function acts like a switchboard operator, directing the call to the right department based on the intent detected. This demonstrates flexible langgraph if-else conditional edges for multiple outcomes.

Diving Deeper: True/False Routing with State

The decision function always looks at the “state” of your AI. The state is like a whiteboard where all the nodes write down what they learned or did. When a conditional edge needs to make a choice, it peeks at this whiteboard to get the information it needs.

Using State for Decisions

Let’s say your AI needs to know if a user has logged in before giving them access to special features. The “state” would include a variable like is_logged_in.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
from typing import TypedDict
from langgraph.graph import StateGraph, START, END

class UserSessionState(TypedDict):
    user_id: str
    is_logged_in: bool
    message: str

# Nodes
def check_login_status(state: UserSessionState) -> UserSessionState:
    print(f"Checking login status for user: {state['user_id']}")
    # In a real app, this would query a database or session
    # For this example, let's say user "alice" is logged in, "bob" is not
    if state["user_id"] == "alice":
        state["is_logged_in"] = True
    else:
        state["is_logged_in"] = False
    return state

def provide_member_access(state: UserSessionState) -> UserSessionState:
    print("Providing member access.")
    state["message"] = f"Welcome back, {state['user_id']}! Here are your exclusive member benefits."
    return state

def prompt_login(state: UserSessionState) -> UserSessionState:
    print("Prompting user to log in.")
    state["message"] = "Please log in to access member content."
    return state

# Conditional function based on login status
def route_by_login(state: UserSessionState) -> str:
    print(f"Routing based on login status: {state.get('is_logged_in')}")
    if state["is_logged_in"]:
        return "logged_in"
    else:
        return "not_logged_in"

# Build the graph
workflow = StateGraph(UserSessionState)

workflow.add_node("check_login", check_login_status)
workflow.add_node("member_access", provide_member_access)
workflow.add_node("login_prompt", prompt_login)

workflow.set_entry_point("check_login")

workflow.add_conditional_edges(
    "check_login",
    route_by_login,
    {
        "logged_in": "member_access",
        "not_logged_in": "login_prompt",
    },
)

workflow.add_edge("member_access", END)
workflow.add_edge("login_prompt", END)

app = workflow.compile()

# Test with a logged-in user
print("--- Testing with Alice (logged in) ---")
initial_alice: UserSessionState = {"user_id": "alice", "is_logged_in": False, "message": ""}
result_alice = app.invoke(initial_alice)
print(result_alice["message"])

# Test with a non-logged-in user
print("\n--- Testing with Bob (not logged in) ---")
initial_bob: UserSessionState = {"user_id": "bob", "is_logged_in": False, "message": ""}
result_bob = app.invoke(initial_bob)
print(result_bob["message"])

Here, the check_login_status node updates the is_logged_in variable in the UserSessionState. Then, the route_by_login function uses this is_logged_in value to decide the next step. This is a clear example of true/false routing based on the AI’s internal memory (state).

Advanced Scenarios: Nested If-Else and Condition Composition

Sometimes, decisions aren’t just one simple choice. You might have an “if-else” inside another “if-else.” This is called “nested if-else.” LangGraph can handle this too, making it easy for nested if-else translation.

Mimicking Nested If-Else

Imagine this logic: “IF the user is logged in, THEN (IF they are a premium member, give them premium content, ELSE give them regular member content). ELSE (if not logged in), ask them to log in.”

How would this look in LangGraph? You can chain your conditional edges. One conditional edge decides is_logged_in, and if true, it leads to another node which contains another conditional edge to decide is_premium.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
from typing import TypedDict, Literal
from langgraph.graph import StateGraph, START, END

class AccessState(TypedDict):
    user_id: str
    is_logged_in: bool
    is_premium: bool
    content: str

# Nodes
def check_user_status(state: AccessState) -> AccessState:
    print(f"Checking status for user: {state['user_id']}")
    # Simulate user roles
    if state["user_id"] == "premium_pat":
        state["is_logged_in"] = True
        state["is_premium"] = True
    elif state["user_id"] == "regular_chris":
        state["is_logged_in"] = True
        state["is_premium"] = False
    else: # Guest
        state["is_logged_in"] = False
        state["is_premium"] = False
    return state

def offer_premium_content(state: AccessState) -> AccessState:
    state["content"] = "Here's your exclusive premium content!"
    return state

def offer_regular_content(state: AccessState) -> AccessState:
    state["content"] = "Here's your standard member content."
    return state

def request_login_content(state: AccessState) -> AccessState:
    state["content"] = "Please log in to view content."
    return state

# First level conditional function: logged in or not?
def route_by_login_status(state: AccessState) -> str:
    print(f"First routing: logged in? {state.get('is_logged_in')}")
    if state["is_logged_in"]:
        return "user_is_logged_in" # Go to a node that makes further decision
    else:
        return "user_not_logged_in" # Go to login prompt

# Second level conditional function: premium or regular?
def route_by_premium_status(state: AccessState) -> str:
    print(f"Second routing: premium? {state.get('is_premium')}")
    if state["is_premium"]:
        return "is_premium"
    else:
        return "is_regular"

# Build the graph
workflow = StateGraph(AccessState)

workflow.add_node("check_status", check_user_status)
workflow.add_node("premium_node", offer_premium_content)
workflow.add_node("regular_node", offer_regular_content)
workflow.add_node("login_node", request_login_content)

# Add an intermediate "decision node" if you want to visually represent the nested decision
# Or directly attach a conditional edge to a node that updates state for the next decision
# Let's create an intermediate "router" node for clarity for the premium check
def premium_router_node(state: AccessState) -> AccessState:
    # This node doesn't do much itself, just serves as a point for the next conditional edge
    print("Routing for logged-in user...")
    return state

workflow.add_node("premium_router", premium_router_node)

workflow.set_entry_point("check_status")

# First conditional edge: decides based on login status
workflow.add_conditional_edges(
    "check_status",
    route_by_login_status,
    {
        "user_is_logged_in": "premium_router", # If logged in, go to the premium decision node
        "user_not_logged_in": "login_node",    # If not logged in, go to login node
    },
)

# Second conditional edge: decides based on premium status (only reachable if user_is_logged_in)
workflow.add_conditional_edges(
    "premium_router",
    route_by_premium_status,
    {
        "is_premium": "premium_node",
        "is_regular": "regular_node",
    },
)

# All content nodes lead to the end
workflow.add_edge("premium_node", END)
workflow.add_edge("regular_node", END)
workflow.add_edge("login_node", END) # Login node also ends here for this example

app = workflow.compile()

# Test cases
test_users = ["premium_pat", "regular_chris", "guest_dave"]

for user in test_users:
    print(f"\n--- Testing with user: {user} ---")
    initial_state: AccessState = {"user_id": user, "is_logged_in": False, "is_premium": False, "content": ""}
    final_state = app.invoke(initial_state)
    print(f"AI's content for {user}: {final_state['content']}")

Here, the check_status node updates both is_logged_in and is_premium. The first conditional edge (route_by_login_status) then checks is_logged_in. If true, it sends the flow to premium_router. The premium_router node then has its own conditional edge (route_by_premium_status) that checks is_premium and routes accordingly. This is how you achieve nested if-else translation in LangGraph.

Composing Conditions

Sometimes, a single decision depends on many different things at once. Instead of nested if-else, you might want a single conditional function that combines multiple checks. This is called condition composition.

For example: “IF (user is logged in AND user is admin) OR (user is a special partner), THEN grant full access.” You can write one Python function that checks all these conditions and returns the correct path.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# Reusing AccessState from above
# (Skipping node definitions as they are similar)

# Conditional function that combines multiple logic checks
def route_by_complex_access(state: AccessState) -> str:
    print(f"Routing based on complex access: User '{state['user_id']}'")
    is_logged_in = state["is_logged_in"]
    is_premium = state["is_premium"] # Let's treat premium as 'admin' for this example
    is_special_partner = (state["user_id"] == "special_partner_eve")

    if (is_logged_in and is_premium) or is_special_partner:
        return "full_access"
    elif is_logged_in:
        return "limited_access"
    else:
        return "no_access"

# (Redefine nodes if needed, or re-use previous ones, just rename them for clarity)
def grant_full_access(state: AccessState) -> AccessState:
    state["content"] = "Welcome, privileged user! Enjoy full access."
    return state

def grant_limited_access(state: AccessState) -> AccessState:
    state["content"] = "Welcome, member! Here's your limited content."
    return state

def deny_access(state: AccessState) -> AccessState:
    state["content"] = "Access denied. Please log in or contact support."
    return state

# Build graph with this composed condition
workflow_composed = StateGraph(AccessState)

workflow_composed.add_node("check_status", check_user_status) # Reusing this node
workflow_composed.add_node("full_access_node", grant_full_access)
workflow_composed.add_node("limited_access_node", grant_limited_access)
workflow_composed.add_node("deny_access_node", deny_access)

workflow_composed.set_entry_point("check_status")

workflow_composed.add_conditional_edges(
    "check_status",
    route_by_complex_access, # Using the composed condition function
    {
        "full_access": "full_access_node",
        "limited_access": "limited_access_node",
        "no_access": "deny_access_node",
    },
)

workflow_composed.add_edge("full_access_node", END)
workflow_composed.add_edge("limited_access_node", END)
workflow_composed.add_edge("deny_access_node", END)

app_composed = workflow_composed.compile()

# Test cases for composed conditions
test_users_composed = ["premium_pat", "regular_chris", "guest_dave", "special_partner_eve"]

for user in test_users_composed:
    print(f"\n--- Testing composed logic with user: {user} ---")
    initial_state_composed: AccessState = {"user_id": user, "is_logged_in": False, "is_premium": False, "content": ""}
    final_state_composed = app_composed.invoke(initial_state_composed)
    print(f"AI's content for {user}: {final_state_composed['content']}")

This makes your conditional logic very clean. The route_by_complex_access function decides everything in one go. This is a powerful way for condition composition, making your graphs efficient and readable.

Practical Use Cases for LangGraph Conditional Edges

Using langgraph if-else conditional edges isn’t just for fancy coding. It’s super useful for building real-world AI applications that need to be smart and adaptable.

Customer Support Bots

Imagine a chatbot helping customers.

  • IF the customer asks “Where is my order?”, THEN go to the order_tracking node.
  • ELSE IF they say “I want to talk to a person,” THEN go to connect_to_agent node.
  • ELSE try to answer with FAQ_search node.

This kind of routing is perfect for handling many different customer needs. It ensures the customer gets the right help, fast.

Content Generation Workflows

A content creation AI could use these decisions too.

  • IF the user asks for a “summary of this article,” THEN use summarize_node.
  • ELSE IF they say “write a blog post about X,” THEN use blog_post_generator node.
  • ELSE IF they request “10 ideas for Y,” THEN use idea_list_generator node.

This allows the AI to produce different types of content based on the request. It makes the AI a versatile content assistant.

Data Processing Pipelines

Even for tasks behind the scenes, conditional edges are helpful.

  • IF data is clean (checked by a data_validator node), THEN send it to analysis_node.
  • ELSE IF data is dirty, THEN send it to data_cleaning_node first, and then to analysis_node.

This ensures that only good data gets analyzed, saving time and preventing errors. It’s like having a smart filter for your data.

Interactive Storytelling/Games

Imagine building a game where your choices matter.

  • IF the player chooses “open the door,” THEN go to room_exploration_node.
  • ELSE IF they choose “fight the monster,” THEN go to combat_node.

These decisions shape the story and the game experience. Conditional edges make these branching narratives easy to design and implement.

Simplifying Complex Conditionals

Even with all this power, things can get complicated if you’re not careful. The goal is always to make your AI’s brain as easy to understand as possible.

The Power of Well-Defined Condition Functions

Keep your conditional functions simple and focused. Each function should ideally make just one clear decision. For instance, one function checks login status, another checks premium status.

If a single function tries to decide too many things, it becomes hard to read and fix. Breaking it down helps with simplifying complex conditionals. Think of each function as a small, expert judge for one specific question.

Visualizing Your Workflow

One of the biggest advantages of LangGraph is that it lets you see your AI’s brain. When you draw out your nodes and conditional edges, it’s like looking at a map. This helps you understand how decisions lead to different paths.

Tools that visualize LangGraph (like the built-in app.get_graph().draw_png()) are super helpful. They show you exactly where the ternary-like routing happens and how your AI makes its way through various choices. A clear visual makes simplifying complex conditionals much easier.

Tips for Using LangGraph If-Else Conditional Edges Effectively

Here are some friendly tips to help you build great AI workflows with conditional edges:

  1. Name Your Nodes Clearly: Give your nodes names that describe what they do. check_user_intent is better than node_A.
  2. Keep Condition Functions Simple: As we discussed, each conditional function should have one clear job. If it gets too long, maybe you can split it into a few simpler functions or use a helper function inside it.
  3. Test Each Path: Make sure you try out all the different choices your AI can make. What happens if the user is happy? What if they are sad? Test every route!
  4. Think About Default Paths: What if none of your conditions are met? Always have a plan for a “default” path, like an “I don’t understand” response in a chatbot. This is like the else part of your if-else logic.
  5. Use the State Wisely: Remember that the state is your AI’s memory. Make sure each node puts important information into the state so other nodes (especially conditional edges) can use it.

Conclusion

You’ve learned that building smart AI means making decisions, just like you do every day. LangGraph’s langgraph if-else conditional edges are like special signposts that guide your AI through different paths. They let your AI choose what to do next based on what’s happening or what information it has.

From simple yes/no choices to complex, multi-layered decisions, these conditional edges make your AI flexible and powerful. You can easily create binary decision workflows, use true/false routing, and even manage nested if-else translation in a clear, visual way.

By using condition function patterns and focusing on simplifying complex conditionals, you can build amazing AI systems. So, go ahead and start building your smart AI workflows today, letting LangGraph draw the path for its intelligent choices!

Leave a comment