---
title: "Create a simulation suite for this agent"
method: POST
path: "/v1/agents/{agent_id}/simulation-suites"
---

# Create a simulation suite for this agent

`POST /v1/agents/{agent_id}/simulation-suites`

## Request

- Base URL: `https://api.skysay.ai`
- URL: `https://api.skysay.ai/v1/agents/{agent_id}/simulation-suites`
- Auth: none declared

Creates the suite and its first immutable revision. Authored scenarios are validated and bounded here; a scenario may name a runner whose runtime is not deployed yet, but a run that selects one is refused with 422 unsupported_mode.

## Path parameters

- `agent_id` string, required

## Request body

- object
  - `default_snapshot_source` 'draft' | 'published'
  - `description` string
  - `name` string, required
  - `policy` object: Thresholds, budget ceiling and retention for this suite.
  - `scenarios` object[]: Authored caller scenarios. At most 50 per suite. Each scenario's turns carry what the caller does and when: kind is speech, backchannel or silence; a silence turn carries silence_ms and no caller_input, because a silence is time rather than words; cue.after_agent_turn (1-based, and 0 meaning no cue at all: take the turn when the agent finishes) and cue.delay_ms record where inside an observed agent turn the caller speaks. Multiple cues anchored to the same turn share that observed origin, and an unobserved cue or incomplete schedule produces no scenario timing proof rather than an invented one. ground_truth_variants records alternative renderings of the same line -- a numeral written as digits or as words, say -- so a run's stored evidence carries what the caller was authored to say in every form that counts as correct. The platform's own offline recognition metric still scores against caller_input alone; the variants are carried for the readiness scorer that reads them. A silence turn needs the adaptive_voice runner and is refused with 422 silence_needs_a_room on any other, because only a room has time to spend. An adaptive_voice scenario may also carry caller_environment: a version-pinned synthetic caller MICROPHONE condition using noise_level (not the agent audio_environment volume). A scenario that supplies caller_environment must use adaptive_voice and also supply a non-blank language; it is never silently changed to English. Off/noise_level=0 is the quiet baseline; it never changes the agent's output ambience, TTS, or production STT configuration. A saved condition is authoring data, not proof that this deployment ran a realtime room.
    - `caller_environment` CallerInputEnvironmentSelection: Simulation Lab only: a version-pinned condition mixed into the synthetic caller microphone. This is not the agent's outgoing audio_environment and never changes a production call's STT/TTS configuration.
      - `asset_version` 'v1', required: Immutable packaged asset version; it is never inferred.
      - `noise_level` integer, required: Whole-number caller-input level. Off requires 0; enabled presets require 1 through 100.
      - `preset_id` string, required: Exact catalogue id. `off` has no asset and is the quiet baseline.

## Response `201`

Created suite at revision 1

## Other responses

- `400`: Invalid scenario contract or a limit exceeded
- `404`: Agent not found, or Simulations Lab is not enabled

---

[API](https://skmtc.dev/skysay/apis/skysay-api.md) · [All operations](https://skmtc.dev/skysay/apis/skysay-api/llms.txt) · [OpenAPI document](https://skmtc.dev/skysay/apis/skysay-api/revisions/95b8c66f99aa?raw)
