Live Demo: https://adroite2.onrender.com
This project routes customer questions through a LangGraph workflow for Sales, Technical Support, Billing, and Account Support. It retrieves company guidance, keeps customer history in SQLite, pauses risky requests for a supervisor, and checks every response before returning it to the customer.
The graph follows this order:
classify_intentdetects the department and checks for high-risk language.- Memory questions go directly to
recall_memory. - Other questions go through
retrieve_contextand then to one department agent. - Refunds, cancellations, account closures, compensation, and management
escalations pause at
human_review. - The
supervisorchecks the draft beforefinalizestores the interaction and returns the response.
LangGraph checkpoints and the readable support_interactions table share the
same SQLite database. A customer ID is also used as the LangGraph thread ID, so
the workflow keeps each customer's state separate.
SupportState contains:
- request and customer IDs
- current query and classified intent
- high-risk flag and approval status
- retrieved context and document sources
- department draft, reviewer feedback, and final response
- accumulated LangChain messages
The local retriever loads the four Markdown files in knowledge-base. It scores
each document with term frequency and inverse document frequency, then supplies
the three best documents to the selected support agent. The agent is instructed
to answer only from that retrieved context.
This keeps the sample project small and avoids a separate vector database. New company guidance can be added as another Markdown file.
The graph calls LangGraph interrupt() for every high-risk request. The graph
and its draft are saved in SQLite while execution is paused. The Streamlit page
shows Approve and Reject controls. Either decision resumes the same thread with
Command(resume=...).
An approval means the request can move to the next processing step. It does not claim that money was transferred or an account was changed. A rejection returns the supervisor's reason without implying approval.
Python 3.10 or later is required.
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
export GROQ_API_KEY="your-key"The Groq key is read only from the environment. Do not add it to .env.example
or commit a local .env file.
Start the web interface:
streamlit run app.pyRun the five required queries in the terminal:
python support_system.py --demo --db demo-memory.dbRun one query:
python support_system.py \
--customer customer-001 \
--query "I forgot my account password."Without GROQ_API_KEY, the application uses fixed local responses. Routing,
retrieval, SQLite memory, and human review still run through the same LangGraph.
This mode is useful for checking the workflow without spending API quota.
| Query | Route | Human approval |
|---|---|---|
| What are the pricing plans available for your software? | Sales | No |
| I forgot my account password. | Account | No |
| My application crashes whenever I upload a file. | Technical Support | No |
| I need a refund for my annual subscription. | Billing | Yes |
| What was my previous support issue? | Memory Recall | No |
The fifth query must use the same customer ID as an earlier query. The included demo does this automatically.
schema.sql creates the readable interaction table. LangGraph creates its own
checkpoint tables in the same memory.db file on first run.
sqlite3 memory.db < schema.sqlRuntime database files are ignored by Git.
render.yaml defines a Render web service. Create a Blueprint from the
repository and set GROQ_API_KEY in the Render dashboard. The free filesystem is
temporary, so a production deployment should mount a persistent disk for
memory.db.
