Ringer makes the phone calls you hate — negotiating bills, cancelling subscriptions, chasing refunds, comparing quotes — and hands back an honest, structured result, not just a transcript.

Inspiration

Everyone has a short list of calls they keep putting off: the retention line that won't let you cancel, ringing five shops to compare a price, chasing a refund through a phone tree. They're high-friction, easy to procrastinate — and the ones with money on the line quietly cost you every week you delay. CALL-E can place a real phone call from code; we wanted to turn that raw capability into outcomes you can actually trust, especially across several businesses at once.

What it does

You describe a call in plain English — lower my internet bill, cancel my gym membership, book a dentist appointment, get quotes from five auto shops. Ringer compiles it into a tuned CALL-E task with a strict result schema, places the call, and returns a typed outcome: the new price, the confirmation number, the booked time, the refund amount, the quote — each with CALL-E's completion confidence, quoted evidence, and the full transcript.

Six playbooks (negotiate-bill, cancel-subscription, chase-refund, book-appointment, get-quote, general-inquiry) plus a custom mode. Two ideas make it different from a generic "AI calls for you" wrapper:

  • It names its denominator. Quote Shootout calls several businesses at once and reports how many were called, reached, and answered. A business that hit voicemail or declined is never counted or folded into the comparison ("2 quoted of 3 called · 1 not reached — not counted"); cheapest/savings are computed over answered businesses only.
  • It won't assert what it can't back. Every completed call is tagged evidence-backed or needs review from CALL-E's confidence + quoted evidence, and shared output flags anything unverified.

It also does human-in-the-loop decision authority ("capture the offer but don't commit"), a "Rate Watch" that re-negotiates before a promo expires, multilingual calls, and local-currency reporting (₦, €, ₹, …) so it works outside the US.

How we built it

React 19 + Vite + Tailwind v4 front end, with Vercel serverless functions as a thin proxy. On the CALL-E Developer API: client.calls.create() with per-call and per-recipient strict result_schemas, a create-then-poll live timeline over /v1/calls/{id} + /events (real calls outlast serverless timeouts), and signed-webhook verification (client.webhooks.unwrap(), HMAC over timestamp + "." + raw_body). Batch mode pairs a recipient_result_schema with a call-level aggregate schema.

Safety is built in: BYOK (the user's key lives only in their browser, never persisted), an optional operator key gated by CALLE_APP_SECRET (fail-closed, so strangers can't spend it on a public deploy), content-bound idempotency (hash of phone + task + schema), and a base-URL allowlist. A durable scheduler (Vercel KV + cron) fires recurring calls, each cancelable until it runs. And a full client-side Demo Mode simulator reproduces CALL-E's object model — statuses, streaming transcript turns, events, structured results, confidence, evidence — so the entire product runs with no key and zero credits. We also packaged the playbook engine as a standalone CALL-E Agent Skill (ringer-consumer-tasks).

Challenges we ran into

  • result_schema rejects nullable union types ({"type":["string","null"]}), and the actionable reason only surfaces in details.reason — it cost us a live-testing cycle.
  • Batch calls return no per-recipient transcript (single calls do), which removed the only signal we had for inferring reachability.
  • The big one: on live calls that didn't connect, CALL-E sometimes fabricated a transcript/disposition, and marked a task completed before the calls actually happened — a recipient shown as "No answer" received the real call minutes later. We only caught it because we owned the test numbers. Rather than trust the provider blindly, this pushed us to make Ringer honest by construction: denominator-honesty and evidence-gating mean it never launders an unreached call into a result. We filed detailed feedback with video repros.
  • CALL-E's region matrix doesn't list Nigeria, yet +234 numbers dial fine — so we route Nigerian calls through a supported English region while dialing the real number.

Accomplishments that we're proud of

  • Honesty as a product feature — batch results state their denominator, and outcomes are tagged verified vs. needs-review. It's the thing we'd want if an agent made calls on our behalf.
  • A deep, real CALL-E integration (dual strict schemas, create-then-poll, signed webhooks) with production-grade safety hardening, backed by 143 automated checks.
  • A no-credit Demo Mode that faithfully mirrors the real object model, so anyone can experience the whole app instantly.
  • Multilingual + local currency, so it's useful well beyond the US.

What we learned

  • Strict result schemas + confidence/evidence are the right trust primitives — build directly on them.
  • Grounding is everything. A fabricated transcript is worse than an empty one; verify reachability before you count anything.
  • Safe outbound calling has real patterns worth codifying: content-bound idempotency, persisting the accepted call id before polling, reconciling ambiguous creates, and fail-closed credential handling.

What's next for Ringer

  • Officially support more regions (Nigeria / ₦ first).
  • Generalize our fabrication-detection into provider-agnostic reachability guardrails.
  • More playbooks, deeper scheduling, and a shared savings dashboard.

Built With

Share this project:

Updates

Submission history