Create an agent test
Create a complete Simulation, Next Reply, or Tool Invocation test as an immutable initial revision, optionally attaching it to the caller's Agent draft atomically.
Endpoint
POST
/api/v1/workspaces/{workspace_id}/agent-testsAuthentication
| Operation class | Authentication | Minimum role | API key |
|---|---|---|---|
| customer-api | Bearer API key or dashboard session cookie; dashboard mutations also require X-CX-Request: 1. | member | Allowed |
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
workspace_id | path | string | Yes | — |
Request body
application/json request schema
| Field path | Type | Reference | Format | Nullable | Required | Enum | Description |
|---|---|---|---|---|---|---|---|
$ | object | — | — | No | Yes | — | — |
Choose exactly one variant using type.
Simulation variant (type = "simulation")
| Field path | Type | Reference | Format | Nullable | Required | Enum | Description |
|---|---|---|---|---|---|---|---|
$ | object | — | — | No | Yes | — | — |
attach_to_agent_id | string or null | — | — | Yes | No | — | — |
chat_history | array<HistoryEntry> | — | — | No | No | — | — |
chat_history[] | object | HistoryEntry | — | No | Yes | — | — |
chat_history[].message | string or null | — | — | Yes | No | — | — |
chat_history[].role | string | — | — | No | Yes | "user", "agent" | — |
chat_history[].tool_calls | array<ToolCall> | — | — | No | No | — | — |
chat_history[].tool_calls[] | object | ToolCall | — | No | Yes | — | Bagian stabil kontrak vendor; detail bertipe baru tetap dipertahankan. |
chat_history[].tool_calls[].params_as_json | string | — | — | No | Yes | — | — |
chat_history[].tool_calls[].request_id | string | — | — | No | Yes | — | — |
chat_history[].tool_calls[].tool_details | object or null | — | — | Yes | No | — | — |
chat_history[].tool_calls[].tool_has_been_called | boolean | — | — | No | Yes | — | — |
chat_history[].tool_calls[].tool_name | string | — | — | No | Yes | — | — |
chat_history[].tool_calls[].type | string or null | — | — | Yes | No | — | — |
chat_history[].tool_results | array<ToolResult> | — | — | No | No | — | — |
chat_history[].tool_results[] | object | ToolResult | — | No | Yes | — | — |
chat_history[].tool_results[].is_blocked | boolean | — | — | No | No | — | — |
chat_history[].tool_results[].is_error | boolean | — | — | No | Yes | — | — |
chat_history[].tool_results[].request_id | string | — | — | No | Yes | — | — |
chat_history[].tool_results[].result_value | string | — | — | No | Yes | — | — |
chat_history[].tool_results[].tool_has_been_called | boolean | — | — | No | Yes | — | — |
chat_history[].tool_results[].tool_latency_secs | number | — | — | No | No | — | — |
chat_history[].tool_results[].tool_name | string | — | — | No | Yes | — | — |
chat_history[].tool_results[].type | string | — | — | No | Yes | — | — |
conversation_initiation_source | string | — | — | No | No | "unknown", "telegram_integration" | — |
dynamic_variables | object | — | — | No | No | — | — |
evaluation_model | string | — | — | No | No | — | — |
from_conversation_metadata | object or null | FromConversationMetadata | — | Yes | No | — | — |
from_conversation_metadata.conversation_id | string | — | — | No | Yes | — | — |
from_conversation_metadata.event_seq | integer | — | — | No | Yes | — | — |
from_conversation_metadata.original_agent_response | string or null | — | — | Yes | No | — | — |
from_conversation_metadata.system__conversation_id | string or null | — | — | Yes | No | — | — |
from_conversation_metadata.system__time_utc | string | — | date-time | No | Yes | — | — |
name | string | — | — | No | Yes | — | — |
parent_folder_id | string or null | — | — | Yes | No | — | — |
simulated_user_model | string | — | — | No | No | — | — |
simulation_max_turns | integer | — | — | No | No | — | — |
simulation_scenario | string | — | — | No | Yes | — | — |
success_conditions | array<string> | — | — | No | Yes | — | — |
success_conditions[] | string | — | — | No | Yes | — | — |
tool_mock_config | object | ToolMockConfig | — | No | No | — | — |
tool_mock_config.fallback_strategy | string | — | — | No | No | "raise_error", "call_real_tool" | — |
tool_mock_config.mocked_tool_ids | array<string> | — | — | No | No | — | — |
tool_mock_config.mocked_tool_ids[] | string | — | — | No | Yes | — | — |
tool_mock_config.mocking_strategy | string | — | — | No | No | "all", "selected", "none" | — |
tool_mock_overrides | object | — | — | No | No | — | — |
type | string | — | — | No | Yes | "simulation" | — |
Next Reply variant (type = "llm")
| Field path | Type | Reference | Format | Nullable | Required | Enum | Description |
|---|---|---|---|---|---|---|---|
$ | object | — | — | No | Yes | — | — |
attach_to_agent_id | string or null | — | — | Yes | No | — | — |
chat_history | array<HistoryEntry> | — | — | No | No | — | — |
chat_history[] | object | HistoryEntry | — | No | Yes | — | — |
chat_history[].message | string or null | — | — | Yes | No | — | — |
chat_history[].role | string | — | — | No | Yes | "user", "agent" | — |
chat_history[].tool_calls | array<ToolCall> | — | — | No | No | — | — |
chat_history[].tool_calls[] | object | ToolCall | — | No | Yes | — | Bagian stabil kontrak vendor; detail bertipe baru tetap dipertahankan. |
chat_history[].tool_calls[].params_as_json | string | — | — | No | Yes | — | — |
chat_history[].tool_calls[].request_id | string | — | — | No | Yes | — | — |
chat_history[].tool_calls[].tool_details | object or null | — | — | Yes | No | — | — |
chat_history[].tool_calls[].tool_has_been_called | boolean | — | — | No | Yes | — | — |
chat_history[].tool_calls[].tool_name | string | — | — | No | Yes | — | — |
chat_history[].tool_calls[].type | string or null | — | — | Yes | No | — | — |
chat_history[].tool_results | array<ToolResult> | — | — | No | No | — | — |
chat_history[].tool_results[] | object | ToolResult | — | No | Yes | — | — |
chat_history[].tool_results[].is_blocked | boolean | — | — | No | No | — | — |
chat_history[].tool_results[].is_error | boolean | — | — | No | Yes | — | — |
chat_history[].tool_results[].request_id | string | — | — | No | Yes | — | — |
chat_history[].tool_results[].result_value | string | — | — | No | Yes | — | — |
chat_history[].tool_results[].tool_has_been_called | boolean | — | — | No | Yes | — | — |
chat_history[].tool_results[].tool_latency_secs | number | — | — | No | No | — | — |
chat_history[].tool_results[].tool_name | string | — | — | No | Yes | — | — |
chat_history[].tool_results[].type | string | — | — | No | Yes | — | — |
conversation_initiation_source | string | — | — | No | No | "unknown", "telegram_integration" | — |
dynamic_variables | object | — | — | No | No | — | — |
evaluation_model | string | — | — | No | No | — | — |
failure_examples | array<string> | — | — | No | No | — | — |
failure_examples[] | string | — | — | No | Yes | — | — |
from_conversation_metadata | object or null | FromConversationMetadata | — | Yes | No | — | — |
from_conversation_metadata.conversation_id | string | — | — | No | Yes | — | — |
from_conversation_metadata.event_seq | integer | — | — | No | Yes | — | — |
from_conversation_metadata.original_agent_response | string or null | — | — | Yes | No | — | — |
from_conversation_metadata.system__conversation_id | string or null | — | — | Yes | No | — | — |
from_conversation_metadata.system__time_utc | string | — | date-time | No | Yes | — | — |
name | string | — | — | No | Yes | — | — |
parent_folder_id | string or null | — | — | Yes | No | — | — |
success_condition | string | — | — | No | Yes | — | — |
success_examples | array<string> | — | — | No | No | — | — |
success_examples[] | string | — | — | No | Yes | — | — |
type | string | — | — | No | Yes | "llm" | — |
Tool Invocation variant (type = "tool")
| Field path | Type | Reference | Format | Nullable | Required | Enum | Description |
|---|---|---|---|---|---|---|---|
$ | object | — | — | No | Yes | — | — |
attach_to_agent_id | string or null | — | — | Yes | No | — | — |
chat_history | array<HistoryEntry> | — | — | No | No | — | — |
chat_history[] | object | HistoryEntry | — | No | Yes | — | — |
chat_history[].message | string or null | — | — | Yes | No | — | — |
chat_history[].role | string | — | — | No | Yes | "user", "agent" | — |
chat_history[].tool_calls | array<ToolCall> | — | — | No | No | — | — |
chat_history[].tool_calls[] | object | ToolCall | — | No | Yes | — | Bagian stabil kontrak vendor; detail bertipe baru tetap dipertahankan. |
chat_history[].tool_calls[].params_as_json | string | — | — | No | Yes | — | — |
chat_history[].tool_calls[].request_id | string | — | — | No | Yes | — | — |
chat_history[].tool_calls[].tool_details | object or null | — | — | Yes | No | — | — |
chat_history[].tool_calls[].tool_has_been_called | boolean | — | — | No | Yes | — | — |
chat_history[].tool_calls[].tool_name | string | — | — | No | Yes | — | — |
chat_history[].tool_calls[].type | string or null | — | — | Yes | No | — | — |
chat_history[].tool_results | array<ToolResult> | — | — | No | No | — | — |
chat_history[].tool_results[] | object | ToolResult | — | No | Yes | — | — |
chat_history[].tool_results[].is_blocked | boolean | — | — | No | No | — | — |
chat_history[].tool_results[].is_error | boolean | — | — | No | Yes | — | — |
chat_history[].tool_results[].request_id | string | — | — | No | Yes | — | — |
chat_history[].tool_results[].result_value | string | — | — | No | Yes | — | — |
chat_history[].tool_results[].tool_has_been_called | boolean | — | — | No | Yes | — | — |
chat_history[].tool_results[].tool_latency_secs | number | — | — | No | No | — | — |
chat_history[].tool_results[].tool_name | string | — | — | No | Yes | — | — |
chat_history[].tool_results[].type | string | — | — | No | Yes | — | — |
check_any_tool_matches | boolean | — | — | No | No | — | — |
conversation_initiation_source | string | — | — | No | No | "unknown", "telegram_integration" | — |
dynamic_variables | object | — | — | No | No | — | — |
from_conversation_metadata | object or null | FromConversationMetadata | — | Yes | No | — | — |
from_conversation_metadata.conversation_id | string | — | — | No | Yes | — | — |
from_conversation_metadata.event_seq | integer | — | — | No | Yes | — | — |
from_conversation_metadata.original_agent_response | string or null | — | — | Yes | No | — | — |
from_conversation_metadata.system__conversation_id | string or null | — | — | Yes | No | — | — |
from_conversation_metadata.system__time_utc | string | — | date-time | No | Yes | — | — |
name | string | — | — | No | Yes | — | — |
parent_folder_id | string or null | — | — | Yes | No | — | — |
tool_call_parameters | object or null | ToolCallParameters | — | Yes | No | — | — |
tool_call_parameters.parameters | array<ParameterCondition> | — | — | No | No | — | — |
tool_call_parameters.parameters[] | object | ParameterCondition | — | No | Yes | — | — |
tool_call_parameters.parameters[].eval | object | AnythingEval or ExactEval or RegexEval or LlmEval | — | No | Yes | — | — |
tool_call_parameters.parameters[].path | string | — | — | No | Yes | — | — |
tool_call_parameters.referenced_tool | object or null | ReferencedTool | — | Yes | No | — | — |
tool_call_parameters.referenced_tool.id | string | — | — | No | Yes | — | — |
tool_call_parameters.referenced_tool.type | string | — | — | No | Yes | "system", "webhook", "google_sheets", "client", "workflow", "api_integration_webhook", "mcp", "code" | — |
tool_call_parameters.verify_absence | boolean | — | — | No | No | — | — |
tool_call_parameters.workflow_node_transition | object or null | WorkflowTransition | — | Yes | No | — | — |
tool_call_parameters.workflow_node_transition.agent_id | string | — | — | No | Yes | — | — |
tool_call_parameters.workflow_node_transition.target_node_id | string | — | — | No | Yes | — | — |
tool_call_parameters.workflow_node_transition.type | string | — | — | No | No | "node_id" | — |
type | string | — | — | No | Yes | "tool" | — |
Next Reply request example
{
"chat_history": [
{
"message": "How do I return an unopened order?",
"role": "user"
}
],
"evaluation_model": "gpt-5-mini",
"failure_examples": [
"I cannot help with returns."
],
"name": "Helpful return reply",
"success_condition": "Explain the return policy and give one clear next action.",
"success_examples": [
"You can return it within the stated window. Start here…"
],
"type": "llm"
}Simulation request example
{
"chat_history": [],
"dynamic_variables": {
"customer_tier": "standard"
},
"evaluation_model": "gpt-5-mini",
"name": "Refund policy conversation",
"simulated_user_model": "gpt-5-mini",
"simulation_max_turns": 5,
"simulation_scenario": "A customer asks whether an unopened order can be returned.",
"success_conditions": [
"The agent explains the return window and gives the next action."
],
"tool_mock_config": {
"fallback_strategy": "raise_error",
"mocked_tool_ids": [],
"mocking_strategy": "all"
},
"tool_mock_overrides": {},
"type": "simulation"
}Tool Invocation request example
{
"chat_history": [
{
"message": "Where is order order_demo?",
"role": "user"
}
],
"check_any_tool_matches": true,
"name": "Look up the order",
"tool_call_parameters": {
"parameters": [
{
"eval": {
"expected_value": "order_demo",
"type": "exact"
},
"path": "order_id"
}
],
"referenced_tool": {
"id": "tool_demo",
"type": "webhook"
},
"verify_absence": false
},
"type": "tool"
}Example
curl --request POST 'https://operade.ai/api/v1/workspaces/ws_demo/agent-tests' \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{"type":"llm","name":"Helpful reply","chat_history":[{"role":"user","message":"How do I return an order?"}],"success_condition":"Explain the return policy clearly."}'{
"type": "llm",
"name": "Helpful reply",
"chat_history": [
{
"role": "user",
"message": "How do I return an order?"
}
],
"success_condition": "Explain the return policy clearly."
}Responses
| Status | Description | Content |
|---|---|---|
4XX | Handled client error | application/json: ErrorResponse |
201 | Successful Response | application/json: object |
4XX application/json response schema
| Field path | Type | Reference | Format | Nullable | Required | Enum | Description |
|---|---|---|---|---|---|---|---|
$ | object | ErrorResponse | — | No | Yes | — | — |
error | object | ErrorItem | — | No | Yes | — | — |
error.code | string | — | — | No | Yes | — | — |
error.details | object | — | — | No | No | — | — |
error.message | string | — | — | No | Yes | — | — |
201 application/json response schema
| Field path | Type | Reference | Format | Nullable | Required | Enum | Description |
|---|---|---|---|---|---|---|---|
$ | object | SimulationTestResource or NextReplyTestResource or ToolInvocationTestResource | — | No | Yes | — | — |
access | array<AccessGrant> | — | — | No | Yes | — | — |
access[] | object | AccessGrant | — | No | Yes | — | — |
access[].role | string | — | — | No | Yes | "viewer", "editor" | — |
access[].user_id | string | — | — | No | Yes | — | — |
access_role | string | — | — | No | Yes | "admin", "creator", "viewer", "editor" | — |
chat_history | array<HistoryEntry> | — | — | No | Yes | — | — |
chat_history[] | object | HistoryEntry | — | No | Yes | — | — |
chat_history[].message | string or null | — | — | Yes | No | — | — |
chat_history[].role | string | — | — | No | Yes | "user", "agent" | — |
chat_history[].tool_calls | array<ToolCall> | — | — | No | No | — | — |
chat_history[].tool_calls[] | object | ToolCall | — | No | Yes | — | Bagian stabil kontrak vendor; detail bertipe baru tetap dipertahankan. |
chat_history[].tool_calls[].params_as_json | string | — | — | No | Yes | — | — |
chat_history[].tool_calls[].request_id | string | — | — | No | Yes | — | — |
chat_history[].tool_calls[].tool_details | object or null | — | — | Yes | No | — | — |
chat_history[].tool_calls[].tool_has_been_called | boolean | — | — | No | Yes | — | — |
chat_history[].tool_calls[].tool_name | string | — | — | No | Yes | — | — |
chat_history[].tool_calls[].type | string or null | — | — | Yes | No | — | — |
chat_history[].tool_results | array<ToolResult> | — | — | No | No | — | — |
chat_history[].tool_results[] | object | ToolResult | — | No | Yes | — | — |
chat_history[].tool_results[].is_blocked | boolean | — | — | No | No | — | — |
chat_history[].tool_results[].is_error | boolean | — | — | No | Yes | — | — |
chat_history[].tool_results[].request_id | string | — | — | No | Yes | — | — |
chat_history[].tool_results[].result_value | string | — | — | No | Yes | — | — |
chat_history[].tool_results[].tool_has_been_called | boolean | — | — | No | Yes | — | — |
chat_history[].tool_results[].tool_latency_secs | number | — | — | No | No | — | — |
chat_history[].tool_results[].tool_name | string | — | — | No | Yes | — | — |
chat_history[].tool_results[].type | string | — | — | No | Yes | — | — |
conversation_initiation_source | string | — | — | No | Yes | "unknown", "telegram_integration" | — |
created_at | string | — | date-time | No | Yes | — | — |
created_by | string | — | — | No | Yes | — | — |
current_revision_id | string | — | — | No | Yes | — | — |
dynamic_variables | object | — | — | No | Yes | — | — |
entity_type | string | — | — | No | Yes | "test" | — |
evaluation_model | string | — | — | No | Yes | — | — |
from_conversation_metadata | object or null | FromConversationMetadata | — | Yes | Yes | — | — |
from_conversation_metadata.conversation_id | string | — | — | No | Yes | — | — |
from_conversation_metadata.event_seq | integer | — | — | No | Yes | — | — |
from_conversation_metadata.original_agent_response | string or null | — | — | Yes | No | — | — |
from_conversation_metadata.system__conversation_id | string or null | — | — | Yes | No | — | — |
from_conversation_metadata.system__time_utc | string | — | date-time | No | Yes | — | — |
id | string | — | — | No | Yes | — | — |
name | string | — | — | No | Yes | — | — |
parent_folder_id | string or null | — | — | Yes | Yes | — | — |
revision_created_at | string | — | date-time | No | Yes | — | — |
simulated_user_model | string | — | — | No | Yes | — | — |
simulation_max_turns | integer | — | — | No | Yes | — | — |
simulation_scenario | string | — | — | No | Yes | — | — |
success_conditions | array<string> | — | — | No | Yes | — | — |
success_conditions[] | string | — | — | No | Yes | — | — |
tool_mock_config | object | ToolMockConfig | — | No | Yes | — | — |
tool_mock_config.fallback_strategy | string | — | — | No | No | "raise_error", "call_real_tool" | — |
tool_mock_config.mocked_tool_ids | array<string> | — | — | No | No | — | — |
tool_mock_config.mocked_tool_ids[] | string | — | — | No | Yes | — | — |
tool_mock_config.mocking_strategy | string | — | — | No | No | "all", "selected", "none" | — |
tool_mock_overrides | object | — | — | No | Yes | — | — |
type | string | — | — | No | Yes | "simulation" | — |
updated_at | string | — | date-time | No | Yes | — | — |
failure_examples | array<string> | — | — | No | Yes | — | — |
failure_examples[] | string | — | — | No | Yes | — | — |
success_condition | string | — | — | No | Yes | — | — |
success_examples | array<string> | — | — | No | Yes | — | — |
success_examples[] | string | — | — | No | Yes | — | — |
check_any_tool_matches | boolean | — | — | No | Yes | — | — |
tool_call_parameters | object or null | ToolCallParameters | — | Yes | Yes | — | — |
tool_call_parameters.parameters | array<ParameterCondition> | — | — | No | No | — | — |
tool_call_parameters.parameters[] | object | ParameterCondition | — | No | Yes | — | — |
tool_call_parameters.parameters[].eval | object | AnythingEval or ExactEval or RegexEval or LlmEval | — | No | Yes | — | — |
tool_call_parameters.parameters[].path | string | — | — | No | Yes | — | — |
tool_call_parameters.referenced_tool | object or null | ReferencedTool | — | Yes | No | — | — |
tool_call_parameters.referenced_tool.id | string | — | — | No | Yes | — | — |
tool_call_parameters.referenced_tool.type | string | — | — | No | Yes | "system", "webhook", "google_sheets", "client", "workflow", "api_integration_webhook", "mcp", "code" | — |
tool_call_parameters.verify_absence | boolean | — | — | No | No | — | — |
tool_call_parameters.workflow_node_transition | object or null | WorkflowTransition | — | Yes | No | — | — |
tool_call_parameters.workflow_node_transition.agent_id | string | — | — | No | Yes | — | — |
tool_call_parameters.workflow_node_transition.target_node_id | string | — | — | No | Yes | — | — |
tool_call_parameters.workflow_node_transition.type | string | — | — | No | No | "node_id" | — |
Response example
{
"entity_type": "test",
"id": "string",
"current_revision_id": "string",
"created_by": "string",
"created_at": "2026-01-01T00:00:00Z",
"updated_at": "2026-01-01T00:00:00Z",
"revision_created_at": "2026-01-01T00:00:00Z",
"access_role": "admin",
"access": [],
"name": "string",
"parent_folder_id": "string",
"chat_history": [],
"dynamic_variables": {},
"conversation_initiation_source": "unknown",
"from_conversation_metadata": {
"conversation_id": "string",
"event_seq": 0,
"system__time_utc": "2026-01-01T00:00:00Z"
},
"type": "simulation",
"simulation_scenario": "string",
"success_conditions": [],
"simulation_max_turns": 0,
"simulated_user_model": "string",
"evaluation_model": "string",
"tool_mock_config": {},
"tool_mock_overrides": {}
}Errors
Reviewed common and route-declared errors are summarized here; the list is not exhaustive. Start with the distributed error index to find each code's canonical domain page.
| Status | Code | Description |
|---|---|---|
401 | unauthenticated | Authentication is missing, invalid, or revoked. |
403 | forbidden | The authenticated caller does not have access to this operation. |
404 | not_found | The requested workspace resource was not found. |
422 | validation_failed | The request did not pass field or business validation. |
