curl --request POST \
--url https://api.goyappr.com/agent-eval/cases/{case_id}/run \
--header 'Content-Type: application/json' \
--data '
{
"agent_overrides": {}
}
'import requests
url = "https://api.goyappr.com/agent-eval/cases/{case_id}/run"
payload = { "agent_overrides": {} }
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({agent_overrides: {}})
};
fetch('https://api.goyappr.com/agent-eval/cases/{case_id}/run', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.goyappr.com/agent-eval/cases/{case_id}/run",
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([
'agent_overrides' => [
]
]),
CURLOPT_HTTPHEADER => [
"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.goyappr.com/agent-eval/cases/{case_id}/run"
payload := strings.NewReader("{\n \"agent_overrides\": {}\n}")
req, _ := http.NewRequest("POST", url, payload)
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.goyappr.com/agent-eval/cases/{case_id}/run")
.header("Content-Type", "application/json")
.body("{\n \"agent_overrides\": {}\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.goyappr.com/agent-eval/cases/{case_id}/run")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"agent_overrides\": {}\n}"
response = http.request(request)
puts response.read_body{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"company_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"status": "queued",
"mode": "text",
"created_at": "2023-11-07T05:31:56Z",
"case_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"case": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"company_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"agent_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"persona_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "Yes path — caller agrees on first ask",
"scenario": "The persona is responding to a missed call from your business about their recent inquiry. They have time to talk for 5 minutes.",
"success_criteria": [
{
"type": "must_say",
"kind": "must_say",
"weight": 1,
"description": "<string>",
"pattern": "<string>",
"phrase": "<string>",
"match_type": "substring",
"case_sensitive": false,
"tool_name": "<string>",
"args_match": {},
"node_id": "<string>",
"rubric": "<string>"
}
],
"max_turns": 20,
"pass_threshold": 80,
"tool_policy": "mock",
"created_at": "2023-11-07T05:31:56Z",
"agent": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"type": "prompt",
"flow_config": {
"nodes": [
{
"id": "<string>",
"type": "start",
"name": "<string>",
"position": {
"x": 123,
"y": 123
},
"agent_speaks_first": true,
"greeting": "<string>",
"is_literal": false,
"next_step_id": "<string>",
"auto_advance": true
}
],
"flow_config_version": "1",
"metadata": {
"custom_metadata_keys": [
"<string>"
]
}
},
"system_prompt": "<string>",
"description": "<string>",
"voice": "Michal",
"background_sound": "call_center",
"background_sound_volume": 0.3,
"language": "he",
"temperature": 1,
"greeting_message": "<string>",
"agent_speaks_first": true,
"vad_stop_secs": 0.5,
"vad_start_secs": 0.2,
"vad_confidence": 0.7,
"silence_timeout_secs": 60,
"max_continuous_speech_secs": 120,
"max_call_duration_secs": 600,
"lead_memory_enabled": true,
"is_active": true,
"webhook_url": "<string>",
"webhook_events": [
"call.started"
],
"webhook_headers": {
"Authorization": "Bearer sk_live_…",
"X-Source": "yappr"
},
"extraction_parameters": [
{
"name": "customerName",
"description": "The caller's full name as mentioned during the conversation"
}
],
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z"
},
"persona": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"company_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "Frustrated tenant",
"identity_prompt": "You are a 38-year-old tenant calling about a leaking pipe in your kitchen. You're frustrated because this is the third time you've reported it.",
"language": "en",
"created_at": "2023-11-07T05:31:56Z",
"description": "<string>",
"behavior_traits": {
"patience": "low",
"verbosity": "chatty",
"cooperation": "cooperative",
"interruption_tendency": "occasional",
"goal": "Get a maintenance technician scheduled today"
},
"voice_config": {},
"updated_at": "2023-11-07T05:31:56Z",
"deleted_at": "2023-11-07T05:31:56Z"
},
"suite_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"description": "<string>",
"agent_overrides": {},
"tool_allowlist": [],
"updated_at": "2023-11-07T05:31:56Z",
"deleted_at": "2023-11-07T05:31:56Z"
},
"suite_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"suite_run_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"queue_status": "pending",
"agent_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"persona_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"started_at": "2023-11-07T05:31:56Z",
"ended_at": "2023-11-07T05:31:56Z",
"duration_ms": 123,
"score": 50,
"pass_fail": true,
"termination_reason": "persona_goodbye",
"evaluation": {
"score": 50,
"pass_fail": true,
"results": [
{
"assertion": {
"type": "must_say",
"kind": "must_say",
"weight": 1,
"description": "<string>",
"pattern": "<string>",
"phrase": "<string>",
"match_type": "substring",
"case_sensitive": false,
"tool_name": "<string>",
"args_match": {},
"node_id": "<string>",
"rubric": "<string>"
},
"passed": true,
"weight": 123,
"reason": "<string>"
}
]
},
"agent_input_tokens": 0,
"agent_output_tokens": 0,
"persona_input_tokens": 0,
"persona_output_tokens": 0,
"agent_cost_cents": 0,
"persona_cost_cents": 0,
"total_cost_cents": 0,
"error": "<string>",
"agent_overrides": {}
}{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"company_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"status": "queued",
"mode": "text",
"created_at": "2023-11-07T05:31:56Z",
"case_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"case": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"company_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"agent_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"persona_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "Yes path — caller agrees on first ask",
"scenario": "The persona is responding to a missed call from your business about their recent inquiry. They have time to talk for 5 minutes.",
"success_criteria": [
{
"type": "must_say",
"kind": "must_say",
"weight": 1,
"description": "<string>",
"pattern": "<string>",
"phrase": "<string>",
"match_type": "substring",
"case_sensitive": false,
"tool_name": "<string>",
"args_match": {},
"node_id": "<string>",
"rubric": "<string>"
}
],
"max_turns": 20,
"pass_threshold": 80,
"tool_policy": "mock",
"created_at": "2023-11-07T05:31:56Z",
"agent": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"type": "prompt",
"flow_config": {
"nodes": [
{
"id": "<string>",
"type": "start",
"name": "<string>",
"position": {
"x": 123,
"y": 123
},
"agent_speaks_first": true,
"greeting": "<string>",
"is_literal": false,
"next_step_id": "<string>",
"auto_advance": true
}
],
"flow_config_version": "1",
"metadata": {
"custom_metadata_keys": [
"<string>"
]
}
},
"system_prompt": "<string>",
"description": "<string>",
"voice": "Michal",
"background_sound": "call_center",
"background_sound_volume": 0.3,
"language": "he",
"temperature": 1,
"greeting_message": "<string>",
"agent_speaks_first": true,
"vad_stop_secs": 0.5,
"vad_start_secs": 0.2,
"vad_confidence": 0.7,
"silence_timeout_secs": 60,
"max_continuous_speech_secs": 120,
"max_call_duration_secs": 600,
"lead_memory_enabled": true,
"is_active": true,
"webhook_url": "<string>",
"webhook_events": [
"call.started"
],
"webhook_headers": {
"Authorization": "Bearer sk_live_…",
"X-Source": "yappr"
},
"extraction_parameters": [
{
"name": "customerName",
"description": "The caller's full name as mentioned during the conversation"
}
],
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z"
},
"persona": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"company_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "Frustrated tenant",
"identity_prompt": "You are a 38-year-old tenant calling about a leaking pipe in your kitchen. You're frustrated because this is the third time you've reported it.",
"language": "en",
"created_at": "2023-11-07T05:31:56Z",
"description": "<string>",
"behavior_traits": {
"patience": "low",
"verbosity": "chatty",
"cooperation": "cooperative",
"interruption_tendency": "occasional",
"goal": "Get a maintenance technician scheduled today"
},
"voice_config": {},
"updated_at": "2023-11-07T05:31:56Z",
"deleted_at": "2023-11-07T05:31:56Z"
},
"suite_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"description": "<string>",
"agent_overrides": {},
"tool_allowlist": [],
"updated_at": "2023-11-07T05:31:56Z",
"deleted_at": "2023-11-07T05:31:56Z"
},
"suite_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"suite_run_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"queue_status": "pending",
"agent_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"persona_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"started_at": "2023-11-07T05:31:56Z",
"ended_at": "2023-11-07T05:31:56Z",
"duration_ms": 123,
"score": 50,
"pass_fail": true,
"termination_reason": "persona_goodbye",
"evaluation": {
"score": 50,
"pass_fail": true,
"results": [
{
"assertion": {
"type": "must_say",
"kind": "must_say",
"weight": 1,
"description": "<string>",
"pattern": "<string>",
"phrase": "<string>",
"match_type": "substring",
"case_sensitive": false,
"tool_name": "<string>",
"args_match": {},
"node_id": "<string>",
"rubric": "<string>"
},
"passed": true,
"weight": 123,
"reason": "<string>"
}
]
},
"agent_input_tokens": 0,
"agent_output_tokens": 0,
"persona_input_tokens": 0,
"persona_output_tokens": 0,
"agent_cost_cents": 0,
"persona_cost_cents": 0,
"total_cost_cents": 0,
"error": "<string>",
"agent_overrides": {}
}{
"error": "<string>",
"code": "<string>"
}Run a Case
Trigger one execution of the case. Blocks up to 60 seconds waiting for the run to fully finish (worker assertions + billing complete) so simple callers don’t have to poll for short runs.
Required scope agent_eval:run.
Response codes:
200— run finished within the 60s window. Body is the fullEvalRunwithcase(and nestedagent+persona) expanded;score,pass_fail,evaluation, and the cost columns are final.202— still running after 60s. Body is the latest non-terminalEvalRun. Keep pollingGET /agent-eval/runs/{id}until bothstatusis terminal ANDqueue_status === "done".
There is no synchronous balance check on this endpoint. Insufficient credit
surfaces asynchronously: the worker sets the run’s status to failed with the
reason in the run’s error field — discovered by polling, not via a 402.
curl --request POST \
--url https://api.goyappr.com/agent-eval/cases/{case_id}/run \
--header 'Content-Type: application/json' \
--data '
{
"agent_overrides": {}
}
'import requests
url = "https://api.goyappr.com/agent-eval/cases/{case_id}/run"
payload = { "agent_overrides": {} }
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({agent_overrides: {}})
};
fetch('https://api.goyappr.com/agent-eval/cases/{case_id}/run', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.goyappr.com/agent-eval/cases/{case_id}/run",
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([
'agent_overrides' => [
]
]),
CURLOPT_HTTPHEADER => [
"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.goyappr.com/agent-eval/cases/{case_id}/run"
payload := strings.NewReader("{\n \"agent_overrides\": {}\n}")
req, _ := http.NewRequest("POST", url, payload)
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.goyappr.com/agent-eval/cases/{case_id}/run")
.header("Content-Type", "application/json")
.body("{\n \"agent_overrides\": {}\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.goyappr.com/agent-eval/cases/{case_id}/run")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"agent_overrides\": {}\n}"
response = http.request(request)
puts response.read_body{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"company_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"status": "queued",
"mode": "text",
"created_at": "2023-11-07T05:31:56Z",
"case_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"case": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"company_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"agent_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"persona_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "Yes path — caller agrees on first ask",
"scenario": "The persona is responding to a missed call from your business about their recent inquiry. They have time to talk for 5 minutes.",
"success_criteria": [
{
"type": "must_say",
"kind": "must_say",
"weight": 1,
"description": "<string>",
"pattern": "<string>",
"phrase": "<string>",
"match_type": "substring",
"case_sensitive": false,
"tool_name": "<string>",
"args_match": {},
"node_id": "<string>",
"rubric": "<string>"
}
],
"max_turns": 20,
"pass_threshold": 80,
"tool_policy": "mock",
"created_at": "2023-11-07T05:31:56Z",
"agent": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"type": "prompt",
"flow_config": {
"nodes": [
{
"id": "<string>",
"type": "start",
"name": "<string>",
"position": {
"x": 123,
"y": 123
},
"agent_speaks_first": true,
"greeting": "<string>",
"is_literal": false,
"next_step_id": "<string>",
"auto_advance": true
}
],
"flow_config_version": "1",
"metadata": {
"custom_metadata_keys": [
"<string>"
]
}
},
"system_prompt": "<string>",
"description": "<string>",
"voice": "Michal",
"background_sound": "call_center",
"background_sound_volume": 0.3,
"language": "he",
"temperature": 1,
"greeting_message": "<string>",
"agent_speaks_first": true,
"vad_stop_secs": 0.5,
"vad_start_secs": 0.2,
"vad_confidence": 0.7,
"silence_timeout_secs": 60,
"max_continuous_speech_secs": 120,
"max_call_duration_secs": 600,
"lead_memory_enabled": true,
"is_active": true,
"webhook_url": "<string>",
"webhook_events": [
"call.started"
],
"webhook_headers": {
"Authorization": "Bearer sk_live_…",
"X-Source": "yappr"
},
"extraction_parameters": [
{
"name": "customerName",
"description": "The caller's full name as mentioned during the conversation"
}
],
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z"
},
"persona": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"company_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "Frustrated tenant",
"identity_prompt": "You are a 38-year-old tenant calling about a leaking pipe in your kitchen. You're frustrated because this is the third time you've reported it.",
"language": "en",
"created_at": "2023-11-07T05:31:56Z",
"description": "<string>",
"behavior_traits": {
"patience": "low",
"verbosity": "chatty",
"cooperation": "cooperative",
"interruption_tendency": "occasional",
"goal": "Get a maintenance technician scheduled today"
},
"voice_config": {},
"updated_at": "2023-11-07T05:31:56Z",
"deleted_at": "2023-11-07T05:31:56Z"
},
"suite_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"description": "<string>",
"agent_overrides": {},
"tool_allowlist": [],
"updated_at": "2023-11-07T05:31:56Z",
"deleted_at": "2023-11-07T05:31:56Z"
},
"suite_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"suite_run_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"queue_status": "pending",
"agent_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"persona_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"started_at": "2023-11-07T05:31:56Z",
"ended_at": "2023-11-07T05:31:56Z",
"duration_ms": 123,
"score": 50,
"pass_fail": true,
"termination_reason": "persona_goodbye",
"evaluation": {
"score": 50,
"pass_fail": true,
"results": [
{
"assertion": {
"type": "must_say",
"kind": "must_say",
"weight": 1,
"description": "<string>",
"pattern": "<string>",
"phrase": "<string>",
"match_type": "substring",
"case_sensitive": false,
"tool_name": "<string>",
"args_match": {},
"node_id": "<string>",
"rubric": "<string>"
},
"passed": true,
"weight": 123,
"reason": "<string>"
}
]
},
"agent_input_tokens": 0,
"agent_output_tokens": 0,
"persona_input_tokens": 0,
"persona_output_tokens": 0,
"agent_cost_cents": 0,
"persona_cost_cents": 0,
"total_cost_cents": 0,
"error": "<string>",
"agent_overrides": {}
}{
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"company_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"status": "queued",
"mode": "text",
"created_at": "2023-11-07T05:31:56Z",
"case_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"case": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"company_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"agent_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"persona_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "Yes path — caller agrees on first ask",
"scenario": "The persona is responding to a missed call from your business about their recent inquiry. They have time to talk for 5 minutes.",
"success_criteria": [
{
"type": "must_say",
"kind": "must_say",
"weight": 1,
"description": "<string>",
"pattern": "<string>",
"phrase": "<string>",
"match_type": "substring",
"case_sensitive": false,
"tool_name": "<string>",
"args_match": {},
"node_id": "<string>",
"rubric": "<string>"
}
],
"max_turns": 20,
"pass_threshold": 80,
"tool_policy": "mock",
"created_at": "2023-11-07T05:31:56Z",
"agent": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "<string>",
"type": "prompt",
"flow_config": {
"nodes": [
{
"id": "<string>",
"type": "start",
"name": "<string>",
"position": {
"x": 123,
"y": 123
},
"agent_speaks_first": true,
"greeting": "<string>",
"is_literal": false,
"next_step_id": "<string>",
"auto_advance": true
}
],
"flow_config_version": "1",
"metadata": {
"custom_metadata_keys": [
"<string>"
]
}
},
"system_prompt": "<string>",
"description": "<string>",
"voice": "Michal",
"background_sound": "call_center",
"background_sound_volume": 0.3,
"language": "he",
"temperature": 1,
"greeting_message": "<string>",
"agent_speaks_first": true,
"vad_stop_secs": 0.5,
"vad_start_secs": 0.2,
"vad_confidence": 0.7,
"silence_timeout_secs": 60,
"max_continuous_speech_secs": 120,
"max_call_duration_secs": 600,
"lead_memory_enabled": true,
"is_active": true,
"webhook_url": "<string>",
"webhook_events": [
"call.started"
],
"webhook_headers": {
"Authorization": "Bearer sk_live_…",
"X-Source": "yappr"
},
"extraction_parameters": [
{
"name": "customerName",
"description": "The caller's full name as mentioned during the conversation"
}
],
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z"
},
"persona": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"company_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"name": "Frustrated tenant",
"identity_prompt": "You are a 38-year-old tenant calling about a leaking pipe in your kitchen. You're frustrated because this is the third time you've reported it.",
"language": "en",
"created_at": "2023-11-07T05:31:56Z",
"description": "<string>",
"behavior_traits": {
"patience": "low",
"verbosity": "chatty",
"cooperation": "cooperative",
"interruption_tendency": "occasional",
"goal": "Get a maintenance technician scheduled today"
},
"voice_config": {},
"updated_at": "2023-11-07T05:31:56Z",
"deleted_at": "2023-11-07T05:31:56Z"
},
"suite_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"description": "<string>",
"agent_overrides": {},
"tool_allowlist": [],
"updated_at": "2023-11-07T05:31:56Z",
"deleted_at": "2023-11-07T05:31:56Z"
},
"suite_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"suite_run_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"queue_status": "pending",
"agent_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"persona_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"started_at": "2023-11-07T05:31:56Z",
"ended_at": "2023-11-07T05:31:56Z",
"duration_ms": 123,
"score": 50,
"pass_fail": true,
"termination_reason": "persona_goodbye",
"evaluation": {
"score": 50,
"pass_fail": true,
"results": [
{
"assertion": {
"type": "must_say",
"kind": "must_say",
"weight": 1,
"description": "<string>",
"pattern": "<string>",
"phrase": "<string>",
"match_type": "substring",
"case_sensitive": false,
"tool_name": "<string>",
"args_match": {},
"node_id": "<string>",
"rubric": "<string>"
},
"passed": true,
"weight": 123,
"reason": "<string>"
}
]
},
"agent_input_tokens": 0,
"agent_output_tokens": 0,
"persona_input_tokens": 0,
"persona_output_tokens": 0,
"agent_cost_cents": 0,
"persona_cost_cents": 0,
"total_cost_cents": 0,
"error": "<string>",
"agent_overrides": {}
}{
"error": "<string>",
"code": "<string>"
}Response semantics
200— run finished within the 60-second window. Body is the flatEvalRunrow —case_id,agent_id,persona_id(NOT expandedcase/agent/personaobjects) — withscore,pass_fail,evaluation, and the cost columns final. To get the expandedcase(and nestedagent+persona), callGET /agent-eval/runs/{id}.202— still running after 60s. Body is the latest non-terminalEvalRunrow (also flat). Keep pollingGET /agent-eval/runs/{id}until bothstatusis terminal ANDqueue_status === "done".
Per-run overrides
agent_overrides in the request body is the cleanest way to test “what if I changed the system_prompt to this” without committing the change to the case. The override is layered over the case’s own agent_overrides and recorded on the run row, so you can always trace back which config produced which result.
No webhooks
Eval runs do not emit webhooks. Polling is the only mechanism — for batches use the suite-run aggregate (GET /agent-eval/suites/{id}/runs/{suite_run_id}).Path Parameters
Body
Optional per-run overrides applied on top of the case's own overrides.
Response
Run finished within 60s; fully scored.
One execution of a case. Append-only after creation except for status/billing/lifecycle fields.
User-facing run status. Flips to completed/failed as soon as the conversation ends — BEFORE the worker scores assertions and bills. Do not treat score / pass_fail / total_cost_cents as final until queue_status === "done".
queued, running, completed, failed, cancelled Always text in v1. voice is reserved for the future loopback mode.
text, voice FK; nullable because cases can be deleted while runs are kept as history.
A specific eval scenario — persona + target agent + scenario + success criteria.
Show child attributes
Show child attributes
Groups runs spawned by a single POST /agent-eval/suites/{id}/run call.
Pass to GET /agent-eval/suites/{id}/runs/{suite_run_id} for the aggregate.
Internal worker pipeline state. pending = waiting in queue, claimed = the cron worker has dispatched it to the voice runtime, done = the worker has finished scoring + billing. Always poll for queue_status === "done" before reading the scoring / billing fields. The transient window between status === "completed" and queue_status === "done" is typically < 5 seconds but can be longer under contention.
pending, claimed, done Denormalized snapshot — same as case.agent_id at the moment the run was created.
0 <= x <= 100Why the run stopped.
persona_goodbye, agent_ended, max_turns, timeout, error, cancelled Populated when status is completed or failed.
Show child attributes
Show child attributes
Total amount debited from the company's credit balance for this run.
Populated when status='failed'. Stable machine-readable codes: insufficient_credits, agent_inactive (the agent under test is deactivated — reactivate it and re-run), eval_unreachable, eval_dispatch_failed, eval_timeout, eval_failed. Anything else is a free-text detail; treat an unrecognized value as eval_failed.
Snapshot of the case's agent_overrides plus any per-run overrides supplied at create time.