A multi-agent conversational AI that runs over a regular phone call — no internet, no smartphone, no banking app. Built in 24 hours and crowned Overall 1st Place + Goldman Sachs Track Winner at HackUTD 2024 across 1,100+ hackers.
A real phone call routes through Retell AI into a multi-agent FastAPI backend; the operator console reflects every event in real time. Watch the full 2‑minute demo on YouTube →
Tip
The fastest way to understand this project is to open the live site. The interactive walkthrough at talktuah.art3m1s.me/demo replays the same multi-agent transcripts the FastAPI backend produced — no setup required — and an optional Live AI tab lets you talk to a real LLM running the same tool surface.
- The problem
- What we built
- Architecture at a glance
- Tech stack
- The deployed project page
- Two demo modes
- Quick start
- Repository layout
- Team
- HackUTD 2024 — the weekend at a glance
- Acknowledgements
A complete telephony banking flow with four LLM agents coordinating live during a single phone call.
|
Inbound PSTN calls land in Retell AI, which streams transcript chunks over a bidirectional WebSocket to a FastAPI server. Replies stream straight back to the caller's ear via Retell's TTS. |
Triage, Accounts, Payments, and Applications — each with its own prompt and tool surface, coordinated via OpenAI Swarm handoff functions. The Triage agent decides who should answer; the others actually do the work. |
Loan and credit-card applications are rendered server-side with LaTeX, then pinned to IPFS through Pinata. The CID flows through to the operator console, so support can pull the exact PDF the caller signed off on. |
flowchart TB
classDef edge fill:#eef5ff,stroke:#64A8F0,stroke-width:1px,color:#1d2533
classDef agent fill:#fff9ec,stroke:#F2C744,stroke-width:1px,color:#1d2533
classDef store fill:#f0f7ee,stroke:#88c87a,stroke-width:1px,color:#1d2533
caller([ User on a phone ])
retell[Retell AI<br/>Telephony + STT/TTS]:::edge
fastapi[FastAPI server<br/>main.py]:::edge
console[Operator Console<br/>Next.js]:::edge
caller -- PSTN voice --> retell
retell -- wss /llm-websocket --> fastapi
fastapi -- ws /ws?client_id --> console
llm[LlmClient<br/>llm.py]:::edge
swarm[AgentSwarm<br/>agent_swarm.py]:::agent
triage[Triage Agent]:::agent
accounts[Accounts Agent]:::agent
payments[Payments Agent]:::agent
apps[Applications Agent]:::agent
db[(In-memory bank DB)]:::store
pdfs((LaTeX PDF))
pinata[(Pinata · IPFS pin)]:::store
fastapi --> llm --> swarm --> triage
triage --> accounts & payments & apps
accounts --> db
payments --> db
apps --> pdfs --> pinata
pinata -. CID .-> console
Or read the same diagram with annotated source excerpts on the live site:Â talktuah.art3m1s.me/architecture.
|
|
|
The repo also ships with a full Next.js portfolio site in client/ that tells the project story end-to-end without spinning up the Python backend. It deploys as a single Vercel project and lives at talktuah.art3m1s.me.
| Route | What's there |
|---|---|
/ |
Hero, embedded demo reel, feature cards, hackathon stats, team |
/demo |
Interactive multi-agent walkthrough (Guided + optional Live AI) |
/console |
The operator dashboard from HackUTD, wired to a session-local mock |
/architecture |
Mermaid system diagram + annotated excerpts from server/ |
/build |
Stack rundown, 24-hour timeline, lessons learned, self-host instructions |
|
Default · no API key required. Six pre-canned scenarios stream the same multi-agent transcripts the FastAPI backend produced — transfer funds, schedule a payment, cancel a payment, apply for a loan, apply for a credit card, check balance — with full handoff animations, in-memory ledger mutations, and fake Pinata IPFS hashes for every signed PDF. 100% client-side. Works offline. Always-on for recruiters. |
Optional · enabled when A Next.js Route Handler at Each request operates on an isolated, ephemeral clone of the bank ledger — the LLM cannot mutate state across sessions. |
Run the deployable Next.js project page locally
cd client
pnpm install
pnpm dev # → http://localhost:3000For the optional Live AI tab on Vercel:
- Enable the Vercel AI Gateway on the project (no plaintext
OPENAI_API_KEYneeded; the platform issues a short-lived OIDC token at deploy time) - Optionally set
LIVE_AI_MODELto override the default model - Build/install commands and
maxDurationare wired inclient/vercel.json
Self-host the original FastAPI backend (telephony loop)
# Terminal A — backend
cd server
pip install -r requirements.txt
export RETELL_API_KEY=... # Retell telephony
export OPENAI_API_KEY=... # OpenAI Swarm
export PINATA_API_KEY=... # IPFS pinning
uvicorn main:app --reload --port 8000
# Terminal B — original operator console
cd client
pnpm install
pnpm devTo re-bind the operator console to the live FastAPI socket, swap the Zustand mock in client/src/lib/store.ts for new WebSocket("ws://localhost:8000/ws?client_id=…") and pipe each parsed JSON message into useDemoStore.getState().dispatchEvent(event). The event contract from server/main.py is preserved verbatim:
{ event: "combined_response", calls, db }
{ event: "db_response", data: db }
{ event: "calls_response", data: calls }Show tree
TalkTuahBank/
├── client/ Next.js 15 portfolio site (deployable)
│ ├── public/team/ Team headshots
│ ├── src/app/
│ │ ├── page.tsx / — hero, embedded demo, team
│ │ ├── demo/ /demo — guided + live AI walkthrough
│ │ ├── console/ /console — operator dashboard (verbatim port)
│ │ ├── architecture/ /architecture — mermaid + annotated source
│ │ ├── build/ /build — stack, timeline, lessons
│ │ ├── api/chat/ Live AI route (AI SDK v6 streamText)
│ │ ├── icon.svg Favicon (chat bubble logo)
│ │ ├── apple-icon.tsx Dynamic Apple touch icon
│ │ ├── opengraph-image.tsx Dynamic 1200×630 social card
│ │ └── manifest.ts PWA manifest
│ └── src/lib/
│ ├── tools.ts Bank tools as Zod-typed AI SDK tools
│ ├── mock-bank.ts TS port of server/db.py
│ ├── mock-scenarios.ts Scripted multi-agent transcripts
│ └── store.ts Zustand store mirroring the FastAPI WS contract
├── server/ Original Python backend (HackUTD build)
│ ├── main.py FastAPI + bidirectional Retell WebSocket
│ ├── llm.py LlmClient bridge between Retell and Swarm
│ ├── agent_swarm.py Triage / Accounts / Payments / Applications
│ ├── db.py In-memory bank ledger (5 seeded users)
│ └── pinata.py IPFS pinning client
├── experiments/ Notebooks & prompt scratchpads
└── .github/assets/ README artwork
Three friends who showed up at ECSW with a hunch about voice and a list of bank-ledger ideas, and walked out with the overall trophy.
Aurelisa Juan Voice agent design + product |
Bill Zhang Swarm + backend orchestration |
Warren Yun Operator console + IPFS pipeline |
| Event HackUTD 2024 · Ripple Effect |
Dates Nov 16–17, 2024 |
Venue ECSW · UT Dallas |
Hackers 1,100+ |
Prize pool $120,810 |
We won Overall 1st Place + Goldman Sachs Track |
Note
What's in this repo vs. what's running in production
The Python backend in server/ is unchanged from the HackUTD build — it still runs the live telephony loop. The Next.js project page in client/ is a post-hackathon rebuild that ports the operator dashboard, adds an interactive walkthrough, and replaces the old WebSocket connection with a session-local mock so the deployed site has zero infra dependencies. Re-binding to the real FastAPI socket is a one-line change in store.ts.
- HackUTD 2024 · Ripple Effect — for hosting the largest 24-hour hackathon in the United States and giving us the constraints that made this fun
- Goldman Sachs — for sponsoring the financial-services track and judging the project
- Retell AI — for telephony + STT/TTS that worked first try at 3am
- OpenAI — for the Swarm framework that made multi-agent handoffs feel almost obvious
- Pinata — for free IPFS pinning that survived the demo
