Skip to content

Flows: guide a call step by step

An assistant follows its instructions. A flow gives a call structure: it walks the call through steps, such as greet, ask for the customer’s ID, look the order up on your server, answer, offer a transfer, say goodbye, and branches on what happens at each one. Use a flow when the conversation has to follow your process every time, and the instructions alone when the call can wander.

Flows are built in the visual editor, BuildFlows: on a canvas, from a template, or by describing the flow in words and letting the AI draw it. There are three kinds:

Kind What it does
Voice AI flow Guides an AI assistant through a phone call, step by step. The assistant still talks naturally inside each step.
IVR A keypad and speech menu for inbound lines (“press 1 for sales”), with opening hours, Shabbat and holidays. No AI model is needed.
Agent script A branching script the copilot shows to human agents during their calls.
  1. Before the call, a Pre-call API node can fetch the caller’s details from your CRM, so the greeting can use them.

  2. The call starts at Start and moves from node to node. Each node has transitions, and the first one that matches moves the call on: what the caller said (decided by the model), a key they pressed, a rule on the variables, or a time-out.

  3. Global nodes can interrupt from anywhere: a Knowledge answer for a question off the script, a Transfer call when the caller asks for a person. Return goes back to where the call was.

  4. After the call, the nodes of the After the call phase run on their own: extract details, classify the call, set its outcome, and send the results to your systems.

Node Type What it does In flows for
Pre-call API precall_api Fetch the caller’s details before saying hello (CRM lookup). Voice AI, IVR
Node Type What it does In flows for
Start start Where every call begins — the greeting. Voice AI, Agent script, IVR
Say say Say an exact line (instant, from cache) or a line the AI rephrases naturally. Voice AI, IVR
Conversation dialogue A free conversation step with a goal — the AI talks until a transition matches. Voice AI
Ask & collect question Ask for one detail (name, date, ID…), validate it and store it in a variable. Voice AI, IVR
Decision decision Branch by rules on variables — no AI, always the same result. Voice AI, Agent script, IVR
Knowledge answer kb_answer Answer the caller’s question from your knowledge base. Voice AI
API / Webhook api Call any system (CRM, calendar, your server) and use the answer in the call. Voice AI, IVR
Set variable set_var Store or calculate a value for later steps. Voice AI, Agent script, IVR
SMS sms Send a text message during the call (link, confirmation, address). Voice AI, IVR
Email email Send an email during the call. Voice AI, IVR
Transfer call transfer Hand the caller to your agents, another number, or another AI agent. Voice AI, Agent script, IVR
Add participant add_participant Dial someone into the call — the AI greets them and runs a three-way call. Voice AI
Keypad menu dtmf_menu “Press 1 for… 2 for…” — the caller may also just say the option. Voice AI, IVR
Payment pause pci_pause Stop recording and transcribing while the caller pays (card details never reach the AI); resume after. Voice AI, IVR
Business hours hours Open, closed or a holiday right now? Weekly hours, Shabbat and Israeli holidays, special dates. IVR, Voice AI
Switch language set_language Continue the call in another language and voice. IVR, Voice AI
Voicemail voicemail The caller leaves a message after the beep — recorded, transcribed and summarized. IVR, Voice AI
Schedule callback schedule_callback Book a time to call the customer back. Voice AI, IVR
End call end Say goodbye, save the outcome and hang up. Voice AI, IVR
Return return Go back to where the caller was before this side-topic. Voice AI, Agent script, IVR
CRM / calendar action integration Use a connected CRM or calendar during the call: look the caller up, add a note, create a task. Voice AI, IVR
Node Type What it does In flows for
After the call post_start Everything here runs automatically after the call ends. Voice AI, IVR
Extract details extract Let AI pull structured details out of the conversation. Voice AI, IVR
Classify call classify Let AI pick one category for the call and branch on it. Voice AI, IVR
Set outcome set_outcome Save the call’s result (disposition) for reports and campaigns. Voice AI, IVR
API / Webhook post_api Send the call’s results to any system after it ends. Voice AI, IVR
CRM / calendar action post_integration After the call, update a connected CRM: add a note, create a follow-up task. Voice AI, IVR
SMS post_sms Text the customer after the call (summary, link, confirmation). Voice AI, IVR
Email post_email Email the summary to your team or the customer. Voice AI, IVR
Node Type What it does In flows for
Call step step One step of the agent’s script: what to say, what to ask, what not to miss. Agent script
Customer answer branch Branch the script by what the customer answers. Agent script
Objection objection When the customer objects anywhere in the call — how to answer, then go back. Agent script
Call outcome outcome How the call ended (sale, follow-up, not interested…) and what to wrap up. Agent script

Text in a flow can use {{variables}}: שלום {{customer_name}}, or {{call.from}} in the body of an API request.

  • The call’s variables: what you pass as variables when you create a call, and a campaign contact’s columns.
  • System variables: {{call.id}}, {{call.from}}, {{call.to}}, {{call.direction}}; {{now.date}}, {{now.time}} and {{now.weekday}} in Israel time; {{contact.…}} and {{campaign.…}} on campaign calls.
  • Variables the flow sets: Ask & collect stores the answer it validated, Set variable stores or calculates a value, and an API / Webhook node maps fields of your server’s answer to variables.
  • Secrets: {{secret.NAME}} puts a stored secret (an API token, say) into an API request. Its value never appears in the editor, the logs or the API.

The editor saves a draft as you work. Publishing checks the flow first: errors (a step with no way out, an API node without a URL) block it, warnings don’t. Each publish creates a numbered version, and only the published version runs on calls, so you can keep editing the draft safely. Any earlier version can be restored into the draft and published again. Every publish sends the flow.published event.

A flow an assistant or a copilot profile uses can’t be deleted: detach it first.

A published voice flow drives every call of the assistant it is attached to (flow_id on the assistant), or one outbound call (flow_id when you create the call, instead of assistant_id):

Terminal window
# Let a published voice flow drive the assistant's calls, step by step. null detaches it.
curl -X PATCH https://api.morevoice.ai/v1/assistants/$ASSISTANT_ID \
-H "Authorization: Bearer $MOREVOICE_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "flow_id": "'"$FLOW_ID"'" }'
# Or run the flow for one outbound call only: it runs on its linked assistant.
curl https://api.morevoice.ai/v1/calls \
-H "Authorization: Bearer $MOREVOICE_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"to": "+972500000001",
"flow_id": "'"$FLOW_ID"'",
"purpose": "service",
"variables": { "customer_name": "דנה" }
}'

An IVR or voice flow can also answer a number directly: give an inbound route a flow target.

GET /v1/calls/{id}/flow_path shows the nodes a call went through: when it entered each one, how the step was chosen (llm, dtmf, condition, timeout), how many turns the caller spent in it, and how the flow ended. While the call runs, live is true and more steps follow.

Terminal window
# The nodes a call went through in its flow: how each step was chosen, when, and how the flow ended.
curl https://api.morevoice.ai/v1/calls/$CALL_ID/flow_path \
-H "Authorization: Bearer $MOREVOICE_API_KEY"

When a node fails during a call (your API timed out, an SMS couldn’t be sent), MoreVoice sends the flow.node_failed event, and the call follows the node’s error transition.

/v1/flows builds and publishes flows from code, so a flow can live in your repository and ship with your release:

Request What it does
POST /v1/flows Creates a flow (voice, ivr or agent_script) with an empty draft, a template’s, or the graph you send.
GET / PUT /v1/flows/{id}/draft Reads and replaces the editable draft. base_rev is the draft’s rev you read: a draft changed since answers 409 and nothing is written.
POST /v1/flows/validate Checks a graph without saving it: the errors that would block publishing, and warnings.
POST /v1/flows/{id}/publish Publishes the draft as a new version, with a note; calls use it at once. A draft with errors answers 409 flow_invalid, with what to fix.
GET /v1/flows/{id}/versions, …/restore Lists the published versions, and copies one back into the draft.
POST /v1/flows/{id}/duplicate, GET …/usage Copies a flow, and shows what uses it (assistants and copilot profiles): a flow in use can’t be deleted.
Terminal window
# Change the greeting of a flow's draft, then publish it. base_rev is the draft revision you read:
# if someone changed the draft meanwhile, the write answers 409 and nothing is saved.
draft=$(curl -s https://api.morevoice.ai/v1/flows/$FLOW_ID/draft -H "Authorization: Bearer $MOREVOICE_API_KEY")
echo "$draft" \
| jq '{ base_rev: .rev, graph: (.graph | (.nodes[] | select(.type == "start") | .start.greeting) |= "שלום, הגעתם לאקמה. במה אפשר לעזור?") }' \
| curl -X PUT https://api.morevoice.ai/v1/flows/$FLOW_ID/draft \
-H "Authorization: Bearer $MOREVOICE_API_KEY" \
-H "Content-Type: application/json" \
--data-binary @-
curl https://api.morevoice.ai/v1/flows/$FLOW_ID/publish \
-H "Authorization: Bearer $MOREVOICE_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "note": "New greeting" }'

The API’s nodes are a stable public subset of the editor’s: start, say, question, ai_agent, kb_answer, api, post_api, integration, post_integration, set_variable, decision, dtmf_menu, hours, transfer and end. Every other node (an SMS, a voicemail, an agent-script step, and any node the editor adds later) reads as { "type": "internal" } and is written back exactly as it was, so a new node in the editor never breaks your code.