# Simulation Coverage

The simulation coverage API provides branch-and-bound exploration of context graph state space. It replaces random sampling with targeted exploration that steers conversations toward untested states, tools, and transitions.

{% hint style="info" %}
**Conceptual overview**: For background on how coverage testing works, see the [Simulation Coverage](https://docs.amigo.ai/testing/simulations#simulation-coverage) conceptual documentation.
{% endhint %}

## Core Model

{% @mermaid/diagram content="%%{init: {"theme": "base", "themeVariables": {"primaryColor": "#D4E2E7", "primaryTextColor": "#100F0F", "primaryBorderColor": "#083241", "lineColor": "#575452", "textColor": "#100F0F", "clusterBkg": "#F1EAE7", "clusterBorder": "#D7D2D0"}}}%%
flowchart TB
subgraph Run\["Coverage Run (ephemeral DB branch)"]
S1\["Session 1"] --> T1a\["Turn 1"] --> T1b\["Turn 2"] --> T1c\["Turn 3"]
T1c -->|Fork| S2\["Session 2\n(child)"]
T1c -->|Fork| S3\["Session 3\n(child)"]
S2 --> T2a\["Turn 4"]
S3 --> T3a\["Turn 4"]
end

```
Run --> Graph["Knowledge Graph"]

subgraph Graph_Detail["Graph Layers"]
    OBS["Observed: per-state\nsession counts + pass rates"]
    GHOST["Ghost nodes: states\nnever reached"]
end

Graph --> Graph_Detail" %}
```

Coverage is organized into three levels:

| Resource             | Description                                                                                  |
| -------------------- | -------------------------------------------------------------------------------------------- |
| **Coverage Run**     | A campaign that owns an ephemeral database branch for write isolation. Contains sessions.    |
| **Coverage Session** | A conversation path within a run. Sessions can be forked from other sessions at any turn.    |
| **Coverage Turn**    | A single agent turn within a session, recording context graph state, tool calls, and scores. |

Sessions form a tree structure through the fork mechanism. Each session tracks its `parent_session_id` and `fork_turn_index`, so the full exploration tree is reconstructable from the session list.

## Endpoints

All endpoints are scoped to a workspace and require a workspace API key.

### Create Coverage Run

|            |                                                |
| ---------- | ---------------------------------------------- |
| **Method** | `POST`                                         |
| **Path**   | `/v1/{workspace_id}/simulations/coverage/runs` |
| **Auth**   | Workspace API key                              |

#### Request Body

| Field        | Type          | Description             |
| ------------ | ------------- | ----------------------- |
| `service_id` | string (UUID) | Service to test against |
| `name`       | string        | Human-readable run name |

#### Response

Returns the created run with ID, status (`active`), and the associated ephemeral database branch.

### Create Coverage Session

|            |                                                                  |
| ---------- | ---------------------------------------------------------------- |
| **Method** | `POST`                                                           |
| **Path**   | `/v1/{workspace_id}/simulations/coverage/runs/{run_id}/sessions` |
| **Auth**   | Workspace API key                                                |

Creates a new conversation session within a run. The session starts with a fresh agent state.

#### Request Body

| Field        | Type          | Description                               |
| ------------ | ------------- | ----------------------------------------- |
| `persona_id` | string (UUID) | Optional persona for the simulated caller |

### Step a Session

|            |                                                                      |
| ---------- | -------------------------------------------------------------------- |
| **Method** | `POST`                                                               |
| **Path**   | `/v1/{workspace_id}/simulations/coverage/sessions/{session_id}/step` |
| **Auth**   | Workspace API key                                                    |

Sends a simulated user message and records the agent's response as a turn.

#### Request Body

| Field         | Type   | Description            |
| ------------- | ------ | ---------------------- |
| `caller_text` | string | Simulated user message |

#### Response

Returns the turn observation including agent response, context graph state, tool calls, and turn index.

### Fork a Session

|            |                                                                      |
| ---------- | -------------------------------------------------------------------- |
| **Method** | `POST`                                                               |
| **Path**   | `/v1/{workspace_id}/simulations/coverage/sessions/{session_id}/fork` |
| **Auth**   | Workspace API key                                                    |

Atomically clones the parent session state N times, steps each clone with a different simulated message, and returns all observations. This is the core branch-and-bound primitive.

#### Request Body

| Field      | Type            | Description                                 |
| ---------- | --------------- | ------------------------------------------- |
| `messages` | array of string | Simulated user messages, one per fork child |

#### Response

Returns an array of fork results, each containing:

| Field        | Type           | Description                                          |
| ------------ | -------------- | ---------------------------------------------------- |
| `session_id` | string (UUID)  | New child session ID                                 |
| `turn`       | object         | Turn observation (agent response, state, tool calls) |
| `error`      | string or null | Error message if the fork child failed               |

Each child session inherits the parent's full conversation history up to the fork point. The parent session remains unchanged.

### Score a Session

|            |                                                                       |
| ---------- | --------------------------------------------------------------------- |
| **Method** | `POST`                                                                |
| **Path**   | `/v1/{workspace_id}/simulations/coverage/sessions/{session_id}/score` |
| **Auth**   | Workspace API key                                                     |

Evaluates the session against configured metrics. Scores are attributed per-session, not per-state-visit.

#### Response

Returns metric scores for the session.

### Get Coverage Graph

|            |                                                               |
| ---------- | ------------------------------------------------------------- |
| **Method** | `GET`                                                         |
| **Path**   | `/v1/{workspace_id}/simulations/coverage/runs/{run_id}/graph` |
| **Auth**   | Workspace API key                                             |

Returns the knowledge graph for the run. The graph has two layers:

| Layer                | Description                                                                                                                 |
| -------------------- | --------------------------------------------------------------------------------------------------------------------------- |
| **Observed turns**   | Aggregated per context graph state: session count, pass rate, total turns                                                   |
| **Topology overlay** | Ghost nodes for context graph states that exist in the state machine but were never reached. These represent coverage gaps. |

#### Response

| Field                   | Type          | Description                                                |
| ----------------------- | ------------- | ---------------------------------------------------------- |
| `nodes`                 | array         | One node per context graph state (observed + ghost)        |
| `nodes[].state_name`    | string        | Context graph state identifier                             |
| `nodes[].session_count` | int           | Number of sessions that visited this state                 |
| `nodes[].pass_rate`     | float or null | Aggregate pass rate across sessions (null for ghost nodes) |
| `nodes[].turn_count`    | int           | Total turns recorded in this state                         |
| `nodes[].is_ghost`      | boolean       | True if the state was never reached                        |
| `edges`                 | array         | Transitions between states (from context graph definition) |
| `sessions`              | array         | Session tree with parent/child relationships               |

### Complete a Coverage Run

|            |                                                                  |
| ---------- | ---------------------------------------------------------------- |
| **Method** | `POST`                                                           |
| **Path**   | `/v1/{workspace_id}/simulations/coverage/runs/{run_id}/complete` |
| **Auth**   | Workspace API key                                                |

Marks the run as finished and cleans up the ephemeral database branch. Sessions and turns remain available for read access.

## Write Isolation

Coverage runs use copy-on-write database branches. All tool writes during simulation sessions go to the ephemeral branch, not production data. When the run completes, the branch is cleaned up. This allows coverage testing to exercise tools that create appointments, update patient records, or write to the world model without contaminating live data.
