> ## Documentation Index
> Fetch the complete documentation index at: https://docs.usetuner.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Save Scenarios To Library

> Bulk-save selected AI-generated scenarios from a completed run into the library.

This is the bridge between AI generation and the scenario library: within an expanded
run card, a user selects one or more generated scenarios, names each one, applies a
shared set of tags, and saves them all in one action. Each new library `scenario` row
is populated field-to-field from that scenario's generated output (`origin=ai_saved`,
`source_run_id` set to this run, `format=freeform`) -- not stored as a text blob.

Only available on a completed run (`status` is `complete` or `partial`). A scenario
whose call failed to connect can still be saved -- the definition is valid even if the
execution wasn't; the run status gate is about the run as a whole, not each call.

Atomic: every selection is validated before anything is created. If any single
selection is invalid, not found, or already saved, the entire request is rejected and
nothing is created.



## OpenAPI

````yaml https://api.usetuner.ai/public/openapi.json post /api/v1/workspaces/{workspace_id}/agents/{agent_id}/simulation-runs/{simulation_run_id}/scenarios/save
openapi: 3.1.0
info:
  title: My Public API
  version: 1.0.0
servers:
  - url: https://api.usetuner.ai
security: []
tags:
  - name: calls
    x-group: Calls
  - name: workspaces
    x-group: Workspaces
  - name: simulation
    x-group: Simulation
  - name: agent-settings
    x-group: Agent Settings
  - name: agents
    x-group: Agents
  - name: scenarios
    x-group: Scenarios
  - name: traces
    x-group: Traces
  - name: providers
    x-group: Providers
paths:
  /api/v1/workspaces/{workspace_id}/agents/{agent_id}/simulation-runs/{simulation_run_id}/scenarios/save:
    post:
      tags:
        - simulation
      summary: Save Scenarios To Library
      description: >-
        Bulk-save selected AI-generated scenarios from a completed run into the
        library.


        This is the bridge between AI generation and the scenario library:
        within an expanded

        run card, a user selects one or more generated scenarios, names each
        one, applies a

        shared set of tags, and saves them all in one action. Each new library
        `scenario` row

        is populated field-to-field from that scenario's generated output
        (`origin=ai_saved`,

        `source_run_id` set to this run, `format=freeform`) -- not stored as a
        text blob.


        Only available on a completed run (`status` is `complete` or `partial`).
        A scenario

        whose call failed to connect can still be saved -- the definition is
        valid even if the

        execution wasn't; the run status gate is about the run as a whole, not
        each call.


        Atomic: every selection is validated before anything is created. If any
        single

        selection is invalid, not found, or already saved, the entire request is
        rejected and

        nothing is created.
      operationId: >-
        save_simulation_scenarios_api_v1_workspaces__workspace_id__agents__agent_id__simulation_runs__simulation_run_id__scenarios_save_post
      parameters:
        - name: simulation_run_id
          in: path
          required: true
          schema:
            type: integer
            description: ID of the simulation run
            title: Simulation Run Id
          description: ID of the simulation run
        - name: agent_id
          in: path
          required: true
          schema:
            type: integer
            description: Tuner's internal numeric ID for the agent.
            title: Agent Id
          description: Tuner's internal numeric ID for the agent.
        - name: workspace_id
          in: path
          required: true
          schema:
            type: integer
            description: Workspace ID. Find this in Workspace > General Settings.
            title: Workspace Id
          description: Workspace ID. Find this in Workspace > General Settings.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SaveScenariosFromRunRequest'
      responses:
        '201':
          description: Successful Response
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/ScenarioResponse'
                title: >-
                  Response Save Simulation Scenarios Api V1 Workspaces 
                  Workspace Id  Agents  Agent Id  Simulation Runs  Simulation
                  Run Id  Scenarios Save Post
        '401':
          description: Missing or invalid API key.
          content:
            application/json:
              example:
                detail: Not authenticated
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: You do not have access to this workspace.
          content:
            application/json:
              example:
                detail: User does not have access to workspace 42
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: >-
            Agent not found, or a selected scenario execution does not belong to
            this run/agent.
          content:
            application/json:
              example:
                detail: Simulation scenario execution 501 not found for this run.
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '409':
          description: >-
            The run has not finished running (status is not `complete` or
            `partial`), or a selected execution was already saved to the
            library.
          content:
            application/json:
              example:
                detail: Scenario execution 501 has already been saved to the library.
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '422':
          description: >-
            A selected execution has no `situation` to save, a selection's
            `name` is blank after trimming, or an execution id was selected more
            than once.
          content:
            application/json:
              example:
                detail: Scenario execution 501 has no situation to save.
              schema:
                $ref: '#/components/schemas/ErrorResponse'
      security:
        - Bearer: []
components:
  schemas:
    SaveScenariosFromRunRequest:
      properties:
        selections:
          items:
            $ref: '#/components/schemas/ScenarioSaveSelection'
          type: array
          maxItems: 100
          minItems: 1
          title: Selections
        tags:
          anyOf:
            - items:
                type: string
                maxLength: 50
              type: array
              maxItems: 20
            - type: 'null'
          title: Tags
      type: object
      required:
        - selections
      title: SaveScenariosFromRunRequest
      description: >-
        Request to bulk-save selected AI-generated scenarios from a completed
        run into the

        library (ENG-1540).


        One `ScenarioSaveSelection` per checked row in the run card's
        multi-select; `tags` is

        a single shared list applied identically to every scenario created by
        this request.
    ScenarioResponse:
      properties:
        id:
          type: integer
          title: Id
        agent_id:
          type: integer
          title: Agent Id
        workspace_id:
          type: integer
          title: Workspace Id
        name:
          type: string
          title: Name
        type:
          type: string
          title: Type
        format:
          type: string
          title: Format
        origin:
          type: string
          title: Origin
        situation:
          type: string
          title: Situation
        goal:
          anyOf:
            - type: string
            - type: 'null'
          title: Goal
        first_line:
          anyOf:
            - type: string
            - type: 'null'
          title: First Line
        stop_condition:
          anyOf:
            - type: string
            - type: 'null'
          title: Stop Condition
        intent_id:
          anyOf:
            - type: integer
            - type: 'null'
          title: Intent Id
        target_ai_evaluation:
          anyOf:
            - additionalProperties: true
              type: object
            - type: 'null'
          title: Target Ai Evaluation
        tags:
          anyOf:
            - items:
                type: string
              type: array
            - type: 'null'
          title: Tags
        source_run_id:
          anyOf:
            - type: integer
            - type: 'null'
          title: Source Run Id
        created_at:
          type: string
          format: date-time
          title: Created At
        updated_at:
          type: string
          format: date-time
          title: Updated At
        last_run:
          anyOf:
            - $ref: '#/components/schemas/ScenarioExecutionItem'
            - type: 'null'
      type: object
      required:
        - id
        - agent_id
        - workspace_id
        - name
        - type
        - format
        - origin
        - situation
        - goal
        - first_line
        - stop_condition
        - intent_id
        - target_ai_evaluation
        - tags
        - source_run_id
        - created_at
        - updated_at
      title: ScenarioResponse
      description: Response schema for a single library scenario.
    ErrorResponse:
      properties:
        detail:
          type: string
          title: Detail
          description: Human-readable description of what went wrong.
      type: object
      required:
        - detail
      title: ErrorResponse
      description: Error body returned when a request fails.
    ScenarioSaveSelection:
      properties:
        simulation_scenario_id:
          type: integer
          title: Simulation Scenario Id
          description: >-
            ID of the generated-scenario execution to save
            (simulation_run_scenarios.id, i.e. SimulationScenarioResponse.id
            from the sibling GET endpoint).
        name:
          type: string
          maxLength: 200
          title: Name
          description: >-
            Library name for the new scenario. Client-side this is prefilled
            from generated_scenario['persona'], but the backend validates it
            independently (must be non-empty after trimming).
      type: object
      required:
        - simulation_scenario_id
        - name
      title: ScenarioSaveSelection
      description: >-
        One AI-generated scenario, selected from an expanded run card, to save
        to the library.


        `simulation_scenario_id` is a `simulation_run_scenarios.id` -- the SAME
        id already

        returned as `SimulationScenarioResponse.id` by `GET
        .../simulation-runs/{id}/scenarios`

        (the "execution" record), not a library `scenario.id`.
    ScenarioExecutionItem:
      properties:
        simulation_run_id:
          type: integer
          title: Simulation Run Id
        run_created_at:
          type: string
          format: date-time
          title: Run Created At
        status:
          anyOf:
            - type: string
            - type: 'null'
          title: Status
        duration:
          anyOf:
            - type: number
            - type: 'null'
          title: Duration
        call_id:
          anyOf:
            - type: integer
            - type: 'null'
          title: Call Id
        analysis_stopped:
          type: boolean
          title: Analysis Stopped
        target_eval_label:
          anyOf:
            - type: string
            - type: 'null'
          title: Target Eval Label
        evals:
          items:
            $ref: '#/components/schemas/SimulationCallEvalResult'
          type: array
          title: Evals
        type:
          type: string
          title: Type
        evals_expected:
          type: boolean
          title: Evals Expected
      type: object
      required:
        - simulation_run_id
        - run_created_at
        - status
        - duration
        - call_id
        - analysis_stopped
        - target_eval_label
        - type
        - evals_expected
      title: ScenarioExecutionItem
      description: >-
        One past execution of a library scenario, within one simulation run.


        Deliberately its own class rather than a reuse of
        `SimulationCallDetailResponse`

        (`app/schemas/simulation_run.py`): that model already has a field called

        `scenario_id` meaning "the id of the `simulation_run_scenarios` row"
        (the execution

        record itself), which is a different concept from the library
        `scenario.id` this

        endpoint is scoped by. Reusing that model here would silently collide
        the two

        meanings under the same field name.


        Carries the same raw ingredients as `SimulationCallDetailResponse`

        (`status`, `call_id`, `duration`, `analysis_stopped`, `evals`, `type`,

        `target_eval_label`) that the web's `getScenarioVerdict()` helper

        (`voice-ray-web/src/lib/simulation/displayHelpers.ts`) already consumes
        to compute

        pass/fail client-side -- no server-side verdict is computed here, by
        design.


        Reused as-is (ENG-1541) for `ScenarioResponse.last_run`, the scenario
        list's additive

        "most recent execution" field -- same raw ingredients, one execution
        either way.
    SimulationCallEvalResult:
      properties:
        label:
          type: string
          title: Label
        value:
          anyOf:
            - type: string
            - type: 'null'
          title: Value
        evidence:
          anyOf:
            - type: string
            - type: 'null'
          title: Evidence
      type: object
      required:
        - label
        - value
        - evidence
      title: SimulationCallEvalResult
  securitySchemes:
    Bearer:
      type: http
      description: >-
        Use Tuner API key (tr_api_...) or user session token. Find your API key
        in Workspace Settings > API Keys.
      scheme: bearer

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.