Back to Case Studies

CallIntel: running voice agents on real telephony, for many tenants

A multi-tenant platform for building, running and observing production voice agents — control plane, media plane, telephony, channels and the operational tooling around them.

Sector
Voice AI and telephony
Engagement
October 2025 – August 2026, still active
  • Python
  • FastAPI
  • PostgreSQL
  • LiveKit
  • Twilio
  • React
  • Flutter

Context

A voice agent that works in a demo and one that answers a real phone call are different systems. The second needs carrier trunks, turn-taking that holds up over lossy audio, isolation of agents and knowledge per tenant, scheduling and batching for outbound work, and enough telemetry that a call which went badly can be reconstructed afterwards. CallIntel is the platform layer for that problem: not one agent, but the machinery to build, run and observe many of them across tenants and channels.

What we built

  • Backend API

    Control plane: tenants, agents, knowledge bases, scheduled and batched calls, billing.

  • Voice worker

    Owns the live call leg — audio in, turn detection, model, audio out — with bench and eval suites of its own.

  • Web app

    Where tenants configure agents and watch calls in progress.

  • Mobile app

    Companion app; Dart is 85% of the repository by the languages API.

  • WhatsApp channel

    A second channel into the same agents, separate from telephony.

  • Content and documentation

    Marketing content out of a CMS; a docs site the API contract is published against.

Architecture

The system is split along the line that matters in voice — a control plane and a media plane. The control plane is an async FastAPI service: SQLAlchemy over asyncpg, Alembic migrations, Celery on Redis for batch and scheduled calls, pgvector for per-tenant knowledge retrieval, Argon2 and TOTP on the auth path. The media plane is a separate LiveKit worker that owns the live call and nothing else. Turn detection is treated as a swappable component rather than a setting: the worker carries four independently pinned requirement sets (pipecat, rnnoise, smart-turn, VAD) and ships with its own bench/ and evals/ directories, so a change to the turn model can be measured rather than argued about. Telephony is not single-vendor — Twilio and Plivo sit behind the same API alongside LiveKit, and the earlier generation of the backend already separated three carrier managers and three model bridges, so provider substitution was a design assumption rather than a later retrofit. Observability was wired at the start: OpenTelemetry API and SDK with FastAPI, SQLAlchemy and httpx instrumentation exporting over OTLP, alongside Prometheus metrics, Sentry and structlog. It all lives in one pnpm/turbo monorepo — 11 apps and 6 shared packages, including Python and TypeScript SDKs so internal apps and external integrations consume the same contract — with terraform/, kubernetes/, docker/, caddy/ and backup/ checked in beside the application code.

Stack

Backend API
  • Python
  • FastAPI
  • async SQLAlchemy + asyncpg
  • PostgreSQL
  • Alembic
Voice worker
  • Python
  • LiveKit
  • webrtcvad
  • google-genai
Web app
  • React
  • @livekit/components-react
  • Supabase (SSR + JS)
  • TanStack Query
Mobile app
  • Flutter / Dart
  • SDK ^3.12.0
WhatsApp channel
  • Python
  • FastAPI
  • FastMCP
  • Selenium
Content and documentation
  • Strapi 5.31.0
  • Mintlify (MDX)
Integrations
  • LiveKit — real-time media transport for the live call leg
  • Twilio and Plivo — carrier telephony behind a single API
  • OpenAI and Google Gemini — model providers
  • Supabase — auth and Postgres for the web surfaces
  • pgvector — retrieval over per-tenant knowledge bases
  • Stripe and Razorpay — two payment providers, not one
  • Shopify — a dedicated app and API surface
  • OpenTelemetry, Prometheus and Sentry — traces, metrics and errors

Scale

Counts that can be re-derived from the same repositories. Nothing here is a business result — a repository cannot evidence one.

  • 699 commits across 10 repositories; the monorepo alone accounts for 592.
  • 11 apps and 6 shared packages in the monorepo.
  • 4 independently pinned voice-pipeline requirement sets.
  • 40 entries under docs/, and 4 CI workflows.

Where the evidence stops

  • No business outcome is claimed, because none is evidenced by a repository.

Evidence

Each statement above, and the artefact it was read from. The client cannot be named, so the sources are given instead.

  • 699 commits across 10 repositories.

    Sourcesum of history.totalCount on each repository's default branch; the monorepo alone accounts for 592

  • The monorepo holds 11 apps and 6 shared packages.

    Sourceapps/ and packages/ tree listing in the CallIntel monorepo

  • Telephony and media dependencies: livekit-api >=1.1.0, twilio >=9.10.9, plivo >=4.60.1.

    Sourceapps/api/pyproject.toml

  • 4 voice pipeline variants, each an independently pinned requirement set.

    Sourceapps/voice-worker/requirements-{pipecat,rnnoise,smart-turn,vad}.txt

  • Operational documentation runs to 40 entries under docs/, including ARCHITECTURE, TENANCY, OBSERVABILITY, CAPACITY, DR_PLAN, SECRET_ROTATION and PENTEST_RUNBOOK.

    Sourcedocs/ tree listing in the monorepo

  • 4 CI workflows — CI, Security, SAST and an OpenAPI check.

    SourceGitHub Actions badges in the monorepo README

  • Engagement span: 2025-10-16 → 2026-08-10, still active.

    Sourcefirst and last commit dates across the CallIntel repositories, via the commits API

Related capability

AI Call Agent