langgraph-support-agent / ARCHITECTURE.md
mnoorchenar's picture
Update 2026-03-22 16:37:02
1f2bfa7
# πŸ—οΈ TechStore Support Agent - Architecture Guide
## **Project Overview**
This is an **AI-powered customer support chatbot** that uses **LangGraph** (ReAct pattern) and **HuggingFace models** to answer customer questions about TechStore products and services.
**Goal:** Automate customer support by intelligently routing questions to the right tools and providing instant answers.
---
## **How It Works: The ReAct Loop**
### **Step 1: User Sends Message**
```
User: "What is your return policy?"
↓
Flask Backend (/api/chat)
↓
Creates LangGraph session
```
### **Step 2: Agent Thinks**
The **Qwen AI Model** receives the question and decides:
- "I need to search the FAQ for 'return policy'"
- Outputs in this format:
```
Thought: The user is asking about return policy
Action: search_faq
Action Input: {"query": "return policy"}
```
### **Step 3: Tool Execution**
The agent's decision is parsed and a **tool is executed**:
```python
search_faq("return policy")
β†’ Returns best matching FAQ entries
β†’ "You may return items within 30 days..."
```
### **Step 4: Agent Responds**
The tool result is fed back to the AI, which writes:
```
Thought: I have the information needed
Final Answer: You may return most items within 30 days...
```
### **Step 5: Stream to User**
Response is streamed via **Server-Sent Events (SSE)** in real-time:
```
Browser receives: "You may return most items within 30 days..."
Shows on screen instantly
```
---
## **Project Structure**
```
langgraph-support-agent/
β”œβ”€β”€ app.py # Main Flask server
β”œβ”€β”€ events.py # Event streaming system
β”œβ”€β”€ requirements.txt # Python dependencies
β”œβ”€β”€ Dockerfile # Container config
β”œβ”€β”€ agent/
β”‚ β”œβ”€β”€ __init__.py
β”‚ β”œβ”€β”€ state.py # Agent state definition
β”‚ β”œβ”€β”€ tools.py # 5 support tools
β”‚ β”œβ”€β”€ llm.py # Qwen integration
β”‚ β”œβ”€β”€ nodes.py # ReAct nodes
β”‚ └── graph.py # LangGraph definition
β”œβ”€β”€ data/
β”‚ └── faq.json # FAQ knowledge base
β”œβ”€β”€ templates/
β”‚ └── index.html # Web UI
β”œβ”€β”€ static/
β”‚ └── app.js # Frontend logic
└── docs/
└── project-template.html
```
---
## **The 5 Tools**
### **1. πŸ” search_faq(query)**
- **What:** Searches the FAQ knowledge base
- **Use Case:** User asks "What's your return policy?"
- **Example:**
```
search_faq("return policy")
β†’ Returns matching FAQ entries
```
### **2. πŸ“¦ check_order_status(order_id)**
- **What:** Looks up order status and tracking
- **Use Case:** User asks "Where is my order ORD-482910?"
- **Example:**
```
check_order_status("ORD-482910")
β†’ Order: ORD-482910: Shipped. Tracking #1234567890. ETA: March 25, 2026
```
### **3. πŸ›οΈ get_product_info(product_name)**
- **What:** Returns product specs, price, availability
- **Use Case:** User asks "Do you have laptops in stock?"
- **Example:**
```
get_product_info("laptop")
β†’ Product: ProBook X15
Price: $1,299
Availability: In Stock
Specs: Intel i7-13th, 16GB RAM, 512GB NVMe SSD
```
### **4. 🎫 create_ticket(issue, priority)**
- **What:** Creates a support ticket
- **Use Case:** User says "I need to report a broken product"
- **Example:**
```
create_ticket("Screen is broken", "high")
β†’ Ticket TKT-ABC123 created
Priority: HIGH
Expected response: within 8 hours
```
### **5. πŸ‘€ escalate_to_human(reason)**
- **What:** Transfers conversation to human agent
- **Use Case:** User says "I want to talk to someone"
- **Example:**
```
escalate_to_human("Unhappy customer")
β†’ Escalation ESC-XYZ initiated
Queue position: 3 | Est. wait: 15 minutes
```
---
## **Key Technologies**
| Component | Purpose |
|-----------|---------|
| **Flask** | Web server & API |
| **LangGraph** | Agent orchestration (ReAct pattern) |
| **Qwen 2.5 7B** | AI Model (HuggingFace Inference API) |
| **Server-Sent Events** | Real-time streaming |
| **Threading** | Async task processing |
| **LangChain** | Message handling & parsing |
---
## **The ReAct Pattern**
**ReAct** = **Reasoning + Acting**
```
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ 1. Router Node β”‚
β”‚ ↓ β”‚
β”‚ 2. Agent Loop (Reasoning) β”‚
β”‚ - Qwen thinks about question β”‚
β”‚ - Decides which tool to use β”‚
β”‚ ↓ β”‚
β”‚ 3. Tool Executor (Acting) β”‚
β”‚ - Executes the chosen tool β”‚
β”‚ - Returns result β”‚
β”‚ ↓ β”‚
β”‚ 4. Back to Agent (Loop) β”‚
β”‚ - Has tool result β”‚
β”‚ - Decides: use another tool or end? β”‚
β”‚ ↓ β”‚
β”‚ 5. Responder Node β”‚
β”‚ - Final answer sent to user β”‚
β”‚ ↓ β”‚
β”‚ 6. END β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```
**Max 4 tool calls per turn** (to prevent infinite loops)
---
## **UI Layout (60% Chat Focus)**
```
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ πŸ›οΈ TechStore Support Agent β”‚ Orders Β· FAQs Β· Tickets β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ β”‚ β”‚ β”‚
β”‚ β”‚ β”‚ β”‚
β”‚ 20% β”‚ 60% Chat β”‚ 20% β”‚
β”‚ Sidebar β”‚ (Messages & Input) β”‚ Panel β”‚
β”‚ β”‚ β”‚ (Tools & β”‚
β”‚ β€’ Model β”‚ User: "What is return β”‚ Trace) β”‚
β”‚ β€’ Status β”‚ policy?" β”‚ β”‚
β”‚ β€’ Stats β”‚ β”‚ β€’ Tool β”‚
β”‚ β”‚ Agent: "You may return β”‚ Calls β”‚
β”‚ β”‚ items within 30 days..." β”‚ β€’ Executionβ”‚
β”‚ β”‚ β”‚ Trace β”‚
β”‚ β”‚ β”‚ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```
---
## **Data Flow**
```
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ User β”‚
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜
β”‚ "What is your return policy?"
↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Flask API /api/chat β”‚
β”‚ - Validates input β”‚
β”‚ - Gets HF_TOKEN from .env β”‚
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ LangGraph StateGraph β”‚
β”‚ - Manages Agent State β”‚
β”‚ - Orchestrates nodes β”‚
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β”œβ”€ Router Node β†’ sends to Agent
β”‚
β”œβ”€ Agent Node
β”‚ - Calls Qwen AI model
β”‚ - Parses: "Action: search_faq"
β”‚
β”œβ”€ Tool Executor Node
β”‚ - Executes tool
β”‚ - search_faq("return policy")
β”‚
β”œβ”€ Agent Node (again)
β”‚ - Decides: Final Answer or more tools?
β”‚
└─ Responder Node
- Finalizes response
- Emits events via SSE
β”‚
↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Browser (SSE) β”‚
β”‚ Receives events β”‚
β”‚ in real-time β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
↓
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ User sees answer β”‚
β”‚ "You may return... β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```
---
## **How to Extend This**
### **Add a New Tool**
1. Create function in `agent/tools.py`:
```python
def my_tool(param: str) -> str:
"""My new tool."""
return "result"
```
2. Add to TOOLS dict:
```python
TOOLS = {
...
"my_tool": {"fn": my_tool, "desc": "My tool", "icon": "πŸ”§"},
}
```
3. Update system prompt in `agent/llm.py` to mention it
### **Change AI Model**
Edit `app.py`:
```python
AVAILABLE_MODELS = [
{"id":"different-model/name","name":"Display Name","badge":"βœ“"},
]
```
### **Update FAQ**
Edit `data/faq.json` - add/modify entries
---
## **Deployment**
This is designed for **HuggingFace Spaces**:
1. Set `HF_TOKEN` in Space Secrets
2. Push code to repo
3. Space auto-deploys with Docker
4. Runs on port 7860
---
## **Summary**
- **What:** Customer support chatbot for TechStore
- **How:** LangGraph orchestrates an AI agent through a ReAct loop
- **Why:** Automate support & provide instant answers
- **Tech:** Flask + LangGraph + Qwen + SSE streaming
- **Scalable:** Can add more tools/FAQs without changing architecture