AI-powered support ticket classification, enrichment, and routing pipeline.
Built for the Valsoft AI Engineer Technical Assessment.
Processes unstructured inbound support messages through a 6-step agentic workflow:
- Ingestion — accepts raw messages (webhook, file, or direct input)
- Classification — GPT-4o-mini assigns category, priority, and confidence score
- Enrichment — GPT-4o-mini extracts summary, entities, and urgency signal
- Routing — pure Python maps classification to destination queue
- Structured Output — writes
output/results.json+ POSTs to webhook.site - Escalation — flags low-confidence or high-risk tickets for human review
# 1. Install dependencies
pip install -r requirements.txt
# 2. Set up environment
cp .env.example .env
# Edit .env — add OPENAI_API_KEY and webhook.site URLs
# 3. Run
python -m apps.pipeline.runOutput: output/results.json with all 5 processed records.
The latest workflow is deployed and active on n8n Cloud:
https://youssefc.app.n8n.cloud/webhook/arcvault-intake
Send any ticket directly — no setup required:
curl -X POST https://youssefc.app.n8n.cloud/webhook/arcvault-intake \
-H "Content-Type: application/json" \
-d '{"id":1,"source":"Email","raw_message":"Login broken after Tuesday update. 403 error. Account: arcvault.io/user/jsmith"}'All 5 sample inputs are in demo/send_tickets.txt — paste any line directly into PowerShell:
# Ticket 1 — Bug Report
curl.exe -s -X POST "https://youssefc.app.n8n.cloud/webhook/arcvault-intake" -H "Content-Type: application/json" -d "{\"id\":1,\"source\":\"Email\",\"raw_message\":\"Hi, I tried logging in this morning and keep getting a 403 error. My account is arcvault.io/user/jsmith. This started after your update last Tuesday.\"}"To run the workflow locally instead:
# 1. Start n8n
cd infra && docker compose up -d
# 2. Open http://localhost:5678
# 3. Import workflow
# Workflows → Import from file → infra/n8n/workflow.json
# 4. Set up credential
# Settings → Credentials → New → Header Auth
# Name: "OpenAI Header Auth"
# Header Name: Authorization
# Value: Bearer sk-your-key
# 5. Update webhook.site URLs in the Standard Queue and Escalation Queue nodes
# 6. Activate the workflow
# 7. Test
curl -X POST http://localhost:5678/webhook/arcvault-intake \
-H "Content-Type: application/json" \
-d '{"id":1,"source":"Email","raw_message":"Login broken after Tuesday update. 403 error. Account: arcvault.io/user/jsmith"}'python -m pytest tests/ -varcvault/
├── apps/pipeline/ # Python pipeline package
│ ├── run.py # Entry point
│ ├── models.py # Pydantic schemas
│ ├── prompts.py # LLM prompts
│ ├── classifier.py # Classification step
│ ├── enricher.py # Enrichment step
│ ├── router.py # Routing + escalation
│ └── outputs.py # JSON + webhook output
├── infra/
│ ├── docker-compose.yml
│ └── n8n/workflow.json
├── output/results.json # Generated output
├── tests/ # pytest tests
└── docs/ # Architecture + prompt docs
GPT-4o-mini — chosen for consistent JSON mode output, low cost (<$0.01 for 5 inputs), and strong classification accuracy for short support messages. Temperature set to 0.1 for reproducibility.
A ticket is flagged for human review if any of the following are true:
- Classification confidence < 70%
- Message contains:
outage,down for all,multiple users affected - Billing Issue with amount > $500
- High priority + confidence < 80%
See docs/architecture.md for full rationale.