# Call Flow Builder

### What is the Call Flow Builder?

The Call Flow Builder is a visual, drag-and-drop editor for designing how incoming calls are routed, greeted, and qualified — without writing a single line of code. Instead of a single "forward to this number, else voicemail" rule, you can build a tree of decisions: greet the caller, ask them to press a key, check business hours, route to a team, tag the call, send a follow-up SMS, and more.

<figure><img src="/files/yigUWRUR52EUuTFs3HZr" alt=""><figcaption><p>The flow builder canvas with a published IVR flow</p></figcaption></figure>

{% hint style="info" %}
**Use cases at a glance:** Press-1-to-connect spam filters, time-of-day routing (open vs. closed), multi-agent ring groups, VIP repeat-caller lanes, consent-driven SMS follow-ups, and mid-call CRM lookups with dynamic branching.
{% endhint %}

{% hint style="warning" %}
**Plan availability:** All plans can use every node type **except** Agent Queue and Webhook, which require **Agency** because they depend on Agency-only infrastructure (the browser dialer for Agent Queue, API + webhook access for Webhook).

Templates, simulation mode, and full Flow Analytics are available on every plan.
{% endhint %}

***

### Before You Start

{% hint style="info" %}
**New campaigns start without routing.** When you create a new campaign, you'll land on the campaign page with a routing picker. Pick "Use a call flow" and attach the flow you just published — that's how a freshly-created campaign gets connected to a flow.
{% endhint %}

{% stepper %}
{% step %}
**Confirm your Twilio setup is working**

Calls can only be routed through flows if your tracking numbers are already receiving calls. If you haven't imported numbers yet, do that first — see the [Phone Numbers guide](/guides/phone-numbers.md).
{% endstep %}

{% step %}
**Decide which campaign will use the flow**

Flows are **reusable** — one flow can power many campaigns. Pick the campaign you want to upgrade from a simple forward rule to a full IVR, or create a new campaign for it.
{% endstep %}

{% step %}
**(Optional) Set up ElevenLabs for AI voices**

If you want natural-sounding AI voices instead of Twilio's built-in voices, add your ElevenLabs API key to your workspace. See [Voice and audio (ElevenLabs voices)](https://help.ringtonic.app/guides/setup-workspace#voice-and-audio-elevenlabs-voices-optional) in the Setup Workspace guide.
{% endstep %}

{% step %}
**(US only, required for SMS) Register for A2P 10DLC**

If your flow uses **SMS** or **Opt-In / Consent** nodes and your sending number is a US 10-digit long code, you must register the number for A2P 10DLC before any text messages will deliver. US carriers silently block messages from unregistered 10DLC numbers — Twilio reports the send as accepted but the message never reaches the recipient.

* Register via the [Twilio Console A2P 10DLC flow](https://console.twilio.com/us1/develop/sms/regulatory-compliance/a2p-onboarding?activeStep=usA2POnboarding:customerProfileRegistration:businessProfileNeeds) — brand registration takes \~1 business day, campaign approval \~1–3 business days.
* Toll-free numbers have a simpler [verification path](https://www.twilio.com/docs/messaging/compliance/toll-free/console-onboarding) and are a good alternative for low-volume use cases.
* See the [Twilio A2P 10DLC guide](https://www.twilio.com/docs/messaging/compliance/a2p-10dlc) for the full process.

{% hint style="warning" %}
Carrier filtering blocks unregistered 10DLC traffic with Twilio error code **30034**. Ring Tonic surfaces this in the call's **Timeline** tab so you can see exactly which messages were blocked and why.
{% endhint %}
{% endstep %}
{% endstepper %}

***

### Creating Your First Flow

{% stepper %}
{% step %}
**Open the Call Flows page**

Go to **Call Flows** in the sidebar and click **Create Flow**. Give it a name (e.g., "Main Inbound IVR") and an optional description.

<figure><img src="/files/uZkmfYjHlhq2wn7StJBi" alt=""><figcaption><p>Create Flow dialog with name and description</p></figcaption></figure>
{% endstep %}

{% step %}
**Pick a starting point: Blank or template**

The Create Flow dialog has a tabbed picker on the left:

* **Templates** — Built-in starting points: Simple Forwarding, IVR Menu, Business Hours, Sales Team, Spam Filter + Forward, Multi-Location, Simultaneous Ring, Voicemail Only, VIP Tag Routing, and Webhook Smart Routing. Each pre-fills a working flow with all fallback edges already wired, so you only need to swap in your own phone numbers and prompts before publishing.
* **My Templates** — Custom templates you've saved from your own flows. See [Saving a flow as a custom template](#saving-a-flow-as-a-custom-template) below.
* **Blank Flow** — Start from an empty canvas with just a Start node.

Picking a template pre-fills the name field; you can override it before clicking **Create Flow**.
{% endstep %}

{% step %}
**Land on the canvas**

You'll see your starting graph — either a blank canvas with a single **Start** node, or the template's pre-built nodes ready to customize. Every flow has exactly one Start — it's your caller's entry point.
{% endstep %}

{% step %}
**Add your first node**

Click the **+** button on the Start node to open the node picker. Pick a node type (e.g., "Greeting") — Ring Tonic automatically places and connects it to Start.

<figure><img src="/files/AtJ4kksF9h4okci3UPN5" alt=""><figcaption><p>Node picker showing all available node types grouped by category</p></figcaption></figure>

{% hint style="success" %}
**Auto-layout:** Ring Tonic lays out nodes for you automatically using a top-down tree. You don't need to drag nodes around — just click to add, and the canvas organizes itself.
{% endhint %}
{% endstep %}

{% step %}
**Configure the node**

Click any node to open its configuration panel on the right. Each node has different settings — for example, a Greeting node lets you pick an audio provider, type the message, and choose a voice.

<figure><img src="/files/kq1sQMcBximFTxrYrFd6" alt=""><figcaption><p>Node configuration panel on the right side of the canvas</p></figcaption></figure>
{% endstep %}

{% step %}
**Keep adding nodes**

Repeat for each step your flow needs: a Menu for keypress options, Dial to forward, Voicemail as a fallback, and a Hangup at the end. Each node's output ports (the small handles under it) auto-connect to the next node you add.
{% endstep %}

{% step %}
**Publish the flow**

Click **Publish** in the top-right. Ring Tonic validates the flow — no orphan nodes, every path leads to a terminal, all required configs are set — and snapshots it as version 1. Only published versions answer real calls.

<figure><img src="/files/ymwxByyOIyqVaUWq1b4B" alt=""><figcaption><p>Publish dialog with version note and strict validation results</p></figcaption></figure>
{% endstep %}
{% endstepper %}

#### Saving a flow as a custom template

Once you've built a flow you'd like to reuse — e.g., a polished intake pattern your agency uses across many client campaigns — save it as a custom template so it appears under **My Templates** in the Create Flow dialog for future flows.

{% stepper %}
{% step %}
**Open the flow's card menu**

On the **Call Flows** index, click the **⋯** menu on the flow's card and pick **Save as template**.
{% endstep %}

{% step %}
**Name and describe the template**

Give the template a clear name (e.g., "Lead-gen intake with VIP lane") and a short description explaining what it's for. The current flow's nodes and edges become the template's starting graph.
{% endstep %}

{% step %}
**Reuse it in any future flow**

The next time you click **Create Flow**, your saved template appears under the **My Templates** tab. Pick it to start a new flow pre-populated with the saved graph.
{% endstep %}
{% endstepper %}

{% hint style="info" %}
**Custom templates are workspace-scoped.** A template saved in one workspace isn't visible to other workspaces. Built-in templates are visible everywhere.
{% endhint %}

***

### Understanding the Canvas

The canvas has a few core areas:

| Area                          | What it does                                                                 |
| ----------------------------- | ---------------------------------------------------------------------------- |
| **Toolbar (top)**             | Save indicator, zoom controls, Simulate, Publish, Version History, Analytics |
| **Canvas (center)**           | Your flow graph — nodes, edges, and output port connections                  |
| **Node picker (left panel)**  | All available node types, grouped by category                                |
| **Config panel (right side)** | Appears when you select a node; all its settings live here                   |
| **Minimap (bottom-right)**    | Bird's-eye view of the whole flow for quick navigation                       |

{% hint style="info" %}
**Auto-save:** Every change you make is saved to the draft automatically. You only need to click **Publish** when you're ready to put the changes live. Real calls continue to use the previously published version until you publish again.
{% endhint %}

***

### Node Types

Every flow is built from nodes. Here's what each one does:

#### Call flow basics

These are available on all plans and form the core of any flow.

| Node               | What it does                                                             |
| ------------------ | ------------------------------------------------------------------------ |
| **Start** ▶        | Entry point. Required. Holds flow-level settings like timezone.          |
| **Greeting** 🔊    | Plays an audio message — typed text (TTS) or an uploaded MP3.            |
| **Menu** ⌨         | "Press 1 for Sales, press 2 for Support." Branches on the digit pressed. |
| **Dial** 📞        | Forwards the call to a single phone number, with optional whisper.       |
| **Voicemail** 📧   | Plays a greeting then records the caller's message (with transcription). |
| **Hangup** ✋       | Ends the call, with an optional farewell message.                        |
| **Spam Filter** 🛡 | Pre-configured "Press 1 to connect" Menu — blocks silent robocallers.    |

#### Team and time routing

Available on all plans.

| Node                       | What it does                                                                                                         |
| -------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| **Business Hours** 🕐      | Routes based on time: open hours → one path, closed → another, with optional holiday override.                       |
| **Simultaneous Ring** 📱📱 | Rings several phone numbers at once; first to answer wins. Supports "whisper confirm" to prevent voicemail stealing. |
| **Round Robin** 🔄         | Rotates through a list of destinations. Least-recent or weighted distribution.                                       |

{% hint style="warning" %}
**Sim Ring and Round Robin are PSTN-only today.** They ring phone numbers, not browser agents. To route to online dialer agents, use the **Agent Queue** node (Agency). Browser-agent support in Sim Ring and Round Robin is planned — see the product roadmap.
{% endhint %}

#### Data and logic

Available on all plans.

| Node                   | What it does                                                                                                                                            |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Condition** ❓        | Branches on caller attributes — first-time vs. repeat, area code, known contact, custom metadata. First rule that matches wins.                         |
| **Tag / Label** 🏷     | Attaches workspace tags and/or key-value metadata to the call. Tags show up in Call History, webhooks, and reports.                                     |
| **SMS** 💬             | Sends a text message, with template variables like `{{caller_number}}` and `{{campaign_name}}` resolved. Non-blocking — the call continues immediately. |
| **Opt-In / Consent** ✅ | Asks the caller to press 1 to accept (or 2 to decline) a consent prompt. Stores the decision on the call for compliance.                                |

#### Flow composition

Available on all plans.

| Node                 | What it does                                                                                    |
| -------------------- | ----------------------------------------------------------------------------------------------- |
| **Go-To Sub-Flow** ↗ | Jumps into a different published flow. Useful for sharing common intake logic across campaigns. |

#### Sub-flows in depth

A **Go-To Sub-Flow** node hands the call off to another published flow. There are two ways it can behave:

| `Return on completion` setting | What happens when the sub-flow finishes                                                                                                                                                     |
| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Off** (default)              | The sub-flow's terminal node ends the call. The Go-To is effectively a hand-off — the parent flow is done.                                                                                  |
| **On**                         | When the sub-flow reaches a terminal node, the engine pops back into the parent and continues from the Go-To node's **Return** output port. This is how you build reusable building blocks. |

{% hint style="info" %}
**Use sub-flows to share logic.** Build an "After-Hours Voicemail" sub-flow once, then have every campaign's main flow Go-To it from the closed branch of Business Hours. Update the sub-flow once and every campaign that uses it picks up the change on next publish.
{% endhint %}

{% hint style="warning" %}
**Recursion is capped.** A flow can include up to 5 nested Go-To hops in one call. Beyond that, the engine ends the call to prevent infinite loops. If you hit the limit, the chain is too deep — flatten or refactor.
{% endhint %}

**Analytics for sub-flows:** Each flow's analytics counts only the nodes the call traversed in that flow. A parent flow with a Go-To shows the parent's path up to (and including) the Go-To node; the sub-flow's analytics shows the slice the call took inside the sub-flow. The Go-To's row in the parent's Node Metrics has a `→ Sub-flow name` link that takes you straight to the sub-flow's analytics for the same window.

{% hint style="success" %}
**Test the round-trip in the simulator.** When you step through a Go-To node with **Return on completion** turned on, the canvas swaps to the sub-flow with an amber "Now in sub-flow" pill, then snaps back to the parent when the sub-flow's terminal pops the stack. Verify both halves of the path before placing a real call.
{% endhint %}

#### Agency-only nodes

These nodes depend on Agency-only infrastructure and aren't available on the Indie plan.

| Node               | Why it's Agency-only                                                                                                                                                                                                            |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Agent Queue** 🎧 | Routes the caller to a browser dialer agent currently online. Requires the **Dialer** feature, which is included in the Agency plan. Use this when your team uses the Ring Tonic dialer instead of forwarding to PSTN numbers.  |
| **Webhook** 🔗     | Calls an external URL mid-flow. Two modes: **async** (fire-and-forget) for logging/notifications, **sync** for external routing decisions where your API returns which branch to take. Requires the **API & Webhooks** feature. |

{% hint style="info" %}
**Template variables:** Text fields on Greeting, Menu, Dial whisper, SMS, Webhook, and Voicemail support `{{placeholders}}` that resolve at call time. Common ones: `{{caller_number}}`, `{{caller_name}}`, `{{campaign_name}}`, `{{tracking_number}}`, `{{is_repeat_caller}}`. Use the insert button in each text field to pick one without typing.
{% endhint %}

{% hint style="info" %}
**Want `{{caller_name}}` to be populated?** Caller names come from the carrier's CNAM database, which is an opt-in lookup ($0.01 per call). Turn it on per tracking number under [Phone Numbers → Toggle CNAM Lookup](/guides/phone-numbers.md#toggling-cnam-lookup). Without it, `{{caller_name}}` resolves empty. Caller location fields (`{{caller_city}}`, `{{caller_state}}`) are free but only populate when the carrier provides them — cell-phone callers often arrive without geo data.
{% endhint %}

#### Editing the webhook payload

The Webhook node and the SMS node use a smart JSON editor for the request body and message text:

* **Live syntax check.** A red marker in the gutter highlights any line where the JSON isn't valid — for example, a missing comma or an unclosed brace — so you can fix it before saving instead of finding out after a test call.
* **Template variables in amber.** Placeholders like `{{caller_number}}` and `{{campaign_name}}` are coloured in italic amber so you can see at a glance which values resolve at call time.
* **Format button.** Click **Format** to pretty-print your JSON with consistent indentation. Template variables are preserved exactly as you wrote them.

<figure><img src="/files/JwxBBOiI5qQOx7I4aXFe" alt="" width="563"><figcaption><p>Webhook payload editor with template variables highlighted and the Format button visible</p></figcaption></figure>

#### Verifying the request came from Ring Tonic (HMAC signing)

When your Webhook node hits an endpoint you control, you may want the receiver to confirm the request actually came from Ring Tonic — not a spoofed call. Toggle **Sign with HMAC** on the Webhook node, paste a secret of your choice, and Ring Tonic adds two headers to every outgoing request:

| Header                  | What it contains                                                                                               |
| ----------------------- | -------------------------------------------------------------------------------------------------------------- |
| `X-Ringtonic-Signature` | `sha256=<hex>` — an HMAC of the request body, signed with your secret                                          |
| `X-Ringtonic-Timestamp` | Unix timestamp at the moment the request was sent (used as part of the signed value to prevent replay attacks) |

To verify on the receiving side, recompute `HMAC-SHA256(secret, "{timestamp}.{body}")` and compare it to the value in `X-Ringtonic-Signature`. Reject the request if they don't match or the timestamp is older than your tolerance window (5 minutes is a reasonable default).

{% hint style="info" %}
**Per-node secrets.** Each Webhook node has its own secret, so you can use different secrets for different endpoints (CRM vs. Slack vs. internal API). Share the same value with the receiver and keep it out of public source control.
{% endhint %}

{% hint style="warning" %}
**Signing is opt-in.** The toggle defaults to off so existing flows behave the same way they always did. Turn it on only when your receiver knows how to verify — otherwise the verification will silently fail and the receiver may reject legitimate requests.
{% endhint %}

***

### Attaching a Flow to a Campaign

A flow doesn't do anything until a campaign is pointed at it. Attachment lives on the campaign's detail page — not the edit form — so you can swap flows without re-saving the whole campaign.

{% stepper %}
{% step %}
**Open the campaign**

Go to **Campaigns** and click the campaign you want to upgrade.
{% endstep %}

{% step %}
**Pick "Attach a call flow" on the routing picker**

If the campaign has no routing yet, you'll see the **routing picker** with three mode cards: **Forward to a number**, **Attach a call flow**, and **Build a new flow**. Click the middle card.

If the campaign is already on simple routing, click **Switch routing mode** on the routing summary card and confirm — the picker opens automatically. See [Configure Routing](https://help.ringtonic.app/guides/pages/VdOTbPSa6hi12UUj6ZLp#id-3.-configure-routing) in the Campaigns guide for the full workflow.

<figure><img src="/files/cDvIy14gqD3W5AHhAXj0" alt=""><figcaption><p>Routing picker on the campaign page — three mode cards</p></figcaption></figure>
{% endstep %}

{% step %}
**Pick a flow from the picker**

A picker dialog opens listing every call flow in your workspace. Published flows are selectable; unpublished flows are shown greyed-out with a tooltip explaining they must be published first.

<figure><img src="/files/KU4HOIB9Uo6tfiEtuKC4" alt=""><figcaption><p>Attach Call Flow dialog showing workspace's published flows</p></figcaption></figure>
{% endstep %}

{% step %}
**Confirm**

Select the flow you want, then click **Attach**. The campaign page switches to the **Call Flow card** showing the flow name, version number, and publication date. Real calls to this campaign's tracking numbers immediately start going through the flow.

<figure><img src="/files/i7GISFpeTXh0TdCKcUor" alt=""><figcaption><p>Call Flow card in its attached state with Edit, Change, and Switch routing mode actions</p></figcaption></figure>
{% endstep %}

{% step %}
**Call the tracking number to test**

Call any tracking number attached to the campaign. Your flow answers the call — you should hear your greeting, menu prompts, or whatever the first non-logic node generates.
{% endstep %}
{% endstepper %}

#### Build a new flow from the campaign page

If you don't have a flow built yet, you don't need to leave the campaign page. Pick **Build a new flow** on the routing picker — the Create Flow dialog opens directly.

{% stepper %}
{% step %}
**Pick a template (optional)**

Choose **Blank Flow** or one of the built-in templates (Simple forward, IVR menu, Business hours, etc.). Custom templates from your workspace appear under **My Templates**.
{% endstep %}

{% step %}
**Name your flow and click "Create Flow"**

Ring Tonic creates the flow and redirects you straight to the editor canvas — pre-marked to auto-attach to this campaign on publish.
{% endstep %}

{% step %}
**See the auto-attach banner**

A blue banner at the top of the editor confirms: **"Publishing this flow will attach it to {campaign name}"** — so you know exactly which campaign the flow will land on.

<figure><img src="/files/ZyhagrbOsDyDz5WHZq6d" alt=""><figcaption><p>Editor with the auto-attach banner pinned to the top of the canvas</p></figcaption></figure>
{% endstep %}

{% step %}
**Build, publish, done**

Configure your nodes and click **Publish**. As soon as the version goes live, Ring Tonic links it to the campaign and sends you back to the campaign page. No need to navigate back and re-attach.
{% endstep %}
{% endstepper %}

{% hint style="info" %}
**Cancelling out:** If you close the Create Flow dialog or back out of the editor without publishing, the campaign stays on the routing picker — nothing is changed.
{% endhint %}

#### Changing or removing the flow

Once a flow is attached, the Call Flow card shows these actions:

| Action                  | What it does                                                                                                                                                                                          |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Edit Flow**           | Jumps to the flow canvas so you can update the graph and re-publish                                                                                                                                   |
| **Change**              | Re-opens the picker so you can swap in a different flow without detaching first                                                                                                                       |
| **Switch routing mode** | Detaches the flow and opens the **Forward to a number** dialog so you can configure simple routing in one step. The detached flow itself isn't deleted — it can still be attached to other campaigns. |

After detaching (without picking a new mode), the campaign returns to the **routing picker** so you can pick a different mode or attach a different flow.

{% hint style="success" %}
**Zero-disruption switchover:** Attaching a flow takes effect on the next inbound call — no need to redeploy tracking numbers. Switching back to simple routing is equally instant.
{% endhint %}

{% hint style="info" %}
**Many-to-one:** A single flow can serve multiple campaigns. Agencies often build one well-tested "Main Intake" flow and point every campaign at it, then override with custom flows only where needed.
{% endhint %}

{% hint style="warning" %}
**Only published flows can be attached from the picker.** If you just created a flow and haven't clicked Publish yet, it appears disabled in the picker. Either open the flow canvas and publish it, or use the **Build a new flow** path above which auto-attaches on first publish.
{% endhint %}

***

### Publishing and Versioning

Every published flow is an immutable snapshot. Editing the flow always creates a draft — real calls keep using the previously published version until you re-publish.

#### The publish lifecycle

```
   DRAFT (your edits)  ──── Publish ────▶  VERSION N (frozen)
                                                │
                                                │  Set as active
                                                ▼
                                          LIVE (answers real calls)
```

#### Publishing

1. Click **Publish** in the top-right of the canvas
2. Add an optional publish note (e.g., "Added VIP lane for repeat callers")
3. Ring Tonic runs strict validation:
   * Every node reachable from Start
   * No orphan outputs
   * Every Dial has a valid phone number
   * Every Menu has a no-input path
   * Every sync Webhook has a timeout/error port
4. If validation passes, the new version becomes active and real calls immediately start using it

<figure><img src="/files/B8CUFQbQdr15zz1emlR5" alt=""><figcaption><p>Publish validation showing strict rule checks</p></figcaption></figure>

{% hint style="warning" %}
**ElevenLabs flows publish asynchronously.** If your flow uses ElevenLabs voices, publishing starts a background job that generates MP3s via the ElevenLabs API and uploads them to storage. This takes 10–30 seconds. You'll see a green "Published Successfully" toast when it's done. If something fails (bad API key, quota exceeded), the previous version stays live — your traffic is never disrupted.
{% endhint %}

{% hint style="info" %}
**Auto-attach on first publish:** If you opened this editor from a campaign's "Build a new flow" card, you'll see a blue banner at the top of the canvas. The first time you publish, Ring Tonic links the new version to that campaign automatically and returns you to the campaign page — no manual attach step needed.
{% endhint %}

#### Version history and rollback

Click **Version History** on the canvas toolbar to see every version ever published.

| Field          | What it shows                                       |
| -------------- | --------------------------------------------------- |
| Version number | v1, v2, v3…                                         |
| Status         | Active, publishing, failed, rolled back, superseded |
| Published by   | The user who published it                           |
| Published at   | Absolute date + relative time ("2 days ago")        |
| Publish note   | The note you wrote when publishing                  |

Hover any row to reveal the **Rollback** button. Rolling back copies that version's graph back into your draft so you can review, tweak, and re-publish. The currently active version has no Rollback button (you can't roll back to yourself).

<figure><img src="/files/ZzVapwbtWdVPoc2PH0UV" alt=""><figcaption><p>Version history sheet showing timeline of published versions</p></figcaption></figure>

{% hint style="info" %}
**Version retention by plan:** Indie keeps the last 5 versions; Agency keeps the last 50. Older versions are compacted but the active version is always preserved.
{% endhint %}

***

### Testing Before You Publish

#### Simulation mode

Click **Simulate** on the canvas toolbar to open the simulation panel at the bottom of the page and walk through your flow step-by-step without placing a real call. The simulator:

* **Highlights the active node on the canvas** — the current step gets a pulsing amber ring; nodes the simulation has already visited get a dimmed amber ring, so the path you've taken is visible at a glance.
* **Shows the actual TwiML** that would be returned to Twilio at each interactive step (Greeting, Dial, Menu, Opt-In, Voicemail, Spam Filter, etc.) — handy for verifying voice IDs, dial timeouts, and template-variable substitution.
* **Branches at decision points** — click the lane you want to take at Menu, Condition, Opt-In / Consent, Business Hours, and sync Webhook nodes. Single-output nodes show one **Next → {NextNodeType}** button (e.g., "Next → Greeting", "Next → Opt In") so you always know what's coming.
* **Auto-advances logic-only nodes** — Tag, Condition, Go-To Sub-Flow, and the Start node have no caller-facing output, so the simulator skips them silently and shows the next interactive node.
* **Tracks accumulated call state** — applied tags, metadata key/value pairs, and consent decisions are surfaced under "Accumulated state" at the next interactive step, then again in the final summary.
* **Ends with "Flow Complete"** showing the full path taken (every node visited, including the silent ones), the complete tag list, and the final metadata payload.

<figure><img src="/files/ETwHbbWH7VR9usAjwliK" alt=""><figcaption><p>Simulation panel walking through a test call, showing the current step's TwiML and accumulated state</p></figcaption></figure>

{% hint style="success" %}
**Best Practice:** Always simulate before publishing. The simulator catches logic mistakes (unreachable nodes, wrong keypress targets, missing branch edges) in seconds — faster than placing a real test call.
{% endhint %}

{% hint style="info" %}
**Reading the path:** the final "Path taken" line lists every node the engine visited, including the auto-advanced ones (e.g., `start → condition → tag → dial → hangup` is 5 nodes even though you only clicked through 2 interactive screens). If a step count looks higher than the screens you saw, that's why.
{% endhint %}

#### Real test call

After simulation passes, publish the flow and call your tracking number. You'll hear the caller-side experience directly. The simulator covers **logic**; a real call is the only way to validate **audio quality, whisper timing, and recording**.

***

### Flow Analytics

Once your flow is published and receiving calls, open **Flow Analytics** from the toolbar to see how callers move through it.

<figure><img src="/files/kkwKj9EeGECEE6Jz2MQt" alt="" width="563"><figcaption><p>Flow Analytics panel with calls, paths, node metrics, and drop-off funnel</p></figcaption></figure>

#### What you'll see

| Section             | What it tells you                                                                      |
| ------------------- | -------------------------------------------------------------------------------------- |
| **Calls**           | Total calls that entered the flow in the selected range                                |
| **Avg Duration**    | Average total call duration                                                            |
| **Completion %**    | Percentage of calls that reached a terminal node (Hangup, Voicemail, or answered Dial) |
| **Top Paths**       | The most-common routes callers took through the flow                                   |
| **Node Metrics**    | Per-node: calls entered, average time spent there, drop-off rate                       |
| **Drop-off Funnel** | Stage-by-stage funnel showing where callers leave — or reach a terminal                |

{% hint style="info" %}
**Reading drop-off correctly:** A node's drop-off percentage means "% of calls that entered this node and did NOT continue to any outgoing port." Terminal nodes (Hangup, Voicemail) are successful completions, not drops. The funnel shows a `+N completed here` chip at stages where terminal splits exist.
{% endhint %}

#### Using analytics to improve flows

* **High drop-off at a Menu:** Your prompt is unclear or the options don't match caller intent. Rewrite the prompt.
* **Long average time at a Greeting:** The message may be too long. Trim it, or split into a shorter intro.
* **Low Dial answer rate:** Your whisper is too long or your team isn't online. Simplify the whisper or review agent availability.
* **Spam Filter catching 30% of calls:** That's robocaller traffic being filtered out correctly. Usually a good sign.

***

### Recipes — Real-World Flow Patterns

These are the patterns we see most often in production. Each one starts from a built-in template, then layers on the nodes you need.

<details>

<summary>Recipe 1 — Robocall-resistant business inbound</summary>

**Goal:** filter out auto-dialers, route to your team during business hours, take a voicemail otherwise.

Start from the **Spam Filter + Forward** template, then insert a Business Hours node between the Spam Filter and the Dial.

```
Start → Spam Filter → Business Hours
                        ├── open  → Dial → (answered: Hangup, else: Voicemail)
                        └── closed/holiday → Voicemail (after-hours greeting)
```

{% hint style="success" %}
**Why this works:** the Spam Filter eliminates \~80% of robocaller volume before the Business Hours node ever evaluates. Your team only ever rings on real, human-verified calls.
{% endhint %}

</details>

<details>

<summary>Recipe 2 — VIP lane for repeat callers</summary>

**Goal:** known repeat callers skip the menu and ring a senior rep directly; new callers get the standard IVR.

Start from the **VIP Tag Routing** template. The Condition node already branches on `is_repeat_caller`. Tweak the dial numbers and the IVR menu options for your team.

```
Start → Condition
          ├── is_repeat_caller=true → Tag (VIP, Returning) → Dial (senior rep)
          └── default                 → Menu → Sales / Support / Voicemail
```

{% hint style="info" %}
**Want to branch on more than just repeat-vs-new?** Open the Condition node's **Rules** panel and add another rule (e.g., `caller_number starts_with +1206` for a Seattle local lane). The first rule that matches wins; everything else falls through to the default port.
{% endhint %}

</details>

<details>

<summary>Recipe 3 — CRM-driven smart routing</summary>

**Goal:** look up the caller in your CRM during the call, then route based on their tier (VIP / Standard / Lost lead).

Start from the **Webhook Smart Routing** template. Replace the placeholder URL `https://example.com/api/lookup` with your CRM endpoint. Tune the response rules to match your API contract — e.g., if your API returns `{"tier": "vip", "owner": "..."}`, leave the rule as `json.tier equals vip → vip`.

```
Start → Greeting ("Please hold while we look up your account")
        → Webhook (POST {{caller_number}})
            ├── vip      → VIP greeting → VIP rep dial
            ├── standard → Standard greeting → Round Robin team dial
            └── timeout  → Voicemail (graceful fallback)
```

{% hint style="warning" %}
**Always wire `timeout_error`.** A sync Webhook holds the call until your endpoint replies. If your API is slow or down, the `timeout_error` port is what saves the call from dead air. The template wires this for you — don't delete it.
{% endhint %}

{% hint style="info" %}
**Verify the request came from Ring Tonic.** Toggle **Sign with HMAC** on the Webhook node and verify `X-Ringtonic-Signature` on your endpoint. See [Verifying the request came from Ring Tonic](#verifying-the-request-came-from-ring-tonic-hmac-signing) above.
{% endhint %}

</details>

<details>

<summary>Recipe 4 — Reusable after-hours sub-flow</summary>

**Goal:** one after-hours flow shared by every campaign, instead of duplicating the same Voicemail + SMS confirmation in 20 different campaign flows.

1. Build the sub-flow first: a small flow with `Start → Voicemail → SMS → Hangup` that takes a message and texts the caller a confirmation. Publish it as **"After-Hours Sub-Flow"**.
2. In each campaign's main flow, on the Business Hours **closed** branch, drop a **Go-To Sub-Flow** node and point it at the after-hours flow. Leave **Return on completion** off — the sub-flow ends the call.

```
Main flow:   Start → Business Hours
                       ├── open   → Dial → Voicemail
                       └── closed → Go-To "After-Hours Sub-Flow"

Sub-flow:    Start → Voicemail → SMS ("Got your message, we'll call you back") → Hangup
```

Update the sub-flow once and every campaign picks up the change on the next publish — no need to edit 20 separate flows.

{% hint style="success" %}
**This is the biggest agency win.** Build a "Standard Intake", "After-Hours", and "Spam Filter" sub-flow once, then compose them into every campaign's main flow with Go-To. Every campaign stays consistent without copy-paste drift.
{% endhint %}

</details>

<details>

<summary>Recipe 5 — Team rotation with sequential fallback</summary>

**Goal:** ring three reps at once for the first 25 seconds; if no one picks up, fall through to the next-most-recent agent (round-robin) for another retry; only then voicemail.

Start from the **Sales Team** (Round Robin) template. Insert a **Simultaneous Ring** node before it.

```
Start → Greeting → Simultaneous Ring (3 phones, 25s)
            ├── answered → Hangup
            └── no_answer → Round Robin (least-recent, max 2 retries)
                                ├── answered → Hangup
                                └── no_answer/error → Voicemail
```

{% hint style="info" %}
**Sim Ring vs. Round Robin:** Sim Ring rings everyone at once for the first attempt — fastest pickup, best for in-office teams that are usually free. Round Robin rings one at a time with retries — better for distributed teams where calls should be balanced fairly across agents over time. Combining them gives you the best of both.
{% endhint %}

</details>

***

### Power Tips

{% hint style="success" %}
**Wire every Dial's failure ports.** A bare `dial` with only the **answered** edge connected leaves callers in dead air on busy / no-answer / error. The built-in templates wire all four ports for you — copy that pattern in custom flows.
{% endhint %}

{% hint style="success" %}
**Always end with a Hangup.** Even when the previous node is a Voicemail, an explicit Hangup makes the flow's intent clear in the canvas and triggers the optional farewell message. Drop-off analytics treats Hangup as a successful completion, not a drop.
{% endhint %}

{% hint style="success" %}
**Use SMS to recover lost calls.** On the Voicemail or no-answer path, drop an **SMS** node ("Sorry we missed your call — we'll call you back within an hour. Reply STOP to opt out."). SMS is non-blocking — the call continues immediately — and dramatically improves callback conversion.
{% endhint %}

{% hint style="success" %}
**Save your polished flow as a template.** Once a flow is working well, save it as a custom template (see [Saving a flow as a custom template](#saving-a-flow-as-a-custom-template)). The next time you build a similar flow you'll start from your battle-tested baseline instead of from scratch.
{% endhint %}

{% hint style="warning" %}
**Don't forget the Menu's `no_input` and `invalid_input` edges.** A caller who doesn't press anything (silence) or hits a non-configured digit needs a path. Without those edges, the call drops. Wire both to a Voicemail or back to the menu for a retry.
{% endhint %}

{% hint style="warning" %}
**Replace the placeholder phone numbers before publishing.** Templates ship with `+1XXXXXXXXXX` placeholders so you remember to fill them in. Publish validation will surface any unfilled fields, but it's faster to scan the canvas yourself first.
{% endhint %}

***

### Upgrading from Simple Routing to a Call Flow

Simple routing (Forward to a number with optional voicemail, recording, whisper, and spam filter) is a fully supported routing mode — it isn't deprecated, and you don't have to upgrade. Move to a call flow when you outgrow what simple routing can express: IVR menus, business-hours branching, multiple destinations, tags, conditions, or SMS follow-ups.

{% stepper %}
{% step %}
**Open the campaign and switch routing mode**

On the campaign page, click **Switch routing mode** on the simple routing card, confirm, then pick **Build a new flow** from the routing picker.
{% endstep %}

{% step %}
**Pick a starting template**

The **Simple Forwarding** template is the closest match to your existing setup — it gives you a Start → Dial → Voicemail flow you can tweak. Or start blank if you want to build from scratch.
{% endstep %}

{% step %}
**Carry over your settings**

Fill in the Dial node with your forward number, whisper, and recording. Add a Voicemail node if your simple routing had voicemail. Add a Spam Filter node before the Dial if you had spam filter on. Click **Publish** — Ring Tonic auto-attaches the flow to your campaign, so you don't have to navigate back.
{% endstep %}
{% endstepper %}

{% hint style="info" %}
**Your simple routing settings stay saved.** They go inactive while the flow handles calls, and reactivate automatically if you ever detach the flow.
{% endhint %}

{% hint style="success" %}
**You're never forced to upgrade.** Campaigns on simple routing keep working forever. The flow only activates on a campaign when you explicitly attach (or build + auto-attach) one. If you have many campaigns to convert at once, contact Ring Tonic support and we'll help you do it in one go.
{% endhint %}

***

### Troubleshooting

<details>

<summary>Caller hears dead air or disconnects mid-flow</summary>

**Possible causes:**

* A Dial node's forwarding number is wrong or unreachable — verify the E.164 number and that the destination actually answers
* A Webhook node is pointed at an unreachable URL — check the URL with curl and add a `timeout_error` edge as a fallback
* The flow has a Go-To pointing at an unpublished sub-flow — publish the sub-flow first

**Fix:** Use Simulation mode to walk through each branch. Any node that can't produce output will be obvious. Also check the call's **Timeline** tab in Call History for the exact node where the call stopped.

</details>

<details>

<summary>Menu keypresses aren't routing correctly</summary>

**Possible causes:**

* The output ports on the Menu aren't connected to the right downstream nodes — open the Menu, confirm each keypress has an edge to the intended target
* The caller is pressing a digit you didn't configure — add a `no_input` and `invalid_input` edge to handle those cases (usually pointing to voicemail or a retry)

**Fix:** Simulation mode lets you test every keypress path in seconds.

</details>

<details>

<summary>Published flow shows "failed" status</summary>

**Problem:** The publish job couldn't finish — usually an ElevenLabs API error when generating voice audio.

**Fix:** Click the failed version in Version History to see the exact error message (e.g., "ElevenLabs API returned 401 — check your API key"). Verify your ElevenLabs API key in [Workspace Settings](https://help.ringtonic.app/guides/setup-workspace#voice-and-audio-elevenlabs-voices-optional), then retry the publish from the version history row.

</details>

<details>

<summary>My flow-set tags aren't showing in Call History</summary>

**Check:** Open the call's detail sheet → Timeline tab. You should see the Tag node's tags listed alongside AI-applied tags. If they're missing, re-publish the flow and place a new test call — tags are captured at call time, not retroactively.

</details>

<details>

<summary>SMS node reports "delivered" but recipient didn't get the text</summary>

**Most common cause:** A2P 10DLC registration. US carriers silently block SMS from unregistered 10DLC numbers, even though Twilio reports the send as accepted. Ring Tonic surfaces the true delivery status in the call's **Timeline** tab — look for "SMS Failed" with error code 30034.

**Fix:** Register your Twilio number for A2P 10DLC via the Twilio Console. Alternatively, use a toll-free number, which has a simpler verification path. See the [Twilio A2P guide](https://www.twilio.com/docs/messaging/compliance/a2p-10dlc) for details.

</details>

<details>

<summary>Can't find a node I need</summary>

**Check your plan:** every node is available on every plan **except Agent Queue and Webhook**, which require **Agency** because they depend on Agency-only infrastructure (the browser dialer for Agent Queue, API + webhook access for Webhook). The node picker shows these two gated nodes with a lock icon — clicking one opens an upgrade prompt.

If a node you expected (Business Hours, Sim Ring, Round Robin, Tag, Condition, SMS, Opt-In, Go-To Sub-Flow) is missing from the picker, scroll the picker — it groups nodes by category. They're available on all plans.

</details>

<details>

<summary>Rollback button is missing on my active version</summary>

**Expected behavior:** You can't roll back to the version that's already active. If you want to revert recent edits, either roll back to the previous version, or clear your draft and re-publish the active version to reset the draft state.

</details>

***

### Best Practices

{% hint style="success" %}
**Start small, iterate.** Publish a simple version 1 (Greeting → Dial → Voicemail), then add complexity (menus, business hours, tags) in subsequent versions. Version history lets you roll back instantly if a change breaks something.
{% endhint %}

{% hint style="success" %}
**Always add a Spam Filter for US inbound.** A one-step "Press 1 to connect" before your real flow kicks in eliminates 80%+ of robocaller volume. Use the Spam Filter preset for a pre-configured Menu.
{% endhint %}

{% hint style="success" %}
**Whisper is your agent's best friend.** Even a one-line whisper like "Incoming call from {{caller\_number}} via the Google Ads campaign" dramatically improves pickup speed and call quality. Combine with screening (press 1 to accept) to prevent carrier voicemail from stealing calls.
{% endhint %}

{% hint style="success" %}
**Use Tag nodes on important branches.** Any caller who takes an interesting path (pressed 1 for sales, passed the spam filter, entered the VIP lane) should be tagged so they're filterable and reportable later. Tag nodes are free in the flow and light-weight at runtime.
{% endhint %}

{% hint style="success" %}
**Route by caller attributes with the Condition node.** First-time callers and repeat callers deserve different experiences. Use Condition to detect `is_repeat_caller` or caller area code, and branch into VIP / local / generic lanes with different whispers and routing targets.
{% endhint %}

***

### Related Guides

{% content-ref url="/pages/VdOTbPSa6hi12UUj6ZLp" %}
[Campaigns](/guides/campaigns.md)
{% endcontent-ref %}

{% content-ref url="/pages/RsUXxl71vSxWd0PsQfwr" %}
[Browser Dialer](/guides/browser-dialer.md)
{% endcontent-ref %}

{% content-ref url="/pages/crg7tMxXMDacQLAiSpgl" %}
[Setup Workspace](/guides/setup-workspace.md)
{% endcontent-ref %}

{% content-ref url="/pages/FqrMOC4HeyPH7W0Eqtdm" %}
[Analytics](/guides/analytics.md)
{% endcontent-ref %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://help.ringtonic.app/guides/call-flow-builder.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
