Creates a conversation flow: a graph of nodes joined by edges, where each node does one job (talk, call a function, transfer, branch, end). Attach it to an agent with response_engine: { "type": "conversation-flow", "conversation_flow_id" } on Create agent.
Every field is optional. When you send nodes without start_node_id, the first node becomes the start node. The new flow is version 0, a draft; it is published with the agent that uses it.
Request#
Model and prompt#
| Field | Type | Required | Description |
|---|---|---|---|
global_prompt |
string | No | Prompt that applies on every node. Supports {{dynamic_variables}}. Default "". |
model_choice |
object | No | type (cascading or s2s, default cascading), model (required, one of the LLM models), high_priority (default false), ultrafast, s2s_model (gpt-realtime or gpt-realtime-mini, for type: "s2s"). Default { "type": "cascading", "model": "gpt-5.6-terra", "high_priority": false }. |
model_temperature |
number | No | 0 to 1. Default 0. |
tool_call_strict_mode |
boolean | No | Strict JSON schema for tool calls. |
flex_mode |
boolean | No | Compile the whole flow into one prompt; the model moves between steps itself. |
start_speaker |
string | No | agent or user. Default agent. |
begin_after_user_silence_ms |
integer or null | No | With start_speaker: "user", start talking after this much silence. |
default_dynamic_variables |
object | No | Fallback string values for variables. Default {}. |
The prompt limit is 32,768 tokens (characters divided by 4), counted as global_prompt plus the longest node instruction plus the JSON of tools.
Graph#
| Field | Type | Required | Description |
|---|---|---|---|
nodes |
object[] | No | The nodes. IDs must be unique. See Nodes. Default []. |
start_node_id |
string or null | No | First node. Must be one of nodes. Default: the first node. |
tools |
object[] | No | Tools that function and subagent nodes reference. Each is a tool plus a tool_id string. Default []. |
components |
object[] | No | Component (subflow) definitions used by component nodes: copies of library components or flow-only ones. Each has component_id, name, start_node_id, nodes, tools, begin_tag_display_position. |
mcps |
object[] | No | MCP servers for mcp nodes and tools. Same shape as Retell LLM mcps. |
Knowledge base#
| Field | Type | Required | Description |
|---|---|---|---|
knowledge_base_ids |
string[] | No | Knowledge bases to search. Each must exist. Default []. |
kb_config |
object | No | top_k (1 to 10, default 3) and filter_score (0 to 1, default 0.6). |
kb_instruction |
string | No | Up to 500 characters that steer retrieval. |
Canvas#
| Field | Type | Required | Description |
|---|---|---|---|
begin_tag_display_position |
object | No | { "x", "y" } of the Begin tag. Default { "x": 0, "y": 0 }. |
notes |
object[] | No | Sticky notes, display only: id, text, position ({ "x", "y" }), color, width, height. |
Nodes#
Fields on every node#
| Field | Type | Required | Description |
|---|---|---|---|
id |
string | Yes | Unique within the flow. |
type |
string | Yes | Node type. See Node types. |
name |
string | No | Display name. Default "". |
display_position |
object | No | { "x", "y" } on the canvas. Default { "x": 0, "y": 0 }. |
global_node_setting |
object | No | Makes the node global: it can be entered from anywhere. See global_node_setting. |
Per-node overrides#
Any node can override agent or flow settings while it is active:
| Field | Type | Description |
|---|---|---|
model_choice |
object | { "type": "cascading", "model", "high_priority"?, "ultrafast"? }. |
voice_speed |
number | 0.5 to 2. |
responsiveness |
number | 0 to 1. |
interruption_sensitivity |
number | 0 to 1. |
stt_mode |
string | fast or accurate. |
boosted_keywords |
string[] | Extra STT keywords. |
knowledge_base_ids |
string[] | Knowledge bases for this node. |
kb_instruction |
string | Up to 500 characters. |
allow_dtmf_interruption |
boolean | Keypad presses interrupt the agent. |
reminder_trigger_ms |
integer | At least 1000. |
reminder_max_count |
integer | 0 or more. |
finetune_conversation_examples |
object[] | Example exchanges: { "id", "transcript": [{ "role": "user" or "agent", "content" }] }. |
finetune_transition_examples |
object[] | Example transitions: { "id", "transcript", "destination_node_id" }. |
global_node_setting#
| Field | Type | Description |
|---|---|---|
condition |
string | When to jump to this node from anywhere (required). |
go_back_conditions |
object[] | { "id", "transition_condition" } entries: when to return to the node the conversation came from. |
cool_down |
integer | 0 to 100. After leaving, the node cannot trigger again for this many user turns. |
Instruction#
Nodes that speak take an instruction:
| Field | Type | Description |
|---|---|---|
type |
string | prompt (the model writes the reply from this text) or static_text (say these exact words). |
text |
string | The prompt or the words. |
Node types#
type |
Fields (besides the common ones) | What it does |
|---|---|---|
conversation |
instruction (required), edges, skip_response_edge, always_edge, else_edge, skippable |
Talks with the caller. skip_response_edge moves on without waiting for a reply. always_edge is taken unconditionally. else_edge is taken when no other edge applies (prompt edges are then decided before replying). skippable lets the runtime skip the node when contact memory already answers it. |
function |
tool_id (required), wait_for_result (default true), speak_during_execution (default false), instruction, edges, else_edge |
Runs one tool from tools. |
transfer_call |
transfer_destination (required), transfer_option (default cold sip_invite), instruction, edge |
Transfers the call. Same destination and option shapes as the transfer_call tool. edge is followed when the transfer fails. |
press_digit |
instruction (required), edges, delay_ms (0 to 5000) |
Presses keypad digits to navigate a phone menu. |
branch |
edges, else_edge (required) |
Follows an edge whose condition holds, otherwise else_edge. Says nothing. |
extract_dynamic_variables |
variables (required, analysis fields), edges |
Extracts values into dynamic variables, then follows edges. |
end |
instruction, custom_sip_headers |
Says the instruction, if any, and ends the call. |
subagent |
instruction (required), tool_ids (default []), edges, always_edge, else_edge |
A conversation node with its own tools that the model may call freely while in the node. |
code |
code (required, JavaScript up to 20000 characters), timeout_ms (1000 to 60000), response_variables, speak_during_execution, instruction, edges, else_edge |
Runs code in the API sandbox, stores response variables, then follows equation edges. |
sms |
sms_content (required), instruction, success_edge, failure_edge |
Sends an SMS to the caller. Same sms_content shapes as the send_sms tool. |
agent_swap |
agent_id (required), agent_version, keep_current_voice, instruction, edge |
Hands the call to another agent; history and collected variables carry over. edge is followed when the swap fails. |
mcp |
mcp_id (required), mcp_tool_name (required), arguments, parameters, response_variables, speak_during_execution, instruction, edges, else_edge |
Calls one tool on a server in mcps. arguments are fixed values (with {{variables}} rendered); the model fills the rest from the parameters schema. |
component |
component_id (required), sync, edges, else_edge |
Runs a component subflow. sync: true always uses the latest library version. Otherwise the copy in components is used, or the library entry when the flow has no copy. When the subflow exits, this node's edges continue. |
component_exit |
none | Exit of a component subflow: control returns to the component node's edges. |
bridge_transfer |
instruction |
Transfer agents: connect the waiting caller. |
cancel_transfer |
instruction |
Transfer agents: give up and return the caller to the original agent. |
Edges#
| Field | Type | Required | Description |
|---|---|---|---|
id |
string | Yes | Edge ID. |
destination_node_id |
string or null | No | Target node. Default null (not connected). |
transition_condition |
object | Yes | When to take the edge. See below. |
transition_condition#
type |
Fields | Taken when |
|---|---|---|
prompt |
prompt |
The model judges the condition in prompt is met. |
equation |
equations (at least one), operator (&& or ` |
|
equation_prompt |
equations, operator, prompt |
The equations hold and the model judges the prompt condition met. |
Each equation is { "left", "operator", "right" }. left and right are strings that can use {{variables}}; right defaults to "". operator is one of ==, !=, >, >=, <, <=, contains, not_contains, exists, not_exist.
Example request#
curl -X POST "https://api.tried.com.au/create-conversation-flow" \
-H "Authorization: Bearer $TRIED_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"global_prompt": "You are the receptionist for Bright Dental. Keep replies short.",
"model_choice": {
"type": "cascading",
"model": "gpt-5.6-terra"
},
"start_node_id": "node_greet",
"nodes": [
{
"id": "node_greet",
"type": "conversation",
"name": "Greeting",
"instruction": {
"type": "static_text",
"text": "Hi, thanks for calling Bright Dental. Are you after a booking?"
},
"edges": [
{
"id": "edge_book",
"destination_node_id": "node_book",
"transition_condition": {
"type": "prompt",
"prompt": "Caller wants to book"
}
},
{
"id": "edge_other",
"destination_node_id": "node_end",
"transition_condition": {
"type": "prompt",
"prompt": "Caller wants something else"
}
}
]
},
{
"id": "node_book",
"type": "function",
"name": "Check availability",
"tool_id": "tool_availability",
"speak_during_execution": true,
"instruction": {
"type": "static_text",
"text": "One moment while I check."
},
"edges": [
{
"id": "edge_done",
"destination_node_id": "node_end",
"transition_condition": {
"type": "equation",
"equations": [
{
"left": "{{slot}}",
"operator": "exists"
}
]
}
}
]
},
{
"id": "node_end",
"type": "end",
"instruction": {
"type": "prompt",
"text": "Thank the caller and say goodbye."
}
}
],
"tools": [
{
"tool_id": "tool_availability",
"type": "custom",
"name": "check_availability",
"url": "https://example.com/tools/availability",
"response_variables": {
"slot": "next_slot"
}
}
]
}'const res = await fetch("https://api.tried.com.au/create-conversation-flow", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.TRIED_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"global_prompt": "You are the receptionist for Bright Dental. Keep replies short.",
"model_choice": {
"type": "cascading",
"model": "gpt-5.6-terra"
},
"start_node_id": "node_greet",
"nodes": [
{
"id": "node_greet",
"type": "conversation",
"name": "Greeting",
"instruction": {
"type": "static_text",
"text": "Hi, thanks for calling Bright Dental. Are you after a booking?"
},
"edges": [
{
"id": "edge_book",
"destination_node_id": "node_book",
"transition_condition": {
"type": "prompt",
"prompt": "Caller wants to book"
}
},
{
"id": "edge_other",
"destination_node_id": "node_end",
"transition_condition": {
"type": "prompt",
"prompt": "Caller wants something else"
}
}
]
},
{
"id": "node_book",
"type": "function",
"name": "Check availability",
"tool_id": "tool_availability",
"speak_during_execution": true,
"instruction": {
"type": "static_text",
"text": "One moment while I check."
},
"edges": [
{
"id": "edge_done",
"destination_node_id": "node_end",
"transition_condition": {
"type": "equation",
"equations": [
{
"left": "{{slot}}",
"operator": "exists"
}
]
}
}
]
},
{
"id": "node_end",
"type": "end",
"instruction": {
"type": "prompt",
"text": "Thank the caller and say goodbye."
}
}
],
"tools": [
{
"tool_id": "tool_availability",
"type": "custom",
"name": "check_availability",
"url": "https://example.com/tools/availability",
"response_variables": {
"slot": "next_slot"
}
}
]
}),
});
const data = await res.json();import os, requests
res = requests.post(
"https://api.tried.com.au/create-conversation-flow",
headers={"Authorization": f"Bearer {os.environ['TRIED_API_KEY']}"},
json={
"global_prompt": "You are the receptionist for Bright Dental. Keep replies short.",
"model_choice": {
"type": "cascading",
"model": "gpt-5.6-terra",
},
"start_node_id": "node_greet",
"nodes": [
{
"id": "node_greet",
"type": "conversation",
"name": "Greeting",
"instruction": {
"type": "static_text",
"text": "Hi, thanks for calling Bright Dental. Are you after a booking?",
},
"edges": [
{
"id": "edge_book",
"destination_node_id": "node_book",
"transition_condition": {
"type": "prompt",
"prompt": "Caller wants to book",
},
},
{
"id": "edge_other",
"destination_node_id": "node_end",
"transition_condition": {
"type": "prompt",
"prompt": "Caller wants something else",
},
},
],
},
{
"id": "node_book",
"type": "function",
"name": "Check availability",
"tool_id": "tool_availability",
"speak_during_execution": True,
"instruction": {
"type": "static_text",
"text": "One moment while I check.",
},
"edges": [
{
"id": "edge_done",
"destination_node_id": "node_end",
"transition_condition": {
"type": "equation",
"equations": [
{
"left": "{{slot}}",
"operator": "exists",
},
],
},
},
],
},
{
"id": "node_end",
"type": "end",
"instruction": {
"type": "prompt",
"text": "Thank the caller and say goodbye.",
},
},
],
"tools": [
{
"tool_id": "tool_availability",
"type": "custom",
"name": "check_availability",
"url": "https://example.com/tools/availability",
"response_variables": {
"slot": "next_slot",
},
},
],
},
)
data = res.json()Response#
201 Created with the flow. All fields are returned with defaults filled in, plus:
| Field | Type | Description |
|---|---|---|
conversation_flow_id |
string | conversation_flow_ plus 24 hex characters. |
version |
integer | 0 for a new flow. |
is_published |
boolean | false for a new flow. |
last_modification_timestamp |
integer | Epoch ms. |
{
"conversation_flow_id": "conversation_flow_2c3d4e5f6a7b8c9d0e1f2a3b",
"version": 0,
"is_published": false,
"global_prompt": "You are the receptionist for Bright Dental. Keep replies short.",
"model_choice": { "type": "cascading", "model": "gpt-5.6-terra", "high_priority": false },
"model_temperature": 0,
"start_speaker": "agent",
"start_node_id": "node_greet",
"nodes": [],
"tools": [],
"knowledge_base_ids": [],
"default_dynamic_variables": {},
"begin_tag_display_position": { "x": 0, "y": 0 },
"last_modification_timestamp": 1792310400000
}nodes and tools are shortened to [] in this example; the response contains them in full.
Errors#
| Status | When |
|---|---|
400 |
Validation failed, duplicate node IDs (Duplicate node ids in conversation flow), start_node_id is not a node, the prompt is over the limit, or a knowledge base ID does not exist. |
401 |
Missing or invalid API key. |
403 |
The key's IP allowlist or scopes reject the request. This route needs the agents scope. |
429 |
Rate limit exceeded. See Rate limits. |
See Errors for the body format.