ai newsFr., 30. Okt.
EilmeldungKI-Radar #5: Kurz vor AGI – warum gehen dann so viele? Die neuen KI-Labs und ihre Wetten

Building CallAudit-X: An AI Call Auditing SaaS That Still Works Without an API Key

In most call centers, QA means a manager listens to a small handful of calls and hopes they're representative. The rest go unreviewed. CallAudit-X is my attempt at a different setup: upload call recordings, get a transcript and a QA audit from AI, then let a human approve or correct the result. It'

dev.toFreitag 16:32 · 30.10.4 Min. Lesezeit
Bild: dev.to

In most call centers, QA means a manager listens to a small handful of calls and hopes they're representative. The rest go unreviewed.

CallAudit-X is my attempt at a different setup: upload call recordings, get a transcript and a QA audit from AI, then let a human approve or correct the result. It's a SaaS-style app with customer and admin dashboards, analytics and billing.

Repo: https://github.com/mafzalkalwardev/CallAudit-X (MIT licensed)

This post covers the design decisions I care most about, based on what's in the repo.

Next.js 14 App Router, React, TypeScript and Tailwind CSS on the front, Prisma with PostgreSQL for data, bcryptjs and jose JWT for auth, Recharts for dashboards, Stripe for billing, OpenAI for transcription and audits, and FormSubmit for password reset email.

Nothing exotic. I wanted every moving part to be something a client's team could maintain.

A lot of AI apps quietly call a model during page render. That's expensive, slow and hard to reason about. In CallAudit-X, OpenAI is never called during page render. It only runs from an explicit upload-and-analyze path:

Step 5 means a report is generated once and read many times. Step 6 is the part I think matters most, and I'll come back to it.

OPENAI_API_KEY="" OPENAI_TRANSCRIPTION_MODEL="gpt-4o-transcribe" OPENAI_AUDIT_MODEL="gpt-4.1-mini" Enter fullscreen mode Exit fullscreen mode Without a key, upload and analyze still work with mock AI, so the app stays demo-ready. If the real call fails, the same fallback kicks in instead of leaving the user with a broken page.

This came out of a practical problem. When you're showing software to a client, you don't want the demo to depend on a key, a quota or a network call behaving perfectly. The fallback lets the whole flow be walked through end to end, and the real model slots in when it's configured.

Anyone who has worked near outbound calling knows that a big share of "calls" never become conversations. CallAudit-X has explicit no-live-conversation handling for:

Instead of forcing a sales or support score onto a voicemail greeting, these get N/A handling. Scoring a 10-second beep as a "bad sales call" would make the analytics useless, so this is a correctness feature more than a nice-to-have.

The transcript viewer is defensive in a similar way: it handles transcript data as a string, an array, an object or null. AI output and imported data don't always arrive in the shape you expect, and the UI shouldn't crash because of it.

AI audits are a first pass, not a verdict. Reviewers can approve a report, or reject it and submit a corrected category and feedback. The demo flow in the README shows this on purpose: approve one report, then reject and correct another to show the feedback loop.

The analytics page then shows DB-backed charts for category, sentiment, score and verification. Verification status being on the chart is deliberate. It tells you how much of what you're looking at has actually been checked by a person.

The password reset flow is where I spent extra care:

Admins also get a security log table alongside user CRUD, category management and a payments view.

The billing page shows the current plan, selected plan, usage, invoices, payment status and per-minute audit categories. The repo defines categories such as Sales QA, Support QA, Lead Qualification, Compliance Review, Appointment Review and Spam Detection, each with its own per-minute rate.

If Stripe keys or real Price IDs are missing, checkout buttons stay disabled and say "Stripe checkout is not configured yet." Same idea as the AI fallback: a half-configured app should say what's missing, not throw.

npm install npm run prisma:generate npm run prisma:migrate npm run prisma:seed npm run dev Enter fullscreen mode Exit fullscreen mode Then open http://localhost:3000. The seed creates demo admin and customer accounts (listed in the README), and there's a public/sample-call.wav you can upload from /dashboard/upload. There's also a /transcription-demo page that switches between a sales call, a support call and a voicemail/no-answer example.

Two checks I run before shipping changes:

npx prisma validate npx tsc --noEmit --pretty false --incremental false Enter fullscreen mode Exit fullscreen mode What I took away Make AI calls explicit. A button the user presses is easier to reason about, cache and bill than a hidden call on render. Design for the missing key. Fallbacks keep demos and dev environments useful. Model the non-conversations. Voicemail and no-answer calls deserve their own category, or your scores lie. Keep a human verification step, and show how much has been verified. Fail safely on payments and auth. Disabled buttons with clear messages beat cryptic errors. If you run QA for a call team, I'm curious: what share of your calls actually gets reviewed today?

Open to freelance & remote work Portfolio: https://mafzalkalwardev.github.io/#hire-me GitHub: https://github.com/mafzalkalwardev WhatsApp: +92 307 9670503 — https://wa.me/923079670503

Quelle: dev.to (dev.to). Original öffnen