Workflow Definition Schema
Schema reference for the workflowdefinition object used in the Agents API
The workflow_definition object passed to Create from Definition and Update Agent defines the full conversation graph. It is the same structure the dashboard's visual workflow builder reads and writes — building an agent in the UI produces a workflow_definition under the hood, and anything you can configure visually can equally be expressed here as JSON.
json
{
"nodes": [...],
"edges": [...]
}---
Nodes#
Each node represents a step in the conversation.
json
{
"id": "uuid-string",
"type": "agentNode",
"position": { "x": 100, "y": 200 },
"data": { ... }
}| Field | Type | Description |
|---|---|---|
id | string | Unique node ID (UUID recommended) |
type | string | One of the node types below |
position | object | Visual coordinates in the workflow builder |
data | object | Node configuration — fields vary by type |
Node types#
| Type | Description |
|---|---|
startCall | Entry point for telephony calls |
endCall | Terminates the call |
agentNode | LLM-powered conversation step |
globalNode | Global configuration applied throughout all agent nodes |
trigger | Entry point for API-triggered (non-telephony) runs |
webhook | Sends an HTTP request when reached |
qa | Runs quality analysis on the completed call |
---
Node data fields#
Common fields (all node types)#
| Field | Type | Default | Description |
|---|---|---|---|
name | string | required | Display name for the node |
prompt | string | required* | LLM system prompt. *Not required for trigger, webhook, qa nodes |
allow_interrupt | boolean | false | Allow the caller to interrupt the agent mid-speech |
wait_for_user_response | boolean | false | Pause and wait for caller input before continuing |
wait_for_user_response_timeout | number | null | Seconds to wait for input before timing out |
detect_voicemail | boolean | false | Detect and handle voicemail on outbound calls |
delayed_start | boolean | false | Delay execution of this node |
delayed_start_duration | number | null | Delay in seconds |
add_global_prompt | boolean | true | Merge the globalNode prompt into this node's prompt |
agentNode — data extraction#
| Field | Type | Default | Description |
|---|---|---|---|
extraction_enabled | boolean | false | Extract structured data from the conversation |
extraction_prompt | string | null | Custom prompt to guide extraction |
extraction_variables | array | [] | Variables to extract (see below) |
Extraction variable schema:
json
{
"name": "customer_intent",
"type": "string",
"prompt": "What did the customer want to achieve?"
}type is one of string, number, or boolean.
agentNode — tools#
| Field | Type | Description |
|---|---|---|
tool_uuids | string[] | IDs of tools (HTTP API, call transfer, etc.) to attach to this node |
document_uuids | string[] | IDs of knowledge base documents available to this node |
trigger node#
| Field | Type | Description |
|---|---|---|
trigger_path | string | Unique UUID that becomes the API trigger endpoint path |
webhook node#
| Field | Type | Default | Description |
|---|---|---|---|
enabled | boolean | true | Whether this webhook fires when reached |
http_method | string | — | GET, POST, PUT, PATCH, or DELETE |
endpoint_url | string | — | Target URL |
credential_uuid | string | null | UUID of a stored auth credential |
custom_headers | array | [] | Additional request headers [{"key": "...", "value": "..."}] |
payload_template | object | null | Request body template (supports context variables) |
qa node#
| Field | Type | Default | Description |
|---|---|---|---|
qa_enabled | boolean | true | Enable QA analysis |
qa_system_prompt | string | null | Custom evaluation prompt |
qa_model | string | null | LLM model to use for evaluation |
qa_min_call_duration | integer | 15 | Minimum call duration in seconds to run QA |
qa_voicemail_calls | boolean | false | Include voicemail calls in QA |
qa_sample_rate | integer | 100 | Percentage of calls to analyse (1–100) |
---
Edges#
Each edge connects two nodes and defines when the transition fires.
json
{
"id": "edge-uuid",
"source": "node-uuid-a",
"target": "node-uuid-b",
"data": {
"label": "Customer confirms",
"condition": "The customer has confirmed their appointment",
"transition_speech": "Great, I've got that noted."
}
}| Field | Type | Description |
|---|---|---|
id | string | Unique edge ID |
source | string | ID of the originating node |
target | string | ID of the destination node |
data.label | string | Short label shown in the workflow builder |
data.condition | string | Natural language condition the LLM evaluates to trigger this edge |
data.transition_speech | string | Optional speech the agent says before transitioning |
---
Validation rules#
- All
sourceandtargetIDs in edges must reference existing node IDs - All nodes except
trigger,webhook, andqamust have a non-emptyprompt - Node IDs must be unique within the workflow
- Each workflow must have exactly one
startCallortriggernode as the entry point
---
Minimal example#
json
{
"nodes": [
{
"id": "start-1",
"type": "startCall",
"position": { "x": 0, "y": 0 },
"data": {
"name": "Start",
"prompt": "You are a friendly assistant. Greet the caller and ask how you can help."
}
},
{
"id": "end-1",
"type": "endCall",
"position": { "x": 400, "y": 0 },
"data": {
"name": "End",
"prompt": "Thank the caller and say goodbye."
}
}
],
"edges": [
{
"id": "edge-1",
"source": "start-1",
"target": "end-1",
"data": {
"label": "Done",
"condition": "The caller's question has been answered and they want to end the call"
}
}
]
}