All tutorials

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


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

Next Tutorial

Build a Document Assistant →