# Start a test run (/docs/api/voice-agents/agent-tests/startAgentTestRun)

> For the complete documentation index, see [llms.txt](https://docs.tandemcx.ai/llms.txt). Any page on this site can be fetched as Markdown by appending `.md` to its URL.

`POST /v1/agent-media/agents/{agentId}/test-runs`

Start a test run

Run the agent's tests against one version, draft or published. Each test runs `repeat` times (its own, or the settings' `defaultRepeat`), and each attempt is a case. Cases run in the background; poll the run for progress.

Each test is first checked against the version. A test is recorded as `invalid` straight away and not run when it stubs a tool the version does not have or one that runs inside the agent, stubs a tool chat tests cannot reach, has a `tool_called` check on a tool the version does not have or chat tests cannot reach, or has a `disposition_is` check on a disposition the version does not define. A `tool_not_called` check is not checked against the version. Invalid tests never fail a run, so a run where every test is invalid finishes as `passed`.

An agent has one active run at a time. A run still `queued` or `running` two hours after it started no longer counts.

## Request

**Base URL:** `https://api.tandemcx.ai`

**Authentication:** `Authorization: Bearer <token>` — A Tandem bearer token. Requests are scoped to the organization the token belongs to; no organization header is required.

### Path parameters

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `agentId` | string | Yes | The agent's unique ID. |

### Body (`application/json`) — required

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `version` | string | Yes | The version number to test, such as `0.3`. |
| `testIds` | array of string | No | Run only these tests. All of the agent's tests when omitted. Ids that match no test are ignored. |
| `triggeredBy` | enum: `user` \| `sparky` | No | — |

## Responses

### 202 — The run was created and its cases queued.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `runId` | string | No | — |

### 400 — `error` is `invalid_request` for a malformed body; `version_incomplete`, with a `message`, when the version is missing settings a session needs (such as a `systemPrompt`); `no_tests` when there is nothing to run; or `invalid_agentId` for a malformed path.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `error` | string | No | A stable machine-readable code. |
| `message` | string | No | A human-readable explanation, safe to show to an end user. Present on errors an operator can act on; browser clients display this field in preference to a generic fallback. |
| `limit` | integer | No | Present on some errors (e.g. `prompt_too_long`) that reject a value against a fixed bound: the bound itself. |
| `length` | integer | No | Present on some errors (e.g. `prompt_too_long`) that reject a value against a fixed bound: the measured size of the rejected value. |
| `reason` | string | No | Present on some errors (e.g. `invalid_avatar_image`) that have more than one cause: which one applied. |

### 401 — Missing, malformed, or expired bearer token.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `error` | string | No | A stable machine-readable code. |
| `message` | string | No | A human-readable explanation, safe to show to an end user. Present on errors an operator can act on; browser clients display this field in preference to a generic fallback. |
| `limit` | integer | No | Present on some errors (e.g. `prompt_too_long`) that reject a value against a fixed bound: the bound itself. |
| `length` | integer | No | Present on some errors (e.g. `prompt_too_long`) that reject a value against a fixed bound: the measured size of the rejected value. |
| `reason` | string | No | Present on some errors (e.g. `invalid_avatar_image`) that have more than one cause: which one applied. |

### 404 — `error` is `not_found`: the agent or the version does not exist.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `error` | string | No | A stable machine-readable code. |
| `message` | string | No | A human-readable explanation, safe to show to an end user. Present on errors an operator can act on; browser clients display this field in preference to a generic fallback. |
| `limit` | integer | No | Present on some errors (e.g. `prompt_too_long`) that reject a value against a fixed bound: the bound itself. |
| `length` | integer | No | Present on some errors (e.g. `prompt_too_long`) that reject a value against a fixed bound: the measured size of the rejected value. |
| `reason` | string | No | Present on some errors (e.g. `invalid_avatar_image`) that have more than one cause: which one applied. |

### 409 — `error` is `run_in_progress`, with a `message`: the agent already has an active run.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `error` | string | No | A stable machine-readable code. |
| `message` | string | No | A human-readable explanation, safe to show to an end user. Present on errors an operator can act on; browser clients display this field in preference to a generic fallback. |
| `limit` | integer | No | Present on some errors (e.g. `prompt_too_long`) that reject a value against a fixed bound: the bound itself. |
| `length` | integer | No | Present on some errors (e.g. `prompt_too_long`) that reject a value against a fixed bound: the measured size of the rejected value. |
| `reason` | string | No | Present on some errors (e.g. `invalid_avatar_image`) that have more than one cause: which one applied. |

### 503 — `error` is `tests_unavailable`: the cases could not be queued. A run that was created before the failure is marked `errored`. Retry.

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `error` | string | No | A stable machine-readable code. |
| `message` | string | No | A human-readable explanation, safe to show to an end user. Present on errors an operator can act on; browser clients display this field in preference to a generic fallback. |
| `limit` | integer | No | Present on some errors (e.g. `prompt_too_long`) that reject a value against a fixed bound: the bound itself. |
| `length` | integer | No | Present on some errors (e.g. `prompt_too_long`) that reject a value against a fixed bound: the measured size of the rejected value. |
| `reason` | string | No | Present on some errors (e.g. `invalid_avatar_image`) that have more than one cause: which one applied. |
