← Back to Cookbook

Support Ticket Router

Routes tickets by urgency and department, sends Slack alerts for critical ones.

aiswitchhttp

Source

/**
 * Routes incoming support tickets by urgency and department.
 * Urgent tickets get immediate notification, others are categorized.
 */

webhook support_ticket {
  label: "Support Ticket Webhook"
  schema: @json {
    {
      "type": "object",
      "required": ["subject", "body", "customer_email", "plan"],
      "properties": {
        "subject": { "type": "string" },
        "body": { "type": "string" },
        "customer_email": { "type": "string" },
        "plan": { "type": "string", "enum": ["free", "pro", "enterprise"] }
      }
    }
  }
}

graph route_ticket {
  label: "Route Support Ticket"

  root {
    type: code
    label: "Parse ticket"
    code: @ts { return context.nodes.root.input }
    outputSchema: @json {
      {
        "type": "object",
        "properties": {
          "subject": { "type": "string" },
          "body": { "type": "string" },
          "customer_email": { "type": "string" },
          "plan": { "type": "string" }
        }
      }
    }
  }

  node classify {
    type: ai
    label: "Classify ticket"
    kind: object
    model: "google/gemini-2.5-flash"
    prompt: @ts {
      return "Classify this support ticket.\n\nSubject: " + context.nodes.root.output.subject + "\nBody: " + context.nodes.root.output.body + "\nPlan: " + context.nodes.root.output.plan
    }
    schema: @json {
      {
        "type": "object",
        "required": ["urgency", "department"],
        "properties": {
          "urgency": { "type": "string", "enum": ["critical", "high", "normal", "low"] },
          "department": { "type": "string", "enum": ["billing", "technical", "account", "general"] },
          "suggested_response": { "type": "string" }
        }
      }
    }
  }

  node route_urgency {
    type: switch
    label: "Route by urgency"
    cases: ["critical", "standard"]
    router: @ts {
      if (context.nodes.classify.output.urgency === "critical") return "critical"
      return "standard"
    }
  }

  node escalate {
    type: http
    label: "Escalate to on-call"
    method: "POST"
    url: @ts { return "https://hooks.slack.com/services/EXAMPLE/WEBHOOK" }
    body: @ts {
      const ticket = context.nodes.root.output
      const classification = context.nodes.classify.output
      return JSON.stringify({
        text: "CRITICAL TICKET from " + ticket.customer_email + " (" + ticket.plan + ")\nDept: " + classification.department + "\nSubject: " + ticket.subject
      })
    }
  }

  node queue_standard {
    type: code
    label: "Queue standard ticket"
    code: @ts {
      return {
        queue: context.nodes.classify.output.department,
        urgency: context.nodes.classify.output.urgency,
        customer: context.nodes.root.output.customer_email,
        subject: context.nodes.root.output.subject
      }
    }
  }

  flow {
    root -> classify
    classify -> route_urgency
    route_urgency -["critical"]-> escalate
    route_urgency -["standard"]-> queue_standard
  }
}

trigger on_ticket {
  webhook:support_ticket -> route_ticket
  enabled: true
}

Flow

Trigger → graph

Graph nodes