Inspiration

I kept coming back to one line from Dario Amodei's essay Machines of Loving Grace:

"if AI further increases economic growth and quality of life in the developed world, while doing little to help the developing world, we should view that as a terrible moral failure."

GDP per capita in Sub-Saharan Africa sits at roughly $2,000 compared to $75,000 in the United States. That gap isn't a law of nature, it's a consequence of unequal access to tools, infrastructure, and capital. A well-funded startup in San Francisco has had AI-assisted outbound sales since at least 2023. A small business in Kigali is still cold-calling from a spreadsheet and a personal phone.

outreach is my answer to that imbalance.


What It Does

outreach is a full-stack AI calling platform. A business:

  1. Creates a campaign and describes their product
  2. Uploads a CSV of leads (with explicit consent confirmation)
  3. Claude reads each lead's context and writes a personalised system prompt for that specific person
  4. An AI voice agent (powered by Claude + ElevenLabs) places the call and holds a natural conversation
  5. After each call, Claude analyses the transcript, scoring interest, extracting objections, recommending a next step, and drafting a follow-up message
  6. A campaign rollup synthesises all outcomes into a strategic brief

Crucially, it routes intelligently: US numbers (+1) go through Vapi's native phone number, Rwanda numbers (+250) go through a Twilio number imported into Vapi, so the platform works for both the builder's local testing environment and real Rwandan leads.


How I Built It

Layer Technology
Frontend & API Next.js 16 (App Router), TypeScript
AI — pitch generation & analysis Claude API (claude-haiku-4-5, claude-sonnet-4-5)
Voice calling Vapi + ElevenLabs (Rachel voice)
Rwanda calling Twilio number imported into Vapi
Database Supabase (PostgreSQL) + Prisma 7
CSV parsing Papaparse
Animations Framer Motion
Deployment Vercel

The architecture keeps all AI and telephony calls server-side only — API keys never touch the browser. Claude is used at three distinct stages: pre-call personalisation, post-call analysis, and batch strategic rollup.


Challenges

Vapi model config — Vapi's AnthropicModel type uses messages: [{ role: "system", content }], not a top-level systemPrompt field. Every call was playing Vapi's default demo message until I read the SDK type definitions and found the correct field name. Debugging a voice call with no stack trace is humbling.

Prisma 7 breaking changes — Prisma 7 removed the url field from datasource in the schema. Runtime DB connections now require a driver adapter (PrismaPg) instead of a connection string passed to the constructor. The migration also broke with a provider mismatch error until I realised the generated client was cached from before the sqlite → postgresql schema change.

Supabase connection limits — The session pooler (port 5432) holds one server connection per client for the entire session. In Next.js dev mode, each hot reload created a new pg.Pool, exhausting the 15-connection limit within minutes. Fixed by switching to the transaction pooler (port 6543) and capping max: 3 on the pool.

Rwanda number routing — Vapi's free phone number only calls US (+1) numbers. Getting Twilio working required importing the Twilio number into Vapi via their API, getting the resulting UUID, and building a routing layer that detects the country prefix (+250 vs +1) and picks the right caller ID.

Making AI sound human — The first calls were noticeably robotic. Tuning ElevenLabs stability: 0.4, style: 0.35, adding stopSpeakingPlan for immediate interruption handling, and a short responseDelaySeconds made a significant difference. Backchanneling (mm-hmm, right) was attempted but turned out to be a paid Vapi feature.


What I Learned

  • Reading SDK type definitions is faster than guessing field names from docs
  • "Session pooler" and "transaction pooler" are not interchangeable — the difference matters enormously at scale
  • The consent UX is not a legal formality. It's the first signal to a user that the tool takes responsibility seriously
  • Voice latency and naturalness are product features, not infrastructure details — they determine whether the product is usable at all
  • Building in Rwanda, for Rwanda, matters. Routing to +250 numbers and citing Rwanda's Data Protection Law aren't edge cases — they're the point

What's Next

  • Business verification before platform access (RDB registration number, use-case review)
  • Persistent do-not-call registry — leads who opt out are blocked across all campaigns
  • Consent audit log — timestamped record of who confirmed consent for which leads
  • Multi-language support — Kinyarwanda pitch generation via Claude
  • Real-time call dashboard — live status during active campaigns

Built With

  • claude
  • elevenlabs
  • next
  • vapi
Share this project:

Updates