In the modern airline industry, processing millions of transactions daily—ranging from standard ticket bookings and baggage fees to last-minute flight upgrades and massive corporate refunds—is a massive operational challenge. A single point of failure or a delayed fraud check can result in lost revenue, poor customer experience, or severe security breaches.
Enter LangGraph, a powerful framework for building stateful, multi-actor applications with Large Language Models (LLMs). By utilizing Conditional Edges, we can build an intelligent routing system that dynamically evaluates the risk of an airline transaction in real-time and routes it to the appropriate specialized AI agent.
In this end-to-end article, we will build a real-time Airline Transaction Risk Router. We will assess incoming transactions and route them to a Standard Processing Agent, an Enhanced Verification Agent, or a Fraud Investigation Agent based on their calculated risk level.
Prerequisites
Before we dive into the code, ensure you have the following set up:
1. Python Environment
You need Python 3.9 or higher. It is highly recommended to use a virtual environment.
2. Required Libraries
Install the necessary LangChain and LangGraph packages via pip:
pip install langgraph langchain langchain-openai pydantic3. API Keys
We will use OpenAI's models for our agents. You need an OpenAI API key. Set it as an environment variable in your terminal or .env file:
export OPENAI_API_KEY="your-openai-api-key"4. Conceptual Understanding
StateGraph: The core of LangGraph, representing the workflow as a graph where nodes are actions and edges are transitions.
Conditional Edges: A feature that allows the graph to dynamically choose the next node based on the current state (e.g., routing based on a risk score).
The Airline Use Case: Real-Time Transaction Routing
Imagine you are the Chief Technology Officer of "SkyHigh Airlines." Your payment gateway receives thousands of requests per minute.
The Scenarios:
Low Risk: A frequent flyer purchases a $50 extra baggage fee using a saved credit card. -> Needs instant approval.
Medium Risk: A user attempts a $2,500 last-minute upgrade to First Class from an IP address in a different country. -> Needs enhanced verification (e.g., 3D Secure or SMS OTP).
High Risk: A suspicious pattern of 10 refund requests totaling $50,000 within 5 minutes from a newly created account. -> Needs immediate freezing and fraud investigation.
Instead of writing hundreds of rigid if/else rules, we will build an Agentic Workflow where an Assessment Node evaluates the context, and Conditional Edges route the transaction to the correct specialized AI agent.
Step-by-Step Implementation
Step 1: Define the State
In LangGraph, the State is the shared memory that passes between nodes. We will use Pydantic to strictly define our transaction data.
from typing import TypedDict, Literal
from pydantic import BaseModel, Field
class TransactionState(TypedDict):
transaction_id: str
passenger_name: str
amount: float
transaction_type: str
context: str # Additional context like IP, account age, etc.
# Fields populated by the agents
risk_level: Literal["low", "medium", "high"]
risk_reasoning: str
agent_action: str
final_status: strStep 2: Create the Nodes (The Agents)
Nodes are simply Python functions that take the current State, perform an action (like calling an LLM or a database), and return an updated State.
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
llm = ChatOpenAI(model="gpt-4o", temperature=0)
# 1. Risk Assessment Node
def assess_risk_node(state: TransactionState):
prompt = ChatPromptTemplate.from_template(
"""You are an expert airline fraud detection AI.
Analyze the following transaction and assign a risk level: 'low', 'medium', or 'high'.
Transaction ID: {transaction_id}
Passenger: {passenger_name}
Amount: ${amount}
Type: {transaction_type}
Context: {context}
Respond ONLY in the following JSON format:
{{
"risk_level": "low/medium/high",
"reasoning": "Brief explanation of the risk"
}}
"""
)
# Using structured output for reliable parsing
structured_llm = llm.with_structured_output(
schema={
"type": "object",
"properties": {
"risk_level": {"type": "string", "enum": ["low", "medium", "high"]},
"reasoning": {"type": "string"}
},
"required": ["risk_level", "reasoning"]
}
)
chain = prompt | structured_llm
result = chain.invoke({
"transaction_id": state["transaction_id"],
"passenger_name": state["passenger_name"],
"amount": state["amount"],
"transaction_type": state["transaction_type"],
"context": state["context"]
})
return {
"risk_level": result["risk_level"],
"risk_reasoning": result["reasoning"]
}
# 2. Specialized Processing Agents
def standard_processing_node(state: TransactionState):
return {
"agent_action": "Standard Agent: Instantly approved. No friction applied.",
"final_status": "APPROVED"
}
def enhanced_verification_node(state: TransactionState):
return {
"agent_action": "Enhanced Agent: Triggering 3D Secure / SMS OTP verification.",
"final_status": "PENDING_VERIFICATION"
}
def fraud_investigation_node(state: TransactionState):
return {
"agent_action": "Fraud Agent: Transaction blocked. Account flagged for manual review.",
"final_status": "BLOCKED"
}

Join the conversation! Your thoughts help the community grow.