Flows
Graph-based call logic with a publish-and-freeze model.
A flow is a graph of nodes that drives a call's conversation. You
author graphs in the dashboard editor; at publish time the graph is
compiled and frozen into a runtime artifact (objective,
outcome_schema, tools). Runtime reads the frozen columns only — editing
a graph never silently changes the behavior of in-flight or published flows.
States
- Draft — editable. Saved as
graph_jsonon the flow row. - Published — compiled artifact written to
published_compiled_*. Live calls use this. Editing a draft after publish has no effect until you re-publish.
Endpoints
GET /v1/flows— list flows (all states).POST /v1/flows— create a new draft.POST /v1/flows/{flow_id}/preview— dry-run the compile (no persistence).POST /v1/flows/{flow_id}/publish— compile and freeze.
Node types today
OpenPhn ships a handful of node types (message, question, branch, etc.) and seeds five starter templates. Snippet / custom-tool nodes are not yet supported — the compiler rejects them. Template-based graphs cover the common cases; reach out if you need something bespoke.
Attaching a flow to a number
Set flow_id on the number via PATCH /v1/numbers/{number_id}. Inbound
calls to that number run the attached flow.
Advanced per-flow options
A flow definition can carry optional blocks alongside nodes that tune
runtime behavior:
clarify_on_uncertainty— appends a clause to the system prompt telling the model to ask the caller to repeat when it isn't confident it heard correctly, instead of guessing. Pairs with the "Didn't catch" metric so you can see how often it fires.keypad— collect touch-tone (DTMF) input during the call, masked by default. See Keypad (DTMF).
name: appointment-confirm
entry: ask
nodes:
# ...
clarify_on_uncertainty: {} # enable; the clause is appended automatically
keypad:
ending_mode: terminator
terminators: ["#"]These blocks are compiled into the frozen artifact at publish time like the rest of the graph.