The pieces
Session lifecycle
From a trigger to an active voice conversation: Text channels (WhatsApp, SMS, widget chat) skip the media path: the inbound message is handed to the flow executor directly and the reply is delivered through the channel adapter. The flow definition is the same either way. The flow executor is stateless per request — every invocation reconstructs state from PostgreSQL. A long conversation runs as many short executor calls, driven by inbound events (transcripts, tool callbacks, child-flow completions).Provider resolution
Each flow selects its STT, TTS, and LLM providers. Configuration for the selected provider merges three layers: Config precedence: flow > organization > provider defaults. The organization supplies credentials (API keys) and shared defaults; the flow picks the provider and overrides tuning per use case. Missing required secrets fail the trigger with HTTP 412 before the agent worker is dispatched — preventing opaque mid-call SDK errors.Channels
Conversations run over eight channel types — phone (SIP), web widget (text + voice), WhatsApp, SMS, API, store-and-forward audio clips, child-flow sessions, and Telegram (planned). Each channel declares its capabilities (addressability, persistence, outbound initiation) and its reachability window. Full detail: Channels. Channel-specific prompt hints are injected into the LLM context so a voice flow gets speech-rendering guidance and a chat flow gets markdown guidance — same flow definition, different rendering hint.Memory
Three layers, all backed by pgvector:- Episodic memory — long-term semantic chunks of user turns, facts, preferences, and observations. Extracted automatically at session end. Searchable by user.
- Persistent variables — flow variables marked as persistent survive across sessions for the same user.
- Knowledge bases — per-organization document collections,
retrievable through the
ragflow node.