---
title: "Testați un agent de la un capăt la altul (API)"
description: "Rulați simulări unice, loturi paralele de scenarii și suite de validare a lansării prin API-ul ThunderPhone, astfel încât regresiile agentului să fie detectate înainte ca clienții să le audă."
---

<Note>
  Preferați tabloul de bord? Aceeași funcționalitate este disponibilă în **Simulări**
  (`/dashboard/simulations`), inclusiv generarea de scenarii cu AI — consultați
  [Simulați un apel](/ro/guides/simulate-a-call). Această pagină prezintă
  abordarea programatică.
</Note>

Iterarea unui agent AI înseamnă iterarea promptului, a instrumentelor sale
și a modului în care gestionează cazurile-limită. **API-ul de simulări** execută apeluri reale
către un agent folosind un prompt de scenariu furnizat de dumneavoastră. Direcționarea
către un agent creează o execuție bot-la-bot; direcționarea către un număr de telefon creează o
execuție SIP loopback. Fiecare execuție produce un jurnal de apel real, cu
transcriere, evaluare și facturare, astfel încât vedeți exact cum se comportă agentul
și cât costă.

Utilizați-l pentru:

- Teste rapide înainte de implementare, după fiecare modificare a promptului
- Suite de regresie conectate la CI (conectați webhookul `test-call.completed`
  → eșuați compilarea dacă scorul scade)
- Testarea la stres a limitelor de concurență

## Execuție unică: o singură rulare

```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
  }'
```

Câmpuri:

| Câmp | Tip | Obligatoriu | Descriere |
|-------|------|----------|-------------|
| `target_type` | șir | da | `agent` sau `phone_number` |
| `target_id` | număr întreg | da | ID-ul agentului (sau ID-ul numărului de telefon) |
| `direction` | șir | nu | `outbound` (implicit; apelantul de test inițiază apelul) sau `inbound` (apelantul de test răspunde) |
| `scenario_prompt` | șir | nu | Stabilește ce spune botul de test |
| `language` / `primary_language` | șir | nu | Limba apelantului de test; codurile neacceptate sunt respinse |
| `simulator_product` | șir | nu | `testing` (implicit) sau `spark` pentru un apelant simulat mai asemănător unui om, cum ar fi pentru teste de consultare înainte de transfer asistat |
| `consent_to_charge` | boolean | **da** | Trebuie să fie `true`. Estimarea facturează atât agentul selectat, cât și apelantul simulat la un tarif fix pe minut, plus orice segment de telefonie |
| `target_number` | șir | nu | Suprascriere E.164 pentru partea la distanță; în caz contrar, se utilizează numărul de test al platformei |

`mode` este numai pentru citire și este derivat din `target_type`: `agent` produce
`mode="bot"`, iar `phone_number` produce `mode="sip"`.

Răspunsul este un [obiect de rulare a simulării](/api-reference/test-calls#test-call-run-object)
cu `status="queued"`. Interogați până când `status` devine `completed` sau
`failed`; după ce este setat `call_id`, încărcați transcrierea prin
[`GET /v1/calls/{call_id}/transcript`](/api-reference/calls#get-transcript).

## Loturi: scenarii paralele

Executați N scenarii simultan — util pentru suitele de regresie care
acoperă în paralel fiecare caz-limită cunoscut:

```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
  }'
```

Răspunsul conține o listă `run_ids` cu ID-urile rulărilor copil. Preluați
starea lotului:

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

`run_count` este limitat la 20; `stagger_seconds` distanțează inițierile
pentru a evita suprasolicitarea agentului (0–60 s).

## Integrați-l în CI

Creați o suită de poartă de lansare în pagina **Simulări**
(`/dashboard/simulations`) — alegeți agentul, adăugați scenarii manual sau
faceți clic pe **Generați scenarii cu AI** pentru a le schița pe baza
promptului agentului (cu o verificare opțională pentru cazuri-limită) și
grupați-le într-o suită. O suită fixează scenariile și agentul, precum și o
rată minimă de reușită și o regulă opțională de zero eșecuri critice.
Rulările reușite devin referința acceptată; tranzițiile ulterioare de la
reușită la eșec sunt raportate ca regresii.

Utilizați o [cheie API de organizație](/api-reference/developer-api-keys) în CI.
Acest script declanșează suita, interoghează până când evaluarea și comparația
sunt finalizate și se încheie cu un cod diferit de zero dacă verdictul nu este
`pass`:

```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` returnează `202` cu ID-ul
rulării. `GET /v1/orgs/{org_id}/suites/{suite_id}/runs/{run_id}` returnează
`status`, `verdict`, `pass_rate`, `critical_failure_count` și lista de
`regressions` față de referință. Ambele endpointuri asociază organizația din
URL cu organizația cheii API.

## Rulați o suită conform unui program

Deschideți fila **Simulați** a agentului, selectați **Suite de porți de
lansare** și creați sau editați o suită. Activați **Rulați conform unui
program**, alegeți **Frecvență** și **Fus orar**, apoi setați **Minut după
oră**, **Ora locală** sau **Ziua**, după cum este afișat. Selectați
**Salvați suita**. Debifarea opțiunii **Rulați conform unui program** elimină
programarea din tabloul de bord.

### Prin API

Efectuați PATCH asupra suitei pentru a adăuga sau înlocui programarea. Consultați
[Suite (porți de lansare)](/api-reference/test-scenarios#suites-release-gates)
pentru obiectul complet al suitei și endpointuri.

```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` poate fi `hourly`, `daily` sau `weekly`. Utilizați un fus orar
IANA. Programările orare utilizează `minute`; programările zilnice utilizează
`hour` și `minute`; programările săptămânale utilizează și `weekday`, unde
luni este `0` și duminică este `6`. Răspunsul suitei include `next_run_at` și
`last_run_at`.

Orele urmează schimbările pentru ora de vară ale fusului orar selectat.
Rulările programate apar în istoricul rulărilor suitei și utilizează agentul,
scenariile, criteriile și referința acceptată curente. Fiecare apel de test
generat emite `test-call.completed`; nu există un webhook de finalizare la
nivel de suită. Apelurile programate sunt facturate la aceeași rată de
simulare ca rulările manuale ale suitei și înregistrează `trigger: "schedule"`
pentru rularea suitei.

Pentru a pune pe pauză o programare fără a-i modifica intervalul, efectuați
PATCH cu obiectul complet al programării existente și `"enabled": false`.
`frequency` este obligatoriu; fusul orar și câmpurile de timp omise sunt
resetate la valorile implicite, așadar includeți valorile existente. Trimiteți
`"schedule": null` pentru a elimina programarea.

## Modele

### Corpus de regresie pentru fiecare prompt

Mențineți un fișier JSON cu tupluri `{name, scenario_prompt, expected_outcome}`. La fiecare modificare a promptului, rulați întregul set ca lot; comparați transcrierile și evaluările cu rularea anterioară.

### Test de fum pentru fiecare versiune

Un singur lot de cinci scenarii standard, pe care îl rulați după fiecare implementare. Sensibil la latență, deci păstrați `stagger_seconds: 0`.

### Benchmarking pentru latență

Rulați scenarii identice pentru diferite niveluri de produs (`spark`, `bolt`, `storm-base`). Comparați scorurile `call.graded` și valoarea `duration_seconds` din fiecare jurnal de apel rezultat.

---

## Pașii următori

<CardGroup cols={2}>
  <Card title="Referință pentru apeluri de test" icon="flask" href="/api-reference/test-calls">
    Fiecare parametru de interogare, cod de stare și structură de lot.
  </Card>
  <Card title="Evaluare AI" icon="chart-line" href="/api-reference/calls#ai-call-grading">
    Evaluați automat fiecare rulare de test pentru a urmări calitatea în timp.
  </Card>
  <Card title="Rapoarte de probleme" icon="triangle-exclamation" href="/api-reference/issue-reports">
    Marcați teste specifice pentru revizuire umană.
  </Card>
  <Card title="Webhook test-call.completed" icon="bolt" href="/ro/webhooks/events">
    Transmiteți rezultatele în CI / Slack / PagerDuty.
  </Card>
</CardGroup>
