import Roark from '@roarkanalytics/sdk';
const client = new Roark({
bearerToken: process.env['ROARK_API_BEARER_TOKEN'], // This is the default and can be omitted
});
const customerFlow = await client.customerFlow.create({
graph: [{ type: 'AGENT_TURN' }],
title: 'Reschedule an appointment',
type: 'SCRIPTED',
});
console.log(customerFlow.data);import os
from roark_analytics import Roark
client = Roark(
bearer_token=os.environ.get("ROARK_API_BEARER_TOKEN"), # This is the default and can be omitted
)
customer_flow = client.customer_flow.create(
graph=[{
"type": "AGENT_TURN"
}],
title="Reschedule an appointment",
type="SCRIPTED",
)
print(customer_flow.data)curl --request POST \
--url https://api.roark.ai/v1/customer-flow \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"type": "SCRIPTED",
"title": "Reschedule an appointment",
"agentIds": [
"7c9e6679-7425-40de-944b-e07fc1f90ae7"
],
"graph": [
{
"type": "CUSTOMER_FIRST_MESSAGE",
"content": "Hi, I need to move my appointment.",
"steps": [
{
"type": "AGENT_TURN",
"content": "Offers alternative times",
"steps": [
{
"type": "CUSTOMER_TURN",
"content": "Takes the first slot"
},
{
"type": "CUSTOMER_TURN",
"content": "Asks for later in the week"
}
]
}
]
}
]
}
'<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.roark.ai/v1/customer-flow",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'type' => 'SCRIPTED',
'title' => 'Reschedule an appointment',
'agentIds' => [
'7c9e6679-7425-40de-944b-e07fc1f90ae7'
],
'graph' => [
[
'type' => 'CUSTOMER_FIRST_MESSAGE',
'content' => 'Hi, I need to move my appointment.',
'steps' => [
[
'type' => 'AGENT_TURN',
'content' => 'Offers alternative times',
'steps' => [
[
'type' => 'CUSTOMER_TURN',
'content' => 'Takes the first slot'
],
[
'type' => 'CUSTOMER_TURN',
'content' => 'Asks for later in the week'
]
]
]
]
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.roark.ai/v1/customer-flow"
payload := strings.NewReader("{\n \"type\": \"SCRIPTED\",\n \"title\": \"Reschedule an appointment\",\n \"agentIds\": [\n \"7c9e6679-7425-40de-944b-e07fc1f90ae7\"\n ],\n \"graph\": [\n {\n \"type\": \"CUSTOMER_FIRST_MESSAGE\",\n \"content\": \"Hi, I need to move my appointment.\",\n \"steps\": [\n {\n \"type\": \"AGENT_TURN\",\n \"content\": \"Offers alternative times\",\n \"steps\": [\n {\n \"type\": \"CUSTOMER_TURN\",\n \"content\": \"Takes the first slot\"\n },\n {\n \"type\": \"CUSTOMER_TURN\",\n \"content\": \"Asks for later in the week\"\n }\n ]\n }\n ]\n }\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.roark.ai/v1/customer-flow")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"type\": \"SCRIPTED\",\n \"title\": \"Reschedule an appointment\",\n \"agentIds\": [\n \"7c9e6679-7425-40de-944b-e07fc1f90ae7\"\n ],\n \"graph\": [\n {\n \"type\": \"CUSTOMER_FIRST_MESSAGE\",\n \"content\": \"Hi, I need to move my appointment.\",\n \"steps\": [\n {\n \"type\": \"AGENT_TURN\",\n \"content\": \"Offers alternative times\",\n \"steps\": [\n {\n \"type\": \"CUSTOMER_TURN\",\n \"content\": \"Takes the first slot\"\n },\n {\n \"type\": \"CUSTOMER_TURN\",\n \"content\": \"Asks for later in the week\"\n }\n ]\n }\n ]\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.roark.ai/v1/customer-flow")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"type\": \"SCRIPTED\",\n \"title\": \"Reschedule an appointment\",\n \"agentIds\": [\n \"7c9e6679-7425-40de-944b-e07fc1f90ae7\"\n ],\n \"graph\": [\n {\n \"type\": \"CUSTOMER_FIRST_MESSAGE\",\n \"content\": \"Hi, I need to move my appointment.\",\n \"steps\": [\n {\n \"type\": \"AGENT_TURN\",\n \"content\": \"Offers alternative times\",\n \"steps\": [\n {\n \"type\": \"CUSTOMER_TURN\",\n \"content\": \"Takes the first slot\"\n },\n {\n \"type\": \"CUSTOMER_TURN\",\n \"content\": \"Asks for later in the week\"\n }\n ]\n }\n ]\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"data": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"title": "<string>",
"source": "CUSTOM",
"createdAt": "<string>",
"updatedAt": "<string>",
"agents": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"description": "<string>",
"customId": "<string>",
"createdAt": "<string>",
"updatedAt": "<string>"
}
],
"agentExpectations": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"prompt": "<string>"
}
],
"type": "SCRIPTED",
"branchingMode": "DETERMINISTIC",
"happyPath": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"title": "<string>",
"precededByCustomerFlowId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"precededByCustomerFlowVariantId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"isGenerated": false,
"createdAt": "<string>",
"updatedAt": "<string>",
"personaOverride": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"language": "EN",
"understoodLanguages": [
"EN"
],
"accent": "US",
"age": "ADULT",
"gender": "MALE",
"backgroundNoise": "NONE",
"speechPace": "NORMAL",
"speechClarity": "CLEAR",
"hasDisfluencies": false,
"baseEmotion": "NEUTRAL",
"intentClarity": "CLEAR",
"confirmationStyle": "EXPLICIT",
"memoryReliability": "HIGH",
"responseTiming": "NORMAL",
"idleMessages": [
"<string>"
],
"idleTimeoutSeconds": 10,
"idleMessageMaxSpokenCount": 3,
"idleMessageResetCountOnUserSpeechEnabled": true,
"properties": {
"age": 35,
"zipCode": "94105",
"occupation": "Software Engineer"
},
"createdAt": "<string>",
"updatedAt": "<string>",
"description": "<string>",
"secondaryLanguage": "EN",
"backstoryPrompt": "A busy professional calling during lunch break"
},
"environment": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"backgroundNoise": "NONE",
"createdAt": "<string>",
"updatedAt": "<string>",
"description": "<string>"
},
"additionalExpectations": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"prompt": "<string>"
}
],
"type": "SCRIPTED",
"steps": [
{
"type": "AGENT_TURN",
"nodeId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"ref": "<string>",
"steps": "<array>",
"mergeIntoNodeIds": [
"<string>"
],
"content": "<string>"
}
]
},
"edgeCases": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"title": "<string>",
"precededByCustomerFlowId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"precededByCustomerFlowVariantId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"isGenerated": false,
"createdAt": "<string>",
"updatedAt": "<string>",
"personaOverride": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"language": "EN",
"understoodLanguages": [
"EN"
],
"accent": "US",
"age": "ADULT",
"gender": "MALE",
"backgroundNoise": "NONE",
"speechPace": "NORMAL",
"speechClarity": "CLEAR",
"hasDisfluencies": false,
"baseEmotion": "NEUTRAL",
"intentClarity": "CLEAR",
"confirmationStyle": "EXPLICIT",
"memoryReliability": "HIGH",
"responseTiming": "NORMAL",
"idleMessages": [
"<string>"
],
"idleTimeoutSeconds": 10,
"idleMessageMaxSpokenCount": 3,
"idleMessageResetCountOnUserSpeechEnabled": true,
"properties": {
"age": 35,
"zipCode": "94105",
"occupation": "Software Engineer"
},
"createdAt": "<string>",
"updatedAt": "<string>",
"description": "<string>",
"secondaryLanguage": "EN",
"backstoryPrompt": "A busy professional calling during lunch break"
},
"environment": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"backgroundNoise": "NONE",
"createdAt": "<string>",
"updatedAt": "<string>",
"description": "<string>"
},
"additionalExpectations": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"prompt": "<string>"
}
],
"type": "SCRIPTED",
"steps": [
{
"type": "AGENT_TURN",
"nodeId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"ref": "<string>",
"steps": "<array>",
"mergeIntoNodeIds": [
"<string>"
],
"content": "<string>"
}
]
}
],
"description": "<string>",
"graph": [
{
"type": "AGENT_TURN",
"nodeId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"ref": "<string>",
"steps": "<array>",
"mergeIntoNodeIds": [
"<string>"
],
"content": "<string>"
}
]
}
}{
"type": "validation",
"code": "invalid_parameter",
"message": "The request was invalid",
"param": "email"
}{
"type": "authentication",
"code": "unauthorized",
"message": "Authentication required"
}{
"type": "forbidden",
"code": "permission_denied",
"message": "You do not have permission to access this resource"
}{
"type": "rate_limit",
"code": "too_many_requests",
"message": "Rate limit exceeded"
}{
"type": "internal",
"code": "internal_error",
"message": "Internal server error"
}Create a customer flow
Creates a customer flow. A SCRIPTED flow carries a step graph and gets one way of running it per path through the graph; an IMPROV flow carries the briefs you send. Customer flows replace the older simulation scenarios, so build a flow for anything new.
import Roark from '@roarkanalytics/sdk';
const client = new Roark({
bearerToken: process.env['ROARK_API_BEARER_TOKEN'], // This is the default and can be omitted
});
const customerFlow = await client.customerFlow.create({
graph: [{ type: 'AGENT_TURN' }],
title: 'Reschedule an appointment',
type: 'SCRIPTED',
});
console.log(customerFlow.data);import os
from roark_analytics import Roark
client = Roark(
bearer_token=os.environ.get("ROARK_API_BEARER_TOKEN"), # This is the default and can be omitted
)
customer_flow = client.customer_flow.create(
graph=[{
"type": "AGENT_TURN"
}],
title="Reschedule an appointment",
type="SCRIPTED",
)
print(customer_flow.data)curl --request POST \
--url https://api.roark.ai/v1/customer-flow \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"type": "SCRIPTED",
"title": "Reschedule an appointment",
"agentIds": [
"7c9e6679-7425-40de-944b-e07fc1f90ae7"
],
"graph": [
{
"type": "CUSTOMER_FIRST_MESSAGE",
"content": "Hi, I need to move my appointment.",
"steps": [
{
"type": "AGENT_TURN",
"content": "Offers alternative times",
"steps": [
{
"type": "CUSTOMER_TURN",
"content": "Takes the first slot"
},
{
"type": "CUSTOMER_TURN",
"content": "Asks for later in the week"
}
]
}
]
}
]
}
'<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.roark.ai/v1/customer-flow",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'type' => 'SCRIPTED',
'title' => 'Reschedule an appointment',
'agentIds' => [
'7c9e6679-7425-40de-944b-e07fc1f90ae7'
],
'graph' => [
[
'type' => 'CUSTOMER_FIRST_MESSAGE',
'content' => 'Hi, I need to move my appointment.',
'steps' => [
[
'type' => 'AGENT_TURN',
'content' => 'Offers alternative times',
'steps' => [
[
'type' => 'CUSTOMER_TURN',
'content' => 'Takes the first slot'
],
[
'type' => 'CUSTOMER_TURN',
'content' => 'Asks for later in the week'
]
]
]
]
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.roark.ai/v1/customer-flow"
payload := strings.NewReader("{\n \"type\": \"SCRIPTED\",\n \"title\": \"Reschedule an appointment\",\n \"agentIds\": [\n \"7c9e6679-7425-40de-944b-e07fc1f90ae7\"\n ],\n \"graph\": [\n {\n \"type\": \"CUSTOMER_FIRST_MESSAGE\",\n \"content\": \"Hi, I need to move my appointment.\",\n \"steps\": [\n {\n \"type\": \"AGENT_TURN\",\n \"content\": \"Offers alternative times\",\n \"steps\": [\n {\n \"type\": \"CUSTOMER_TURN\",\n \"content\": \"Takes the first slot\"\n },\n {\n \"type\": \"CUSTOMER_TURN\",\n \"content\": \"Asks for later in the week\"\n }\n ]\n }\n ]\n }\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.roark.ai/v1/customer-flow")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"type\": \"SCRIPTED\",\n \"title\": \"Reschedule an appointment\",\n \"agentIds\": [\n \"7c9e6679-7425-40de-944b-e07fc1f90ae7\"\n ],\n \"graph\": [\n {\n \"type\": \"CUSTOMER_FIRST_MESSAGE\",\n \"content\": \"Hi, I need to move my appointment.\",\n \"steps\": [\n {\n \"type\": \"AGENT_TURN\",\n \"content\": \"Offers alternative times\",\n \"steps\": [\n {\n \"type\": \"CUSTOMER_TURN\",\n \"content\": \"Takes the first slot\"\n },\n {\n \"type\": \"CUSTOMER_TURN\",\n \"content\": \"Asks for later in the week\"\n }\n ]\n }\n ]\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.roark.ai/v1/customer-flow")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"type\": \"SCRIPTED\",\n \"title\": \"Reschedule an appointment\",\n \"agentIds\": [\n \"7c9e6679-7425-40de-944b-e07fc1f90ae7\"\n ],\n \"graph\": [\n {\n \"type\": \"CUSTOMER_FIRST_MESSAGE\",\n \"content\": \"Hi, I need to move my appointment.\",\n \"steps\": [\n {\n \"type\": \"AGENT_TURN\",\n \"content\": \"Offers alternative times\",\n \"steps\": [\n {\n \"type\": \"CUSTOMER_TURN\",\n \"content\": \"Takes the first slot\"\n },\n {\n \"type\": \"CUSTOMER_TURN\",\n \"content\": \"Asks for later in the week\"\n }\n ]\n }\n ]\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"data": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"title": "<string>",
"source": "CUSTOM",
"createdAt": "<string>",
"updatedAt": "<string>",
"agents": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"description": "<string>",
"customId": "<string>",
"createdAt": "<string>",
"updatedAt": "<string>"
}
],
"agentExpectations": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"prompt": "<string>"
}
],
"type": "SCRIPTED",
"branchingMode": "DETERMINISTIC",
"happyPath": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"title": "<string>",
"precededByCustomerFlowId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"precededByCustomerFlowVariantId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"isGenerated": false,
"createdAt": "<string>",
"updatedAt": "<string>",
"personaOverride": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"language": "EN",
"understoodLanguages": [
"EN"
],
"accent": "US",
"age": "ADULT",
"gender": "MALE",
"backgroundNoise": "NONE",
"speechPace": "NORMAL",
"speechClarity": "CLEAR",
"hasDisfluencies": false,
"baseEmotion": "NEUTRAL",
"intentClarity": "CLEAR",
"confirmationStyle": "EXPLICIT",
"memoryReliability": "HIGH",
"responseTiming": "NORMAL",
"idleMessages": [
"<string>"
],
"idleTimeoutSeconds": 10,
"idleMessageMaxSpokenCount": 3,
"idleMessageResetCountOnUserSpeechEnabled": true,
"properties": {
"age": 35,
"zipCode": "94105",
"occupation": "Software Engineer"
},
"createdAt": "<string>",
"updatedAt": "<string>",
"description": "<string>",
"secondaryLanguage": "EN",
"backstoryPrompt": "A busy professional calling during lunch break"
},
"environment": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"backgroundNoise": "NONE",
"createdAt": "<string>",
"updatedAt": "<string>",
"description": "<string>"
},
"additionalExpectations": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"prompt": "<string>"
}
],
"type": "SCRIPTED",
"steps": [
{
"type": "AGENT_TURN",
"nodeId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"ref": "<string>",
"steps": "<array>",
"mergeIntoNodeIds": [
"<string>"
],
"content": "<string>"
}
]
},
"edgeCases": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"title": "<string>",
"precededByCustomerFlowId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"precededByCustomerFlowVariantId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"isGenerated": false,
"createdAt": "<string>",
"updatedAt": "<string>",
"personaOverride": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"language": "EN",
"understoodLanguages": [
"EN"
],
"accent": "US",
"age": "ADULT",
"gender": "MALE",
"backgroundNoise": "NONE",
"speechPace": "NORMAL",
"speechClarity": "CLEAR",
"hasDisfluencies": false,
"baseEmotion": "NEUTRAL",
"intentClarity": "CLEAR",
"confirmationStyle": "EXPLICIT",
"memoryReliability": "HIGH",
"responseTiming": "NORMAL",
"idleMessages": [
"<string>"
],
"idleTimeoutSeconds": 10,
"idleMessageMaxSpokenCount": 3,
"idleMessageResetCountOnUserSpeechEnabled": true,
"properties": {
"age": 35,
"zipCode": "94105",
"occupation": "Software Engineer"
},
"createdAt": "<string>",
"updatedAt": "<string>",
"description": "<string>",
"secondaryLanguage": "EN",
"backstoryPrompt": "A busy professional calling during lunch break"
},
"environment": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"backgroundNoise": "NONE",
"createdAt": "<string>",
"updatedAt": "<string>",
"description": "<string>"
},
"additionalExpectations": [
{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"prompt": "<string>"
}
],
"type": "SCRIPTED",
"steps": [
{
"type": "AGENT_TURN",
"nodeId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"ref": "<string>",
"steps": "<array>",
"mergeIntoNodeIds": [
"<string>"
],
"content": "<string>"
}
]
}
],
"description": "<string>",
"graph": [
{
"type": "AGENT_TURN",
"nodeId": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"ref": "<string>",
"steps": "<array>",
"mergeIntoNodeIds": [
"<string>"
],
"content": "<string>"
}
]
}
}{
"type": "validation",
"code": "invalid_parameter",
"message": "The request was invalid",
"param": "email"
}{
"type": "authentication",
"code": "unauthorized",
"message": "Authentication required"
}{
"type": "forbidden",
"code": "permission_denied",
"message": "You do not have permission to access this resource"
}{
"type": "rate_limit",
"code": "too_many_requests",
"message": "Rate limit exceeded"
}{
"type": "internal",
"code": "internal_error",
"message": "Internal server error"
}Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Body
- Scripted
- Improv
Input for creating a customer flow. SCRIPTED writes the conversation out as a graph of turns; IMPROV gives the simulated customer a brief and lets it improvise.
"SCRIPTED"1"Reschedule an appointment"
The conversation, as a graph of steps. At most 100 steps across at most 25 paths. The variants come from the graph: one per path, so they are not sent here.
1One step in a scripted flow's conversation.
nodeId is the identity contract: include it to update the existing step, omit it to create a new one.
A step continues into steps (more than one child is a branch point) and/or mergeIntoNodeIds, which
names steps elsewhere in the same request that this step rejoins. Branches that come back together are
represented that way rather than by repeating the shared step, so reading a flow, editing it and writing
it back preserves it exactly.
A merge target is named by its nodeId when it already exists, or by ref when it is being created in
the same request. ref is a label you choose, it is request-local, and it is never stored or returned.
Put the shared step inline under the first branch that reaches it and point the others at it: a top-level
step is a root wired straight from the start of the flow, so a merge target parked there would also be
reachable directly.
The two DTMF types are mirror images and both require dtmfDigits. CUSTOMER_DTMF is keys the
simulated caller presses while navigating your agent. AGENT_DTMF is keys your agent under test is
expected to press while navigating a menu the simulation is playing, so its digits are an assertion the
run is graded against rather than an instruction, and it counts as an agent turn for role alternation.
- Option 1
- Option 2
- Option 3
- Option 4
- Option 5
- Option 6
- Option 7
- Option 8
Show child attributes
Show child attributes
Show child attributes
Show child attributes
Agents this flow exercises. Optional for scripted flows.
How a run walks the graph. DETERMINISTIC ("Simulate every path" in the app) places one call per variant, each following its path exactly whatever the agent says. ADAPTIVE ("Adapt to your agent") collapses the paths into one call PER PERSONA, on which the simulated customer picks a branch from what the agent actually said. Both modes speak the exact authored lines, and neither changes how metrics or expectations grade. (DETERMINISTIC is the default.)
DETERMINISTIC, ADAPTIVE Response
The created customer flow
The conversation a simulated customer has with the agent under test.
- Scripted
- Improv
- Voicemail
Show child attributes
Show child attributes