Build production-ready AI phone assistants in minutes — not months.
Flow-IO connects your sipgate phone numbers to AI agents with custom prompts, knowledge bases, multi-step call flows, and full analytics. Open-source, self-hostable, European infrastructure.
Self-hosted (everything included):
git clone https://github.com/sipgate/flow-io.git
cp .env.docker.example .env.docker # fill in API keys
docker compose --env-file .env.docker up -dApp only (requires external Supabase):
Most voice AI platforms are black boxes: fixed prompts, opaque pricing, US-only infrastructure, no self-hosting. Flow-IO gives you full control:
- Your prompts — no guardrails, no vendor-imposed behavior
- Your LLM — OpenAI, Google Gemini, or Mistral; swap at any time
- Your data — Postgres + pgvector, self-hosted or Supabase Cloud
- European infrastructure — sipgate backbone, GDPR-compliant by default
- MIT license — fork it, white-label it, build on it
- Custom system prompts with full LLM control
- LLM providers: OpenAI (GPT-5, GPT-4.1, GPT-4o), Google Gemini (2.5 Flash, 2.5 Pro), Mistral (Small, Medium, Large)
- Text-to-speech: ElevenLabs and Azure voices, phoneme dictionaries for pronunciation tuning
- Barge-in control: let callers interrupt the assistant mid-sentence
- Hold message pattern: assistant announces actions before executing them
- Upload documents (PDF, text) — chunked, embedded, stored in pgvector
- Semantic search injected into context automatically
- Knowledge base as an LLM-callable tool (assistant searches on demand)
- Multiple assistants can share one knowledge base
- MCP servers — connect any Model Context Protocol server (SSE or HTTP)
- HTTP Webhook Tools — define custom HTTP endpoints the assistant calls as tools during a conversation; configure per-org, assign to assistants
Visual drag-and-drop call flow builder with node types:
- Entry agent, agent handoff (seamless or with announcement)
- DTMF collect (gather digits, map to variable)
- DTMF menu (digit-based routing with retries)
- Phone transfer
- Define typed variables (string, number, boolean, date, phone, email)
- Collected via DTMF, real-time LLM extraction, or post-call fallback
- Validation via regex or external webhook
- Mandatory collection and caller confirmation per variable
- Post-call webhook fires after every completed call — regardless of whether variables were configured
- Payload: session data, extracted variables (empty array if none), optional full transcript
- HTTP Webhook Tools for real-time data fetching during calls
- Inject external data at call start via a configurable endpoint
- Returned JSON available in prompts as
{{context.key}}
- Call volume, duration, success rate by day/hour/assistant
- CSAT scoring (1–5) evaluated post-call by LLM
- Configurable call criteria (pass/fail checkpoints per assistant)
- Period-over-period comparison, drill-down per call
- PDF report export
- Multi-tenancy with organizations, roles (owner/admin/member), Row Level Security
- sipgate OAuth — sign in with sipgate, phone numbers imported automatically
- WebSocket + HTTP dual-mode webhook handling
- Chat Simulator — test assistants in-browser without a real phone call
- i18n — English, German, Spanish UI
# 1. Clone
git clone https://github.com/sipgate/flow-io.git
cd flow-io
# 2. Configure
cp .env.docker.example .env.docker
# Edit .env.docker — fill in your API keys (see Prerequisites below)
# 3. Start
docker compose --env-file .env.docker up -d| Service | URL |
|---|---|
| Flow-IO app | http://localhost:3000 |
| Supabase Studio | http://localhost:8000 (login: DASHBOARD_USERNAME/PASSWORD) |
| Email test inbox | http://localhost:54324 |
Everything runs in one command: Postgres, Auth, Storage, Realtime, the app, and automatic database migrations.
Note: STT and TTS during live calls are handled entirely by sipgate's infrastructure — you don't need your own speech API keys for calls to work. The keys below are only needed for dashboard features like voice previews, LLM-powered prompt optimization, CSAT scoring, and knowledge base embeddings.
| Service | Purpose | Required for |
|---|---|---|
| sipgate | Login + phone numbers | Everything — create an OAuth app |
| OpenAI | LLM during calls + embeddings | Calls (if using GPT models), KB search, CSAT scoring |
| ElevenLabs | Voice preview in dashboard | Optional — only needed for previewing voices before assigning them |
sipgate OAuth app setup:
- Go to console.sipgate.com/third-party-clients
- Create a new app, set redirect URI to
https://your-domain.com/api/auth/sipgate/callback - Copy Client ID and Client Secret into
.env.docker(or.env.localfor dev)
Google Gemini and Mistral are alternatives to OpenAI for the LLM during calls. Azure TTS is an alternative to ElevenLabs for voice previews. All are optional — configure per assistant.
Flow-IO needs a Next.js host and a Supabase instance. The Docker setup bundles everything. For PaaS platforms, use Supabase Cloud (free tier available).
| Platform | Supabase needed? | Notes |
|---|---|---|
| Docker (self-hosted) | bundled | Full control, runs anywhere |
| Coolify | bundled | Git-connected, deploys full docker-compose.yml |
| Railway (UI import) | bundled | Drag docker-compose.yml onto Railway canvas |
| Railway (button) | Supabase Cloud | App only, add env vars |
| Render / Fly.io | Supabase Cloud | Deploy as Docker container |
Follow Quick Start above.
- Create a new Resource → Docker Compose
- Connect your GitHub repo
- Set Docker Compose file to
docker-compose.yml - Add env vars from
.env.docker.example - Deploy — Coolify handles HTTPS, restarts, and redeploys on push
- Create a new Railway project
- Drag
docker-compose.ymlonto the canvas - Add env vars from
.env.docker.example - Deploy
- Create a Supabase project at supabase.com
- Run migrations:
npx supabase link --project-ref your-project-ref npx supabase db push
- Deploy the app and set env vars from
.env.example
| Variable | Description |
|---|---|
NEXT_PUBLIC_SUPABASE_URL |
Supabase project URL |
NEXT_PUBLIC_SUPABASE_ANON_KEY |
Supabase anon key |
SUPABASE_SERVICE_ROLE_KEY |
Supabase service role key |
SIPGATE_OAUTH_CLIENT_ID |
sipgate OAuth client ID |
SIPGATE_OAUTH_CLIENT_SECRET |
sipgate OAuth client secret |
SIPGATE_WEBHOOK_SECRET |
Shared secret for webhook HMAC-SHA256 verification |
SIPGATE_WEBHOOK_TOKEN |
Token for WebSocket authentication |
NEXT_PUBLIC_APP_URL |
Canonical app URL for OAuth redirects |
OPENAI_API_KEY |
OpenAI API key — LLM during calls, KB embeddings, CSAT scoring |
ELEVENLABS_API_KEY |
ElevenLabs API key — voice preview in dashboard only (optional) |
See .env.example for the full list including optional variables.
npm install
cp .env.example .env.local # fill in API keys
npx supabase start # start local Supabase
npx supabase db push # apply migrations
npm run dev # start dev server → http://localhost:3000┌─────────────────────────────────────────┐
│ Next.js App │
│ (Frontend + API routes + Server Actions│
└──────────┬──────────────┬──────────────-┘
│ │
┌───────▼──────┐ ┌────▼────────────┐
│ Supabase │ │ sipgate │
│ │ │ │
│ - Auth │ │ - OAuth login │
│ - PostgreSQL │ │ - AI Flow SDK │
│ - pgvector │ │ - WebSocket │
│ - Storage │ │ - Phone numbers │
│ - Realtime │ └─────────────────┘
└───────┬──────┘
│
┌───────▼──────────────────┐
│ LLM Providers │
│ OpenAI · Gemini │
│ Mistral · ElevenLabs │
└──────────────────────────┘
Call flow:
- Incoming call hits sipgate → WebSocket event to Flow-IO
session_start→ context webhook fetches external data, variables injected into promptuser_speak→ LLM generates response, optionally calls tools (KB, MCP, HTTP webhooks)session_end→ variables extracted, post-call webhook fired, CSAT + criteria evaluated
| Layer | Technology |
|---|---|
| Framework | Next.js 15 (App Router, standalone output) |
| Language | TypeScript (strict) |
| Styling | Tailwind CSS v4 + shadcn/ui |
| Database | Supabase PostgreSQL + pgvector |
| Auth | Supabase Auth + sipgate OAuth2 |
| Telephony | sipgate AI Flow SDK |
| LLM | OpenAI · Google Gemini · Mistral |
| TTS | ElevenLabs · Azure |
| Testing | Vitest |
- Fork the repo and create a branch
- Follow the code style (TypeScript strict, no
any) - Write tests for new features (
npm testmust pass) - Run
npm run type-checkandnpm run buildbefore opening a PR - Use conventional commit messages
MIT — see LICENSE for details.
