ACSA — Architecture Reference
User
│
│ WebSocket (ws://localhost:8000/ws/chat)
▼
Intent Classifier
│ confidence score (0.0 – 1.0)
├──── > 0.7 ────────────────────────────┐
│ ▼
│ Autonomous ReAct Agent
│ │
│ ┌──────────┼──────────┐
│ ▼ ▼ ▼
│ KB Search Order Status Ticket Creator
│ (ChromaDB) (Mock API) (Redis)
│ │
│ ▼
│ Confidence Checker (Critic)
│ │
│ ┌──────────┴──────────┐
│ │ PASS │ ESCALATE
│ ▼ ▼
│ Response → User Human Handoff Queue (Redis)
│ │
└──── < 0.7 ──────────────────────────┘
▼
Human Agent Dashboard
Agent Graph Nodes (LangGraph)
Node
File
Responsibility
classifier
agents/classifier.py
LLM call → topic + confidence float
react_agent
agents/react_agent.py
ReAct loop, calls tools iteratively
critic
agents/critic.py
Scores draft response → PASS / ESCALATE
escalator
agents/escalator.py
Packages full context for human queue
responder
agents/responder.py
Sends final answer over WebSocket
graph
agents/graph.py
LangGraph compiled graph, all edges
class AgentState (TypedDict ):
session_id : str
user_message : str
chat_history : Annotated [list , operator .add ]
topic : str
confidence : float
tool_calls_made : Annotated [list , operator .add ]
draft_response : str
critic_score : float
escalated : bool
final_response : str
Tool
File
What it does
kb_search
tools/kb_search.py
Semantic search over FAQ in ChromaDB
order_status
tools/order_status.py
Returns mock order data from JSON
ticket_creator
tools/ticket_creator.py
Creates ticket dict, stores in Redis
Data Flow: Happy Path (autonomous resolution)
User sends message over WebSocket
classifier calls Groq → returns {topic: "refund", confidence: 0.87}
Confidence > 0.7 → routed to react_agent
react_agent runs ReAct loop:
Thought: "I need to check the refund policy"
Action: kb_search("refund policy")
Observation: returns top 3 FAQ chunks
Thought: "I have enough context to answer"
Final answer generated
critic scores the draft → returns 0.82 (PASS threshold: 0.6)
responder sends answer to user over WebSocket
Metrics updated in Redis (resolution_count++)
Data Flow: Escalation Path
Triggered when:
classifier confidence < 0.7 (unclear intent), OR
critic score < 0.6 (low quality draft after ReAct)
Escalation payload sent to Redis human queue:
{
"session_id" : " abc123" ,
"user_message" : " My order is messed up and I want compensation" ,
"chat_history" : [... ],
"topic" : " complaint" ,
"confidence" : 0.45 ,
"tool_calls_made" : [" kb_search" , " order_status" ],
"draft_response" : " ..." ,
"critic_score" : 0.38 ,
"escalated_at" : " 2025-01-01T10:00:00Z" ,
"escalation_reason" : " low_critic_score"
}
Layer
Technology
Why
LLM
Groq llama-3.3-70b-versatile
Free tier, fast (200+ tok/s), no daily limit
Embeddings
sentence-transformers (local)
No API key, free, runs on CPU
Vector DB
ChromaDB (local)
No Docker, pip install, persistent
Session store
Redis (local)
Human queue + session state
Agent framework
LangGraph
Same as EADA, familiar
Backend
FastAPI + WebSocket
Production-grade, async
Frontend
React + TypeScript
Phase 4 only
Package manager
uv
Same as EADA
CI
GitHub Actions
ruff lint + pytest
support-agent/
├── backend/
│ ├── agents/
│ │ ├── __init__.py
│ │ ├── state.py ← AgentState TypedDict
│ │ ├── classifier.py ← intent + confidence
│ │ ├── react_agent.py ← ReAct loop
│ │ ├── critic.py ← quality scorer
│ │ ├── escalator.py ← human handoff
│ │ ├── responder.py ← sends to user
│ │ └── graph.py ← compiled LangGraph
│ ├── tools/
│ │ ├── __init__.py
│ │ ├── kb_search.py
│ │ ├── order_status.py
│ │ └── ticket_creator.py
│ ├── api/
│ │ ├── __init__.py
│ │ ├── websocket.py ← ws/chat endpoint
│ │ └── metrics.py ← GET /metrics
│ ├── db/
│ │ ├── __init__.py
│ │ ├── chroma.py ← ChromaDB client + helpers
│ │ └── redis_client.py ← Redis client + helpers
│ ├── config.py ← Pydantic Settings
│ └── main.py ← FastAPI app
├── frontend/ ← Phase 4
├── data/
│ ├── sample_faq.json ← seeded into ChromaDB on startup
│ └── mock_orders.json ← used by order_status tool
├── tests/
│ └── unit/
├── scripts/
│ └── ingest_faq.py ← one-time KB ingestion script
├── PROGRESS.md
├── ARCHITECTURE.md
├── pyproject.toml
├── .env.example
└── .gitignore
# LLM
GROQ_API_KEY = your_groq_key_here
# Redis
REDIS_URL = redis://localhost:6379
# ChromaDB
CHROMA_PERSIST_PATH = ./chroma_db
# Agent tuning
CONFIDENCE_THRESHOLD = 0.7
CRITIC_PASS_THRESHOLD = 0.6
MAX_REACT_ITERATIONS = 5
# App
APP_ENV = development
LOG_LEVEL = INFO
Evaluation Metrics (Phase 4 Dashboard)
Metric
How calculated
Resolution rate
resolved / total_sessions * 100
Escalation rate
escalated / total_sessions * 100
Avg latency
Mean time from message received to response sent
Top topics
Count by topic field from classifier
Critic score distribution
Histogram of critic scores