Inspiration

Support teams drown in tickets that all look the same on the surface — but underneath, some are angry VIP customers about to churn, some are written in a language nobody on the team speaks, and some are routine questions that could be answered instantly. We wanted to build something that reads a ticket the way an experienced support lead would: catching urgency, emotion, and context in seconds, not minutes.

That's what became HelpPilot — an AI autopilot for support tickets.

What it does

HelpPilot ingests incoming support tickets and automatically:

  • Detects language and translates the ticket body for the agent
  • Flags VIP customers so high-value accounts never get lost in the queue
  • Reasons about emotion, surfacing why a ticket sounds urgent or upset — not just a sentiment score
  • Scores confidence on suggested responses via a "trust dial," so agents know when to trust automation and when to step in
  • Tracks the full lifecycle of a ticket — classified, delivered, resolved — with timestamps and delivery channel visibility

The result is a support queue that tells you what to look at first, and why.

How we built it

  • Frontend: React + TypeScript, built with Vite
  • Backend: Python (FastAPI-style service) handling ticket ingestion, classification, and translation
  • Confidence scoring: modeled as a probability $p \in [0, 1]$ over suggested actions, thresholded against an adjustable "trust dial" $\tau$, where actions are auto-applied only if $p \geq \tau$
  • Deployment: containerized end-to-end with Docker — a multi-stage build that compiles the frontend, then serves it alongside the backend in a single production image, deployed to helppilot.run.place

Challenges we ran into

Getting from "runs on my machine" to a clean, reproducible Docker build surfaced a lot of issues that TypeScript's dev server quietly tolerates but its production compiler does not:

  • Strict tsc type-checking caught fields the frontend expected (translated_body, detected_language, vip_flag, emotion_reasoning, etc.) that hadn't yet been added to the shared Ticket type, forcing us to keep the frontend and backend contracts in sync
  • A project-wide habit of importing modules with explicit .ts/.tsx extensions built fine in dev (Vite) but failed outright under tsc in a clean Docker build — a good reminder that dev-server leniency isn't the same as a production-safe build
  • A couple of duplicate object keys and implicit any parameters that TypeScript's dev tooling silently allowed but a strict CI-style build correctly rejected

Each of these forced us to tighten up type safety across the app — annoying in the moment, but the app is meaningfully more robust for it.

What we learned

  • A working dev environment tells you very little about whether your build is actually production-ready — always test the real build command (tsc && vite build, not just vite dev) before you assume you're done
  • Keeping frontend types and backend response shapes in lockstep is worth the discipline, especially once a project grows past a handful of pages
  • Docker's multi-stage builds are a great forcing function: they surface bugs your local environment was quietly hiding

What's next for HelpPilot

  • Expanding language coverage for translation
  • Making the trust dial ($\tau$) tunable per-team, not just globally
  • Deeper SLA and burndown analytics for support managers

Built With

Share this project:

Updates