Build a Customer Support Agent
Create a customer support assistant that handles FAQs, creates tickets, and escalates complex issues.
Overview
You'll build a support agent that:
- Answers common FAQs automatically
- Creates and tracks support tickets
- Escalates complex issues to a human queue
- Remembers customer context across interactions
- Runs as a durable workflow with observability
Expected outcome: A deployed support agent that reduces first-response time with automated FAQ and ticket routing.
Architecture
Customer
↓
Support Agent
↓
Memory (customer profile + ticket history)
↓
Workflow (faq → ticket → escalate → log)
↓
Support Queue (human escalation)
Prerequisites
- Complete Build an AI Assistant first
- API key set as
NOVIUM_API_KEY
Step 1: Create Support Agent
novium agent create support-agent
Created agent "support-agent" at ./agents/support-agent/
Step 2: Implement Logic
Open agents/support-agent/agent.ts:
const FAQ: Record<string, string> = {
"reset password": "Go to Settings → Security → Reset Password. You'll receive an email link.",
"billing question": "Visit Dashboard → Billing to view your current plan and invoices.",
"delete account": "To delete your account, go to Settings → Account → Delete Account. This action is permanent.",
"api key rotation": "Go to Dashboard → Settings → API Keys → Rotate. Your old key will expire in 24 hours.",
};
export default async function agent(input: {
userId: string;
message: string;
}) {
const message = input.message.toLowerCase();
// Check FAQ
for (const [question, answer] of Object.entries(FAQ)) {
if (message.includes(question)) {
return {
response: answer,
type: "faq_auto_reply" as const,
timestamp: new Date().toISOString(),
};
}
}
// Unknown — escalate
return {
response: "I've forwarded your question to our support team. They'll respond within 2 hours.",
type: "escalated" as const,
timestamp: new Date().toISOString(),
};
}
Step 3: Add Memory
Store customer profiles and ticket history.
export default async function agent(input: { userId: string; message: string }) {
// Load or create customer profile
const profile = (await memory.get(`customer:${input.userId}`)) ?? {
id: input.userId,
createdAt: new Date().toISOString(),
messageCount: 0,
ticketsOpened: 0,
};
profile.messageCount += 1;
await memory.save({ key: `customer:${input.userId}`, value: profile });
// Check FAQ
const message = input.message.toLowerCase();
for (const [question, answer] of Object.entries(FAQ)) {
if (message.includes(question)) {
return {
response: answer,
type: "faq_auto_reply" as const,
customerSince: profile.createdAt,
totalMessages: profile.messageCount,
timestamp: new Date().toISOString(),
};
}
}
// Create ticket for escalation
const ticketId = `ticket_${Date.now()}`;
const ticket = {
id: ticketId,
userId: input.userId,
question: input.message,
status: "open" as const,
createdAt: new Date().toISOString(),
};
await memory.save({ key: ticketId, value: ticket });
profile.ticketsOpened += 1;
await memory.save({ key: `customer:${input.userId}`, value: profile });
return {
response: `Ticket ${ticketId} created. Support will respond within 2 hours.`,
type: "ticket_created" as const,
ticketId,
customerSince: profile.createdAt,
totalMessages: profile.messageCount,
timestamp: new Date().toISOString(),
};
}
Memory keys:
| Key | Purpose |
| --- | ------- |
| customer:{userId} | Customer profile with message count, join date |
| ticket_{id} | Individual support ticket with status tracking |
Step 4: Add Workflow
novium workflow create support-pipeline
Open workflows/support-pipeline/workflow.ts:
export default {
trigger: { type: "http", method: "POST", path: "/support" },
steps: [
{
id: "handle-query",
agent: "support-agent",
input: {
userId: "$input.userId",
message: "$input.message",
},
},
{
id: "escalate-if-needed",
action: "condition",
condition: "$handle-query.result.type === 'ticket_created'",
then: [
{
id: "notify-team",
action: "log",
message: "ESCALATION: Ticket $handle-query.result.ticketId for user $input.userId",
},
],
},
{ id: "finalize", action: "log", message: "Support pipeline complete" },
],
};
Trigger (HTTP POST /support)
↓
handle-query ← support-agent
↓
escalate-if-needed ← condition: ticket_created?
↓ (yes)
notify-team ← log escalation alert
↓
finalize ← log completion
Step 5: Run Locally
novium agent dev
Test FAQ match:
curl -X POST http://localhost:3000 \
-H "Content-Type: application/json" \
-d '{"userId": "user-1", "message": "How do I reset my password?"}'
{
"response": "Go to Settings → Security → Reset Password. You'll receive an email link.",
"type": "faq_auto_reply",
"customerSince": "2025-01-15T10:00:00.000Z",
"totalMessages": 1
}
Test escalation:
curl -X POST http://localhost:3000 \
-H "Content-Type: application/json" \
-d '{"userId": "user-1", "message": "My data export is stuck at 50%"}'
{
"response": "Ticket ticket_1705310000000 created. Support will respond within 2 hours.",
"type": "ticket_created",
"ticketId": "ticket_1705310000000",
"customerSince": "2025-01-15T10:00:00.000Z",
"totalMessages": 2
}
Step 6: Observe Logs
novium logs --workflow support-pipeline
TIMESTAMP REQUEST ID TYPE STATUS
2025-01-15 10:35:01 req_a1b2c3 faq_auto_reply success
2025-01-15 10:36:05 req_d4e5f6 ticket_created success
2025-01-15 10:36:05 req_d4e5f6 ESCALATION logged
Step 7: Deploy
novium deploy
✓ Deployed
Agent "support-agent":
Endpoint: https://ai-assistant.novium.cloud/support-agent
Workflow "support-pipeline":
Endpoint: https://ai-assistant.novium.cloud/support
Final Result
A customer support agent that auto-answers FAQs, creates tickets for unknown questions, and escalates with alerts.
What You Learned
- ✅ Multi-step workflows with conditional branching
- ✅ FAQ pattern matching for auto-replies
- ✅ Customer profile memory across sessions
- ✅ Ticket creation and status tracking
- ✅ Escalation alerts via workflow