An AI support agent for a financial services mobile app. A customer reports a problem (by chat or a simulated voice call); the agent reads it, reproduces it in an isolated sandbox of a bundled mock banking app, proposes a fix, and routes that fix to a human approval gate. Nothing is applied to the app until a human approves. All customer data is PII-redacted and every step is logged for transparency.
v1 is fully offline and deterministic: the "LLM" and "speech-to-text" are mocked so the whole flow runs with no API keys and is easy to test. See Swapping in real models below for where Claude + a real transcription service drop in.
Customer chat — a complaint is sent, and the agent classifies, reproduces the bug in the sandbox, and proposes a fix (right panel shows the audit trail):
Voice call — the same pipeline driven by a simulated call with live transcript:
Approval console — the human gate where proposed fixes are approved (auto-verified in sandbox) or rejected:
Customer (chat OR voice)
│ raw text ─────────────► 🔒 PII redaction (SSN, card, email, phone, acct#)
▼
1. CLASSIFY ──► no match ──► ASK ONE CLARIFYING QUESTION ──► still unclear (x2) ──► ESCALATE to human
│ matched
▼
2. REPRODUCE in isolated sandbox (fresh state each run)
│ bug observed │ no failure
▼ └──► clarify / ESCALATE
3. PROPOSE FIX (code diff + user steps + risk + repro evidence)
▼
4. ⛔ HUMAN APPROVAL GATE ◄── the machine stops here, always
│ approve │ reject
▼ └──► ESCALATE
5. APPLY in sandbox ──► VERIFY (re-run fixed) ──► pass? RESOLVED : ESCALATE
Voice uses the exact same state machine — it just transcribes the call first (streaming interim partials to mimic live captioning), then feeds the final transcript into step 1.
- Human gate is absolute. Code stops at
awaiting_approval;apply/verifyonly run insidedecide()after an approval. A test asserts no fix is applied pre-approval. - Data security. Raw customer text/transcripts never leave the server — the
API only ever returns redacted views (
toView()stripsraw*fields). - Transparency. Each ticket carries a human-readable
timelineand a structuredauditlog, both shown in the dashboard.
Four real, seeded bugs in server/src/bank.ts, each with a buggy + fixed code
path so reproduction and post-fix verification are genuine, not narrated:
| Bug | Symptom |
|---|---|
transfer-overdraft |
Dollar-rounding lets a transfer overdraw the account |
login-early-lockout |
Lock counter never resets on success → locks too early |
balance-rounding |
Balance rounds to whole dollars, hiding cents |
statement-empty-crash |
Statement export crashes on an account with no transactions |
cd support-agent
npm install # installs server + web (npm workspaces)
npm run dev # starts API (:4000) and dashboard (:5173)Open http://localhost:5173.
npm test # vitest: bug repro/fix, PII redaction, the human gate, clarify→escalate- Customer chat tab → click a sample complaint chip → Send to support → watch the agent classify → reproduce → propose on the right.
- Voice call tab → pick a spoken complaint → consent → Call in → watch the live transcript, then the same flow.
- Approval console tab → Approve & apply (auto-verifies) or Reject → escalate.
- Try the vague complaint to see the clarify→escalate path.
Everything model-shaped is isolated in server/src/agent.ts:
classify(text)→ replace keyword match with a Claude call (return the sameClassificationshape).buildPartials()/ voice transcript → replace with a streaming speech-to-text service; keep emitting partials intoticket.transcript.- The reproduction target (
server/src/bank.ts) → replace the bundled app with an adapter that drives your real staging environment / test harness.
The orchestrator, human gate, redaction, audit trail, and dashboard stay unchanged.
server/src
bank.ts mock app + 4 seeded bugs (buggy & fixed paths)
agent.ts mocked LLM classify + proposal + voice presets ← model seam
security.ts PII redaction
orchestrator.ts the workflow state machine + HUMAN GATE
store.ts in-memory tickets + redacted API projection
routes.ts chat / voice / approvals HTTP API
workflow.test.ts vitest coverage
web/src
App.tsx tabs, ticket list, live polling
components/ CustomerChat, VoiceSim, ApprovalConsole, TicketDetail


