For the static picture — which container talks to which — see Architecture. This page is about movement over time.
Inbound call
A caller dials a number attached to atelephony agent.
The runtime never holds long-lived credentials of its own. It mints a bot token with INTERNAL_API_KEY, and the API returns decrypted provider keys for that organisation only. See Provider credentials.
Inbound registration is idempotent — register_inbound_call returns the existing record if the same provider_call_sid arrives twice, so a provider retry does not create a duplicate call log.
Outbound call
Triggered byPOST /api/v1/calls/outbound, or by a campaign batch.
This path takes no concurrency slot.
initiate_outbound_call() never touches Redis — only CampaignCallDispatcher acquires and releases slots, so an organisation’s ceiling constrains campaigns, not direct POST /calls/outbound requests. See Call concurrency.Campaign call
Campaigns add a queue, a worker, and an orchestrator between the request and the call. Nothing polls the database in a loop: the orchestrator reacts to Redis events and only falls back to a timed sweep to catch stalls. See Campaigns.Knowledge ingest
The document’s metadata and status live in FerretDB; the vectors live in Chroma, on thevoicera_oss_chroma_data volume. At call time the runtime retrieves chunks either as a tool the LLM can call or as prepended context. See Knowledge base.
Call artifacts
Layout inside the bucket:minio:// URIs, not signed URLs. Clients always fetch through the authenticated API proxy, so bucket access never has to be public.
Browser websocket sessions register a
call_type: web CallLog on connect, so they produce transcripts and recordings under the same MinIO paths as telephony calls.