{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/cekura-ai/json-schema/cekura-ai-schema-scenario-schema.json",
  "title": "SchemaScenario",
  "x-generated": "2026-10-29",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/cekura-ai-openapi.json#/components/schemas/SchemaScenario",
  "type": "object",
  "properties": {
    "id": {
      "type": "integer",
      "readOnly": true
    },
    "name": {
      "type": "string",
      "description": "Name of the evaluator"
    },
    "agent": {
      "type": "integer",
      "description": "\nAgent ID\nExample: `2142`\n"
    },
    "project": {
      "type": [
        "integer",
        "null"
      ]
    },
    "assistant_id": {
      "type": "string",
      "writeOnly": true,
      "description": "\nAlternative to agent ID - the assistant ID to use for this scenario\nExample: `\"asst_1234567890\"`\n"
    },
    "personality": {
      "type": "integer",
      "description": "ID of the personality"
    },
    "personality_name": {
      "type": "string",
      "description": "Name of the personality"
    },
    "agent_name": {
      "type": "string",
      "readOnly": true,
      "description": "\nName of the agent associated with this scenario\nExample: `\"Customer Support Agent\"`\n"
    },
    "tags": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "\nList of tags of the evaluators\nExample: `[\"tag1\", \"tag2\", \"tag3\"]`\n"
    },
    "tool_ids": {
      "description": "\nList of tool IDs to associate with this scenario\nExample: `[\"TOOL_DTMF\", \"TOOL_END_CALL\"]`\n"
    },
    "metrics": {
      "type": "array",
      "items": {
        "type": "integer"
      },
      "description": "\nList of metric IDs\nExample: `[123, 456, 789]`\n"
    },
    "metric_names": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "\nList of metric names\nExample: `[\"Metric 1\", \"Metric 2\", \"Metric 3\"]`\n"
    },
    "phone_number": {
      "type": "string",
      "description": "Phone number eg: +17776666333"
    },
    "outbound_phone_number_data": {
      "allOf": [
        {
          "$ref": "#/$defs/PhoneNumberInbound"
        }
      ],
      "readOnly": true,
      "description": "\nPhone number used for outbound calls in this scenario\nExample: `\"+1234567890\"`\n"
    },
    "first_message": {
      "type": "string",
      "description": "First message of the evaluator"
    },
    "inbound_phone_number": {
      "type": [
        "integer",
        "null"
      ]
    },
    "inbound_phone_number_data": {
      "allOf": [
        {
          "$ref": "#/$defs/PhoneNumberInbound"
        }
      ],
      "readOnly": true,
      "description": "\n(Deprecated) Phone number used for inbound calls in this scenario. Use outbound_phone_number_data instead.\nAfter CEK-6517, both phone_number and inbound_phone_number fields are synced, so outbound_phone_number_data contains the unified phone number for both inbound and outbound calls.\nExample: `{\"id\": 123, \"number\": \"+1234567890\", \"phone_number_id\": \"abc123\"}`\n"
    },
    "instructions": {
      "type": "string",
      "description": "\nScenario Instructions - format depends on scenario_type:\n- For `instruction` type: Plain text instructions\n- For `conditional_actions` type: JSON string with `role`, `first_message` and a `conditions` array. Each condition has `when` (a natural-language third-person description of the main agent's observable action — e.g. `\"The agent asks for your date of birth\"`, matched semantically), `say` (spoken verbatim, with optional `<silence time=\"1.5s\" />` (interruptible) or `<hold time=\"2s\" />` (not interruptible) and `[laughter]` tags; wrap the whole step in `<ai_generated>...</ai_generated>` to improvise instead) and optional `then` follow-up steps. Responses return this format unless `conditional_actions_format=legacy` is passed. The earlier id-based format (`id`, `condition`, `action`, `type`, `fixed_message`) is still accepted on writes.\n"
    },
    "conditional_actions": {
      "writeOnly": true,
      "description": "Structured conditional-actions object. Requires `scenario_type=\"conditional_actions\"` in the same request, unless the scenario already has that type. Use either `conditional_actions` (structured) or `instructions` (plain text) — not both. `first_message` is what the caller says first (empty means wait for the agent). Each condition's `say` is spoken verbatim; wrap a whole step in `<ai_generated>...</ai_generated>` to let the caller improvise from it. `then` steps fire in order, one per caller turn, after the agent replies. Responses return this format unless `conditional_actions_format=legacy` is passed. The earlier id-based format (`id`, `condition`, `action`, `type`, `fixed_message`) is also accepted.\n\nExample:\n```json\n{\n  \"role\": \"You are a patient calling to schedule an appointment\",\n  \"first_message\": \"Hi, I need to schedule an appointment\",\n  \"conditions\": [\n    {\"when\": \"the agent asks for your name\", \"say\": \"John Smith\",\n     \"then\": [\"<ai_generated>Confirm whichever details the agent reads back</ai_generated>\"]}\n  ]\n}\n```"
    },
    "condition_audio": {
      "type": "object",
      "additionalProperties": {},
      "readOnly": true,
      "description": "Pre-recorded clips available to this scenario's conditional actions, keyed by clip id. Read-only: upload, replace and delete clips, and correct a transcript, through `condition-audio/`. Reference a clip from any number of verbatim steps by pasting its `tag`; `steps` lists where it is used (e.g. `conditions[1].then[0]`).\n\nExample:\n```json\n{\n  \"greeting\": {\"tag\": \"<audio id=\\\"greeting\\\"/>\", \"filename\": \"greeting.wav\",\n               \"status\": \"ready\", \"duration\": 2.4, \"transcript\": \"Hi, is this the clinic?\",\n               \"steps\": [\"first_message\", \"conditions[1]\"]}\n}\n```"
    },
    "simulation_description": {
      "type": "string",
      "readOnly": true
    },
    "information_fields": {
      "type": "object",
      "additionalProperties": {},
      "description": "\nInformation fields of the evaluator\nExample:\n```json\n{\n    \"user_name\": \"John Doe\",\n    \"user_email\": \"john.doe@example.com\",\n}\n```\n"
    },
    "expected_outcome_prompt": {
      "type": "string",
      "description": "\nExpected outcome prompt of the evaluator\nExample: `\"The user should be able to complete the order\"`\n"
    },
    "scenario_language": {
      "enum": [
        "af",
        "ar",
        "bn",
        "bg",
        "zh",
        "cs",
        "da",
        "nl",
        "en",
        "et",
        "fi",
        "fr",
        "de",
        "el",
        "gu",
        "hi",
        "he",
        "hu",
        "id",
        "it",
        "ja",
        "kn",
        "kk",
        "ko",
        "ms",
        "ml",
        "mr",
        "multi",
        "no",
        "pl",
        "pa",
        "pt",
        "ro",
        "ru",
        "sk",
        "es",
        "sv",
        "th",
        "tr",
        "tl",
        "ta",
        "te",
        "uk",
        "uz",
        "vi"
      ],
      "type": "string",
      "x-spec-enum-id": "f996e9ef7edb7fea",
      "description": "\nLanguage of the scenario\n\n\n* `af` - Afrikaans\n* `ar` - Arabic\n* `bn` - Bengali\n* `bg` - Bulgarian\n* `zh` - Chinese Simplified\n* `cs` - Czech\n* `da` - Danish\n* `nl` - Dutch\n* `en` - English\n* `et` - Estonian\n* `fi` - Finnish\n* `fr` - French\n* `de` - German\n* `el` - Greek\n* `gu` - Gujarati\n* `hi` - Hindi\n* `he` - Hebrew\n* `hu` - Hungarian\n* `id` - Indonesian\n* `it` - Italian\n* `ja` - Japanese\n* `kn` - Kannada\n* `kk` - Kazakh\n* `ko` - Korean\n* `ms` - Malay\n* `ml` - Malayalam\n* `mr` - Marathi\n* `multi` - Multilingual\n* `no` - Norwegian\n* `pl` - Polish\n* `pa` - Punjabi\n* `pt` - Portuguese\n* `ro` - Romanian\n* `ru` - Russian\n* `sk` - Slovak\n* `es` - Spanish\n* `sv` - Swedish\n* `th` - Thai\n* `tr` - Turkish\n* `tl` - Tagalog\n* `ta` - Tamil\n* `te` - Telugu\n* `uk` - Ukrainian\n* `uz` - Uzbek\n* `vi` - Vietnamese"
    },
    "scenario_type": {
      "type": "string",
      "description": "\nType of scenario:\n- `instruction`: Standard instruction-based scenario (plain text instructions)\n- `conditional_actions`: Conditional action-based scenario (JSON with role, conditions, SSML tags, emotion markers)\n"
    },
    "suite_type": {
      "enum": [
        "undefined",
        "infrastructure"
      ],
      "type": "string",
      "x-spec-enum-id": "643f6a8cdc799a77",
      "description": "Type of predefined suite (e.g., infrastructure)\n\n* `undefined` - Undefined\n* `infrastructure` - Infrastructure"
    },
    "is_predefined": {
      "type": "boolean",
      "description": "Whether this is a predefined scenario (template)"
    },
    "test_profile": {
      "type": [
        "integer",
        "null"
      ]
    },
    "test_profile_data": {
      "allOf": [
        {
          "$ref": "#/$defs/AIAgentTestProfile"
        }
      ],
      "readOnly": true,
      "description": "\nDetails of the test profile associated with this scenario. `information` uses the\nsectioned shape: `main_agent_variables` are sent to the agent under test as\ndynamic variables at call time; `testing_agent_variables` are persona/context\nused by Cekura's simulated caller. Legacy flat dicts (no section keys) still\nwork — at call time they are delivered to both sides for backward compatibility.\nExample:\n```json\n{\n    \"id\": \"<integer>\",\n    \"agent_id\": \"<integer>\",\n    \"name\": \"<string>\",\n    \"information\": {\n        \"main_agent_variables\": {\n            \"user_id\": \"<string>\",\n            \"account_id\": \"<string>\"\n        },\n        \"testing_agent_variables\": {\n            \"user_name\": \"<string>\",\n            \"user_email\": \"<string>\",\n            \"order_id\": \"<string>\"\n        }\n    }\n}\n```\n"
    },
    "dynamic_variable_values": {
      "readOnly": true,
      "description": "REMOVED FROM API. Reads return the historical value for legacy rows (`null` for new rows). Writes are no longer accepted — supplying a non-null value yields a 400 error. Put dynamic-variable values in `test_profile_data.information.main_agent_variables` instead: create the test profile via POST /test-profiles/ and attach it via the `test_profile` field on the scenario."
    },
    "generated_mock_tool_entries": {
      "oneOf": [
        {},
        {
          "type": "null"
        }
      ],
      "description": "Expected mock tool calls for this evaluator. Each entry has shape {tool_id, tool_name, new_entry: {input, output, response?}}. Auto-generated during scenario generation when the agent has mock tools attached; can also be set or edited manually."
    },
    "folder_path": {
      "type": [
        "string",
        "null"
      ],
      "description": "Path of an existing folder to assign this evaluator to, e.g. \"Sales\" or \"Sales.Inbound\". Create it first with the create-folder endpoint."
    },
    "max_duration": {
      "type": [
        "integer",
        "null"
      ],
      "description": "\nMax call duration in seconds for this scenario. If not provided or set to null, the scenario will use the project's max_call_duration setting.\nValid range: 10-3600 seconds (10 seconds to 60 minutes)\nExample: `600` (10 minutes)\n"
    }
  },
  "$defs": {
    "AIAgentTestProfile": {
      "type": "object",
      "description": "",
      "properties": {
        "id": {
          "type": "integer",
          "readOnly": true
        },
        "project": {
          "type": [
            "integer",
            "null"
          ]
        },
        "agent": {
          "type": [
            "integer",
            "null"
          ]
        },
        "agent_name": {
          "type": "string",
          "readOnly": true,
          "description": "\nName of the agent associated with this test profile\nExample: `\"Customer Support Agent\"`\n"
        },
        "name": {
          "type": "string",
          "maxLength": 255
        },
        "information": {
          "description": "\nVariables for the test profile, split by which agent receives them.\n```json\n{\n    \"main_agent_variables\": {\"user_id\": \"U-123\"},\n    \"testing_agent_variables\": {\"user_name\": \"John Doe\", \"user_email\": \"john.doe@example.com\"}\n}\n```\n`main_agent_variables` are sent to the agent under test as dynamic variables. `testing_agent_variables` shape the simulated caller's persona. A legacy flat dict (no section keys) is accepted for backward compatibility and is sent to both agents.\n\nKeys in `main_agent_variables` starting with `X-` are additionally sent as custom SIP headers (SIP runs) or connection headers (WebSocket runs) to the agent under test. For SIP runs this is the only way to pass custom headers; `X-Run-Id`, `X-Scenario-Id`, and `X-Result-Id` are reserved and always set by Cekura.\n"
        },
        "created_by": {
          "type": [
            "integer",
            "null"
          ],
          "readOnly": true,
          "description": "ID of the user who created this test profile"
        },
        "last_updated_by": {
          "type": [
            "integer",
            "null"
          ],
          "readOnly": true,
          "description": "ID of the user who last updated this test profile"
        },
        "created_at": {
          "type": "string",
          "format": "date-time",
          "readOnly": true,
          "description": "Timestamp when the test profile was created"
        },
        "updated_at": {
          "type": "string",
          "format": "date-time",
          "readOnly": true,
          "description": "Timestamp when the test profile was last updated"
        }
      },
      "required": [
        "name"
      ]
    },
    "PhoneNumberInbound": {
      "type": "object",
      "description": "",
      "properties": {
        "id": {
          "type": "integer",
          "readOnly": true
        },
        "number": {
          "type": "string",
          "maxLength": 15
        },
        "phone_number_id": {
          "type": "string",
          "maxLength": 255
        }
      },
      "required": [
        "number",
        "phone_number_id"
      ]
    }
  }
}