Skip to main content
Flows are directed graphs of typed nodes. The flow executor runs the graph, streams events to the conversation surface, and persists session state in PostgreSQL.

Execution model

The 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). This makes scale-out straightforward: any backend instance can pick up the next event.

Node types

15 node types organised by purpose:

Variables

The agentic node extracts typed variables from the conversation: string, number, boolean, date, phone, email, and image.
  • Asked vs derived — a variable with a prompt is asked of the user; a variable marked derived is authored by the assistant from context and never asked (e.g. a ticket subject line).
  • Image variables are filled by the runtime from media the user sends — never by the LLM.
  • Persistent variables survive across sessions for the same user.
  • Whether a variable is required is decided per edge: an edge can require variables (or a photo on the current turn) before it can be traversed.

Parallel execution

Parallelism is expressed on the graph itself: multiple edges leaving the same port, marked parallel, fan out into concurrent branches. The engine computes where the branches reconverge and merges their results. Branches coordinate at runtime: only one branch speaks to the user at a time (the first to produce output wins the voice), and wait nodes in sibling branches cancel automatically when another branch starts responding.

Invoke → return (child flows)

A parent flow can invoke a child flow — the pattern behind consultations, relays, and warm transfers:
  • Ringing — a dial target is a person, not a device: ringing reaches all their endpoints (in-app notification on every signed-in device + their phone number); the first answer wins. Multiple targets can ring in parallel or sequentially.
  • Hold + narration — the original caller can be held with a message or music, and the parent can narrate child progress (“I’m reaching your advisor now…”) driven by child lifecycle events.
  • Completion typesreturn (the agent comes back to the caller with a result), bridge (the caller is connected directly to the consulted party), or handoff (external transfer).
  • Keep-alive — a child can be kept alive after returning, so a follow-up invoke reconnects the same consulted party without ringing again.

Tools

The toolExecutor node runs configured tools: Tools are authored directly, imported from a cURL command, or imported from an OpenAPI spec. Tool secrets are scoped per organization and injected at invocation time — flow definitions never contain credentials. Asynchronous tools: a tool that reports async completion either routes the flow onward immediately on a pending port or parks the session; your system resumes it later by calling a single-use, HMAC-signed callback URL.

Memory

Three layers, all backed by pgvector:
  • Episodic memory — at session end, an extraction pass turns the transcript into individually embedded facts, preferences, and observations, recalled in later conversations.
  • Persistent variables — flow variables marked persistent are restored at the start of the user’s next session.
  • Knowledge bases — per-organization document collections; ingestion chunks and embeds, retrieval through the rag node.
Identity is unified across channels — the same phone number on voice, SMS, and WhatsApp maps to one memory profile, and anonymous web memory is merged into the verified identity once the visitor is identified.

Storage + versioning

Flows are stored as JSON and schema-validated at write time. Every save appends an immutable version snapshot with author and optional release notes; version numbers are gapless per flow. Rollback writes the selected snapshot back as a new version — history is never mutated. Flows can be exported via the API for Git-tracked operator workflows.

Sessions

Every flow run is persisted with full variable state, tool-call log, and final status. Operators can list, inspect, export, end, or resume sessions through the dashboard or the REST API (see API reference).