---
title: "Test een agent end-to-end (API)"
description: "Voer one-shot-simulaties, parallelle scenariobatches en release-gatesuites uit via de ThunderPhone API, zodat regressies in agents worden opgespoord voordat klanten ze horen."
---

<Note>
  Geef je de voorkeur aan het dashboard? Dezelfde functionaliteit staat in **Simulaties**
  (`/dashboard/simulations`), inclusief AI-scenariogeneratie — zie
  [Een oproep simuleren](/nl/guides/simulate-a-call). Deze pagina behandelt de
  programmatische aanpak.
</Note>

Een AI-agent itereren betekent itereren op de prompt, de tools
en de manier waarop deze randgevallen afhandelt. De **simulatie-API** voert echte
oproepen naar een agent uit met een scenarioprompt die je opgeeft. Als je
een agent target, ontstaat er een bot-naar-bot-uitvoering; als je een telefoonnummer target, ontstaat een
SIP-loopback-uitvoering. Elke uitvoering produceert een echt oproeplogboek met
transcript, beoordeling en facturering, zodat je precies ziet hoe de agent
zich gedraagt en wat dit kost.

Gebruik deze voor:

- Rooktests vóór implementatie na elke promptwijziging
- Regressiesuites gekoppeld aan CI (koppel de webhook `test-call.completed`
  → laat de build mislukken als de score daalt)
- Stresstests van gelijktijdigheidslimieten

## Eenmalig: enkele uitvoering

```bash
curl -X POST https://api.thunderphone.com/v1/simulations \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "target_type":     "agent",
    "target_id":       12,
    "direction":       "outbound",
    "scenario_prompt": "You are a polite caller asking about refund policy for order 12345.",
    "consent_to_charge": true
  }'
```

Velden:

| Veld | Type | Vereist | Beschrijving |
|-------|------|----------|-------------|
| `target_type` | string | ja | `agent` of `phone_number` |
| `target_id` | integer | ja | De agent-ID (of telefoonnummer-ID) |
| `direction` | string | nee | `outbound` (standaard; testbeller belt) of `inbound` (testbeller neemt op) |
| `scenario_prompt` | string | nee | Bepaalt wat de testbot zegt |
| `language` / `primary_language` | string | nee | Taal voor de testbeller; niet-ondersteunde codes worden geweigerd |
| `simulator_product` | string | nee | `testing` (standaard) of `spark` voor een meer mensachtige gesimuleerde beller, zoals tests voor overleg bij warme doorverbinding |
| `consent_to_charge` | boolean | **ja** | Moet `true` zijn. De schatting brengt zowel de geselecteerde agent als de gesimuleerde beller een vast tarief per minuut in rekening, plus eventuele telecommunicatieverbindingen |
| `target_number` | string | nee | E.164-overschrijving voor de externe zijde; anders wordt het testnummer van het platform gebruikt |

`mode` is alleen-lezen en wordt afgeleid van `target_type`: `agent` produceert
`mode="bot"`, terwijl `phone_number` `mode="sip"` produceert.

Het antwoord is een [simulatie-uitvoeringsobject](/api-reference/test-calls#test-call-run-object)
met `status="queued"`. Vraag de status op totdat `status` `completed` of
`failed` wordt; zodra `call_id` is ingesteld, laad je het transcript via
[`GET /v1/calls/{call_id}/transcript`](/api-reference/calls#get-transcript).

## Batches: parallelle scenario's

Voer N scenario's gelijktijdig uit — handig voor regressiesuites die
elk bekend randgeval parallel testen:

```bash
curl -X POST https://api.thunderphone.com/v1/simulations/batches \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "target_type":     "agent",
    "target_id":       12,
    "direction":       "outbound",
    "run_count":       5,
    "stagger_seconds": 2,
    "scenario_prompts": [
      "Ask about refund policy.",
      "Ask for hours of operation.",
      "Complain about a delayed shipment.",
      "Ask to speak with a human.",
      "Ask an unrelated trivia question."
    ],
    "consent_to_charge": true
  }'
```

Het antwoord bevat een lijst met `run_ids` van onderliggende uitvoerings-ID's. Vraag de batchstatus
op:

```bash
curl https://api.thunderphone.com/v1/simulations/batches/{batch_id} \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY"
```

`run_count` is beperkt tot 20; `stagger_seconds` spreidt het starten
om overbelasting van de agent te voorkomen (0–60 s).

## Koppel het aan CI

Maak een releasegate-suite op de pagina **Simulaties**
(`/dashboard/simulations`) — kies de agent, voeg scenario's handmatig toe of
klik op **Scenario's genereren met AI** om ze op te stellen vanuit de prompt
van de agent (met een optionele controle op randgevallen), en groepeer ze in
een suite. Een suite legt de scenario's en agent vast, samen met een minimale
slagingsgraad en een optionele regel zonder kritieke fouten. Geslaagde runs
worden de geaccepteerde basislijn; latere overgangen van slagen naar falen
worden als regressies geretourneerd.

Gebruik een [organisatie-API-sleutel](/api-reference/developer-api-keys) in CI.
Dit script start de suite, controleert totdat de beoordeling en vergelijking
zijn voltooid, en sluit af met een andere status dan nul tenzij het oordeel
`pass` is:

```bash
#!/usr/bin/env bash
set -euo pipefail

: "${THUNDERPHONE_API_KEY:?Set THUNDERPHONE_API_KEY}"
: "${THUNDERPHONE_ORG_ID:?Set THUNDERPHONE_ORG_ID}"
: "${THUNDERPHONE_SUITE_ID:?Set THUNDERPHONE_SUITE_ID}"

base="https://api.thunderphone.com/v1/orgs/${THUNDERPHONE_ORG_ID}/suites/${THUNDERPHONE_SUITE_ID}"
auth="Authorization: Bearer ${THUNDERPHONE_API_KEY}"

run_id="$(curl --fail --silent --show-error -X POST "${base}/run" \
  -H "$auth" -H "Content-Type: application/json" -d '{}' | jq -r '.id')"

deadline=$((SECONDS + 1800))
while (( SECONDS < deadline )); do
  result="$(curl --fail --silent --show-error \
    "${base}/runs/${run_id}" -H "$auth")"
  status="$(jq -r '.status' <<<"$result")"
  if [[ "$status" == "completed" ]]; then
    jq . <<<"$result"
    [[ "$(jq -r '.verdict' <<<"$result")" == "pass" ]]
    exit
  fi
  sleep 10
done

echo "ThunderPhone suite timed out" >&2
exit 1
```

`POST /v1/orgs/{org_id}/suites/{suite_id}/run` retourneert `202` met de
run-ID. `GET /v1/orgs/{org_id}/suites/{suite_id}/runs/{run_id}` retourneert
`status`, `verdict`, `pass_rate`, `critical_failure_count` en de
`regressions`-lijst van de basislijn. Beide endpoints koppelen de organisatie
in de URL aan de organisatie van de API-sleutel.

## Een suite volgens schema uitvoeren

Open het tabblad **Simuleren** van de agent, selecteer **Releasegate-suites** en
maak of bewerk een suite. Schakel **Volgens schema uitvoeren** in, kies
**Frequentie** en **Tijdzone**, en stel vervolgens **Minuut na het uur**,
**Lokale tijd** of **Dag** in zoals weergegeven. Selecteer **Suite opslaan**.
Door **Volgens schema uitvoeren** uit te schakelen, verwijder je het schema in
het dashboard.

### Via API

PATCH de suite om het schema toe te voegen of te vervangen. Zie [Suites
(releasegates)](/api-reference/test-scenarios#suites-release-gates) voor het
volledige suite-object en de endpoints.

```bash
curl -X PATCH https://api.thunderphone.com/v1/suites/{suite_id} \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "schedule": {
      "enabled": true,
      "frequency": "daily",
      "timezone": "America/Chicago",
      "hour": 6,
      "minute": 30
    }
  }'
```

`frequency` kan `hourly`, `daily` of `weekly` zijn. Gebruik een IANA-tijdzone.
Uurroosters gebruiken `minute`; dagroosters gebruiken `hour` en `minute`;
weekroosters gebruiken ook `weekday`, waarbij maandag `0` is en zondag `6`.
De suite-respons bevat `next_run_at` en `last_run_at`.

Tijden volgen de zomertijdwijzigingen van de geselecteerde tijdzone. Geplande
runs verschijnen in de rungeschiedenis van de suite en gebruiken de huidige
agent, scenario's, criteria en geaccepteerde basislijn. Elke gegenereerde
testoproep verstuurt `test-call.completed`; er is geen webhook voor voltooiing
op suite-niveau. Geplande oproepen worden gefactureerd tegen hetzelfde
simulatietarief als handmatige suite-runs en registreren
`trigger: "schedule"` voor de suite-run.

Om een schema te pauzeren zonder de tijdinstelling te wijzigen, PATCH je het
volledige bestaande schema-object met `"enabled": false`. `frequency` is
verplicht; weggelaten tijdzone- en tijdvelden worden teruggezet naar de
standaardwaarden, dus neem de bestaande waarden op. Stuur `"schedule": null`
om het schema te verwijderen.

## Patronen

### Regressiecorpus per prompt

Onderhoud een JSON-bestand met tuples van `{name, scenario_prompt, expected_outcome}`.
Voer bij elke promptwijziging de volledige set als batch uit; vergelijk de
transcripten en beoordelingen met de vorige uitvoering.

### Smoketest per release

Eén batch met vijf happy-pathscenario's die je na elke
deploy uitvoert. Latentiegevoelig, dus houd `stagger_seconds: 0` aan.

### Latentiebenchmarking

Voer identieke scenario's uit voor verschillende productpakketten (`spark`,
`bolt`, `storm-base`). Vergelijk de `call.graded`-scores en de
`duration_seconds` van elk resulterend oproeplogboek.

---

## Volgende stappen

<CardGroup cols={2}>
  <Card title="Referentie voor testoproepen" icon="flask" href="/api-reference/test-calls">
    Elke queryparameter, statuscode en batchvorm.
  </Card>
  <Card title="AI-beoordeling" icon="chart-line" href="/api-reference/calls#ai-call-grading">
    Beoordeel elke testrun automatisch om de kwaliteit in de loop van de tijd te volgen.
  </Card>
  <Card title="Probleemrapporten" icon="triangle-exclamation" href="/api-reference/issue-reports">
    Markeer specifieke tests voor menselijke beoordeling.
  </Card>
  <Card title="test-call.completed-webhook" icon="bolt" href="/nl/webhooks/events">
    Stream resultaten naar je CI / Slack / PagerDuty.
  </Card>
</CardGroup>
