Runs a whole test conversation between a voice agent's latest version and a simulated user that follows your persona prompt. Each transcript item is streamed as a server-sent event. Nothing is stored. Beyond Retell
With an LLM key the simulated user is an LLM. In mock mode the persona prompt is turned into a scripted list of first-person lines. The member role may call this route.
Request#
Path parameters#
| Parameter | Type | Required | Description |
|---|---|---|---|
agent_id |
string | Yes | The voice agent to test. |
Body#
| Field | Type | Required | Description |
|---|---|---|---|
user_prompt |
string | Yes | Persona and goal of the simulated user. 1 to 8000 characters. |
dynamic_variables |
object | No | String, number or boolean values (converted to strings). Default {}. |
tool_mocks |
object[] | No | Up to 50 { "tool_name", "output" } returned instead of running the tool. |
llm_model |
string | No | Model for the simulated user. Default gpt-5.6-terra. |
max_utterances |
integer | No | 2 to 400. Default 40. |
start_component_id |
string | No | Conversation flow only: run inside one component, Begin node to Exit node. |
Example request#
curl -N -X POST "https://api.tried.com.au/agent-playground-simulation/agent_3f9a1c0b2d4e5f6a7b8c9d0e" \
-H "Authorization: Bearer $TRIED_API_KEY" \
-H "Content-Type: application/json" \
-d '{"user_prompt":"You are Sam. You want to move your Thursday booking to Friday morning.","max_utterances":20}'const res = await fetch("https://api.tried.com.au/agent-playground-simulation/agent_3f9a1c0b2d4e5f6a7b8c9d0e", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.TRIED_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ user_prompt: "You are Sam. You want to move your Thursday booking to Friday morning.", max_utterances: 20 }),
});
console.log(await res.text());import json, os, requests
res = requests.post(
"https://api.tried.com.au/agent-playground-simulation/agent_3f9a1c0b2d4e5f6a7b8c9d0e",
headers={"Authorization": f"Bearer {os.environ['TRIED_API_KEY']}"},
json={"user_prompt": "You are Sam. You want to move your Thursday booking to Friday morning.", "max_utterances": 20},
stream=True,
)
for line in res.iter_lines(decode_unicode=True):
if line.startswith("data: "):
print(json.loads(line[6:]))Response#
200 OK with Content-Type: text/event-stream.
data: {"type":"item","item":{"role":"agent","content":"Hi, thanks for calling Bright Dental."}}
data: {"type":"item","item":{"role":"user","content":"Hi, I need to move my Thursday booking."}}
data: {"type":"done","ended_by":"agent_ended","utterances":8}type |
Fields |
|---|---|
item |
item: a transcript item with role agent, user, tool_call_invocation (tool_call_id, name, arguments), tool_call_result (tool_call_id, content) or node_transition (former_node_id, new_node_id). |
done |
ended_by (user_ended, agent_ended, script_finished, utterance_limit, time_limit, aborted) and utterances (agent and user turns). |
error |
message. |
Errors#
| Status | When |
|---|---|
400 |
Validation failed, or start_component_id is used with an agent that is not a conversation flow, or the component has no nodes. |
401 |
Missing or invalid API key. |
403 |
The key's IP allowlist or scopes reject the request. This route needs the agents scope. |
404 |
The agent or component does not exist. |
429 |
Rate limit exceeded. See Rate limits. |
See Errors for the body format.