diff --git a/kits/automation/support-triage/.env.example b/kits/automation/support-triage/.env.example new file mode 100644 index 00000000..156c99d2 --- /dev/null +++ b/kits/automation/support-triage/.env.example @@ -0,0 +1,4 @@ +LAMATIC_PROJECT_ENDPOINT= +LAMATIC_PROJECT_ID= +LAMATIC_PROJECT_API_KEY= +LAMATIC_FLOW_ID= \ No newline at end of file diff --git a/kits/automation/support-triage/.gitignore b/kits/automation/support-triage/.gitignore new file mode 100644 index 00000000..4fa33067 --- /dev/null +++ b/kits/automation/support-triage/.gitignore @@ -0,0 +1,42 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/versions + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# env files (can opt-in for committing if needed) +.env* + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts +!.env.example \ No newline at end of file diff --git a/kits/automation/support-triage/README.md b/kits/automation/support-triage/README.md new file mode 100644 index 00000000..ebe24f88 --- /dev/null +++ b/kits/automation/support-triage/README.md @@ -0,0 +1,17 @@ +# AI Support Triage Engine + +## What This Kit Does +Automates customer support by taking inbound tickets and instantly generating a category, sentiment analysis, urgency level, and a draft email response. This saves time, reduces manual routing work, and improves response clarity. + +## Providers & Prerequisites +- Lamatic Studio Flow +- Gemini Free Tier (Note: Requires a 60-second cooldown between requests to prevent 429 Rate Limit errors). + +## How to Run Locally +1. `cd kits/automation/support-triage` +2. `npm install` +3. `cp .env.example .env.local` and fill in your Lamatic API values. +4. `npm run dev` + +## Lamatic Flow +Flow ID: `your-flow-id` \ No newline at end of file diff --git a/kits/automation/support-triage/app/api/triage/route.ts b/kits/automation/support-triage/app/api/triage/route.ts new file mode 100644 index 00000000..445a92c9 --- /dev/null +++ b/kits/automation/support-triage/app/api/triage/route.ts @@ -0,0 +1,30 @@ +import { Lamatic } from 'lamatic'; +import { NextRequest, NextResponse } from 'next/server'; + +export async function POST(request: NextRequest) { + try { + const endpoint = process.env.LAMATIC_PROJECT_ENDPOINT; + const projectId = process.env.LAMATIC_PROJECT_ID; + const apiKey = process.env.LAMATIC_PROJECT_API_KEY; + const flowId = process.env.LAMATIC_FLOW_ID; + + // Fails fast and safely if env vars are missing + if (!endpoint || !projectId || !apiKey || !flowId) { + return NextResponse.json( + { error: "Missing required Lamatic environment variables on the server." }, + { status: 500 } + ); + } + + const lamaticClient = new Lamatic({ endpoint, projectId, apiKey }); + const { ticket_text } = await request.json(); + + const response = await lamaticClient.executeFlow(flowId, { ticket_text }); + return NextResponse.json(response); + + } catch (error: unknown) { + // Safely narrows the 'unknown' error type + const errorMessage = error instanceof Error ? error.message : "API execution failed"; + return NextResponse.json({ error: errorMessage }, { status: 500 }); + } +} \ No newline at end of file diff --git a/kits/automation/support-triage/app/favicon.ico b/kits/automation/support-triage/app/favicon.ico new file mode 100644 index 00000000..718d6fea Binary files /dev/null and b/kits/automation/support-triage/app/favicon.ico differ diff --git a/kits/automation/support-triage/app/globals.css b/kits/automation/support-triage/app/globals.css new file mode 100644 index 00000000..91d870ba --- /dev/null +++ b/kits/automation/support-triage/app/globals.css @@ -0,0 +1,26 @@ +@import "tailwindcss"; + +:root { + --background: #ffffff; + --foreground: #171717; +} + +@theme inline { + --color-background: var(--background); + --color-foreground: var(--foreground); + --font-sans: var(--font-geist-sans); + --font-mono: var(--font-geist-mono); +} + +@media (prefers-color-scheme: dark) { + :root { + --background: #0a0a0a; + --foreground: #ededed; + } +} + +body { + background: var(--background); + color: var(--foreground); + font-family: var(--font-sans), Arial, Helvetica, sans-serif; +} \ No newline at end of file diff --git a/kits/automation/support-triage/app/layout.tsx b/kits/automation/support-triage/app/layout.tsx new file mode 100644 index 00000000..8427377d --- /dev/null +++ b/kits/automation/support-triage/app/layout.tsx @@ -0,0 +1,34 @@ +import type { Metadata } from "next"; +import { Geist, Geist_Mono } from "next/font/google"; +import "./globals.css"; + +const geistSans = Geist({ + variable: "--font-geist-sans", + subsets: ["latin"], +}); + +const geistMono = Geist_Mono({ + variable: "--font-geist-mono", + subsets: ["latin"], +}); + +export const metadata = { + title: "AI Support Triage Engine", + description: "Automated customer support ticket categorization, sentiment analysis, and draft response generation", +}; + +export default function RootLayout({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) { + return ( + + {children} + + ); +} diff --git a/kits/automation/support-triage/app/page.tsx b/kits/automation/support-triage/app/page.tsx new file mode 100644 index 00000000..6b0ec76e --- /dev/null +++ b/kits/automation/support-triage/app/page.tsx @@ -0,0 +1,169 @@ +'use client'; +import React, { useState } from 'react'; + +export default function Page() { + const [ticketText, setTicketText] = useState(''); + const [loading, setLoading] = useState(false); + const [triageData, setTriageData] = useState(null); + + const executeFlow = async () => { + const normalizedTicket = ticketText.trim(); + if (!normalizedTicket) { + setTriageData({ error: "Please enter a ticket before processing." }); + return; + } + + setLoading(true); + setTriageData(null); + + try { + const res = await fetch('/api/triage', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ ticket_text: normalizedTicket }) + }); + + const response = await res.json(); + const data = response.result || response; + + // Improved Rate Limit Detection + const message = typeof data?.message === 'string' ? data.message.toLowerCase() : ''; + const isRateLimited = message.includes('quota') || message.includes('rate limit') || data?.status === 429; + + if (isRateLimited) { + setTriageData({ error: "API Rate Limit: Free tier restricted. Please wait 60 seconds before testing the next ticket." }); + } else if (data.error) { + setTriageData({ error: data.error }); + } else { + setTriageData(data); + } + + } catch (error) { + console.error("Execution error:", error); + setTriageData({ error: "Failed to connect to AI triage." }); + } finally { + setLoading(false); + } + }; + + return ( +
+
+ + {/* Header */} +
+
+ AgentKit Challenge +
+

+ AI Support Triage Engine +

+

+ Instantly categorize issues, analyze customer sentiment, and draft responses using Lamatic flows. +

+
+ + {/* Input Card */} +
+ +