What you’re building
A web app with a form where users paste support tickets. The AI analyzes each ticket and returns structured JSON:- Category (Billing, Technical, Feature Request, Bug Report, Account, or General Inquiry)
- Urgency (Critical, High, Medium, or Low)
- Sentiment (Positive, Neutral, or Negative)
- Product or service mentioned, if any
- Customer name and email, if provided
- Reference numbers like ticket IDs, project IDs, invoice numbers
- A one-sentence summary
- Suggested actions for the support team
Prerequisites
You’ll need Node.js 22+, npm, an OpenAI API key from platform.openai.com, the Upsun CLI, and Git.Project setup
Create the project:express for the web server, dotenv for env files, cors for cross-origin requests, LangChain packages for working with OpenAI, TypeScript for type safety, tsx to run TypeScript directly, and Biome for linting.
Configure TypeScript (tsconfig.json):
View source on GitHub
package.json:
Building the classifier
1. The classification logic
This is where the AI does its work. We send the ticket to OpenAI with a detailed system prompt that explains the classification schema. Createsrc/classifier.ts:
View source on GitHub
2. Input validation
Support tickets can be any length, but we need sensible limits. Createsrc/validation.ts:
View source on GitHub
3. Rate limiting
Prevent abuse with a simple in-memory rate limiter. Createsrc/rate-limiter.ts:
View source on GitHub
4. Express server
Createsrc/index.ts:
View source on GitHub
5. Frontend
Createpublic/index.html. The full file is in the repository. It has:
- Header with title and description
- Example tickets section with six pre-written Upsun-themed tickets
- Form with textarea and submit button
- Results section showing classification with color-coded badges
- JSON toggle to view raw response
Local development
Create.env:
.env.example for documentation:
View source on GitHub
http://localhost:3000. Click an example ticket, hit “Classify ticket,” and watch the results appear.
Deploying to Upsun
Create.upsun/config.yaml:
View source on GitHub
Testing
Try the example tickets. Each should classify correctly:
Monitor logs:
Extending the classifier
Add more categories
Edit the system prompt insrc/classifier.ts:
ClassificationResult interface if needed.
Extract more fields
Add fields to the prompt and interface:Connect to a ticketing system
Instead of just displaying results, send them somewhere:Add batch processing
Process multiple tickets at once:Store results
Add PostgreSQL for persistence:Cost considerations
Each classification uses roughly 500-1,500 tokens depending on ticket length. Withgpt-4o-mini:
For high volume, consider caching identical tickets, using embeddings to find similar past tickets, batching requests, or fine-tuning a smaller model.
Troubleshooting
”OPENAI_API_KEY is required” error
Check if the variable exists:Classification returns unexpected categories
The model might be using its own judgment. Make the prompt more explicit:JSON parsing fails
Sometimes the model adds extra text. Make the prompt stricter:High latency
Classification should take 1-3 seconds. If slower:- Check if you’re hitting rate limits
- Try a different OpenAI region
- Consider caching common ticket patterns
Rate limiting too strict
Adjust insrc/rate-limiter.ts: