---
title: "Uji agen secara menyeluruh (API)"
description: "Jalankan simulasi sekali jalan, batch skenario paralel, dan rangkaian gerbang rilis melalui API ThunderPhone agar regresi agen terdeteksi sebelum didengar oleh pelanggan."
---

<Note>
  Lebih memilih dashboard? Kemampuan yang sama tersedia di **Simulations**
  (`/dashboard/simulations`), termasuk pembuatan skenario AI — lihat
  [Mensimulasikan panggilan](/id/guides/simulate-a-call). Halaman ini membahas
  jalur terprogram.
</Note>

Melakukan iterasi pada agen AI berarti melakukan iterasi pada Prompt, alatnya,
dan cara agen menangani kasus tepi. **API simulasi** menjalankan panggilan nyata
terhadap agen menggunakan Prompt skenario yang Anda berikan. Menargetkan
agen membuat proses bot-ke-bot; menargetkan nomor telepon membuat proses
loopback SIP. Setiap proses menghasilkan log panggilan nyata dengan
transkrip, penilaian, dan penagihan, sehingga Anda dapat melihat secara tepat
cara agen berperilaku dan biayanya.

Gunakan untuk:

- Uji smoke pra-deploy setelah setiap pengeditan Prompt
- Suite regresi yang terhubung ke CI (hubungkan webhook `test-call.completed`
  → gagalkan build jika skor menurun)
- Pengujian stres batas konkurensi

## Sekali jalan: satu proses

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

Kolom:

| Kolom | Tipe | Wajib | Deskripsi |
|-------|------|----------|-------------|
| `target_type` | string | ya | `agent` atau `phone_number` |
| `target_id` | integer | ya | ID agen (atau ID nomor telepon) |
| `direction` | string | tidak | `outbound` (default; penelepon pengujian melakukan panggilan) atau `inbound` (penelepon pengujian menjawab) |
| `scenario_prompt` | string | tidak | Menentukan apa yang dikatakan bot pengujian |
| `language` / `primary_language` | string | tidak | Bahasa untuk penelepon pengujian; kode yang tidak didukung akan ditolak |
| `simulator_product` | string | tidak | `testing` (default) atau `spark` untuk penelepon simulasi yang lebih mirip manusia, seperti pengujian konsultasi transfer hangat |
| `consent_to_charge` | boolean | **ya** | Harus berupa `true`. Estimasi menagihkan agen yang dipilih dan penelepon simulasi dengan tarif tetap per menit, ditambah biaya sambungan telepon |
| `target_number` | string | tidak | Penggantian E.164 untuk sisi jarak jauh; jika tidak, nomor pengujian Platform digunakan |

`mode` bersifat hanya baca dan diturunkan dari `target_type`: `agent` menghasilkan
`mode="bot"`, sedangkan `phone_number` menghasilkan `mode="sip"`.

Responsnya adalah [objek proses simulasi](/api-reference/test-calls#test-call-run-object)
dengan `status="queued"`. Lakukan polling hingga `status` menjadi `completed` atau
`failed`; setelah `call_id` ditetapkan, muat transkrip melalui
[`GET /v1/calls/{call_id}/transcript`](/api-reference/calls#get-transcript).

## Batch: skenario paralel

Jalankan N skenario secara bersamaan — berguna untuk suite regresi yang
menangani setiap kasus tepi yang diketahui secara paralel:

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

Respons berisi daftar `run_ids` dari ID proses turunan. Ambil Status batch:

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

`run_count` dibatasi hingga 20; `stagger_seconds` memberi jarak waktu pada
pembuatan proses untuk menghindari membebani agen secara berlebihan (0–60 dtk).

## Hubungkan ke CI

Buat suite gerbang rilis di halaman **Simulasi**
(`/dashboard/simulations`) — pilih agen, tambahkan skenario secara manual atau
klik **Buat skenario dengan AI** untuk menyusunnya dari Prompt agen
(dengan pemeriksaan kasus tepi opsional), lalu kelompokkan ke dalam suite.
Suite menetapkan skenario dan agennya, serta tingkat kelulusan minimum dan
aturan opsional tanpa kegagalan kritis. Proses yang lulus menjadi baseline
yang diterima; transisi lulus→gagal berikutnya dikembalikan sebagai regresi.

Gunakan [kunci API organisasi](/api-reference/developer-api-keys) di CI.
Skrip ini memicu suite, melakukan polling hingga penilaian dan perbandingan
selesai, lalu keluar dengan nilai bukan nol kecuali putusannya adalah `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` mengembalikan `202` dengan
id proses. `GET /v1/orgs/{org_id}/suites/{suite_id}/runs/{run_id}` mengembalikan
`status`, `verdict`, `pass_rate`, `critical_failure_count`, serta daftar
`regressions` baseline. Kedua endpoint mengikat organisasi pada URL ke
organisasi milik kunci API.

## Jalankan suite sesuai jadwal

Buka tab **Simulasikan** agen, pilih **Suite gerbang rilis**, lalu buat atau
edit suite. Aktifkan **Jalankan sesuai jadwal**, pilih **Frekuensi** dan
**Zona waktu**, kemudian atur **Menit setelah jam**, **Waktu lokal**, atau
**Hari** seperti yang ditampilkan. Pilih **Simpan suite**. Menghapus centang
**Jalankan sesuai jadwal** akan menghapus jadwal dashboard.

### Melalui API

PATCH suite untuk menambahkan atau mengganti jadwalnya. Lihat [Suite (gerbang
rilis)](/api-reference/test-scenarios#suites-release-gates) untuk objek suite
dan endpoint lengkap.

```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` dapat berupa `hourly`, `daily`, atau `weekly`. Gunakan zona waktu
IANA. Jadwal per jam menggunakan `minute`; jadwal harian menggunakan `hour`
dan `minute`; jadwal mingguan juga menggunakan `weekday`, dengan Senin adalah
`0` dan Minggu adalah `6`. Respons suite mencakup `next_run_at` dan
`last_run_at`.

Waktu mengikuti perubahan waktu musim panas pada zona waktu yang dipilih.
Proses terjadwal muncul dalam riwayat proses suite dan menggunakan agen,
skenario, kriteria, serta baseline yang diterima saat ini. Setiap panggilan
pengujian yang dibuat memancarkan `test-call.completed`; tidak ada webhook
penyelesaian tingkat suite. Panggilan terjadwal ditagihkan dengan tarif
simulasi yang sama seperti proses suite manual dan mencatat
`trigger: "schedule"` pada proses suite.

Untuk menjeda jadwal tanpa mengubah waktunya, PATCH seluruh objek jadwal yang
ada dengan `"enabled": false`. `frequency` wajib diisi; zona waktu dan kolom
waktu yang dihilangkan akan diatur ulang ke nilai default, jadi sertakan nilai
yang ada. Kirim `"schedule": null` untuk menghapus jadwal.

## Pola

### Korpus regresi per Prompt

Kelola file JSON berisi tuple `{name, scenario_prompt, expected_outcome}`.
Pada setiap perubahan Prompt, jalankan seluruh rangkaian sebagai batch; bandingkan
transkrip dan nilai dengan hasil sebelumnya.

### Uji smoke per rilis

Satu batch berisi lima skenario jalur sukses yang Anda jalankan setelah setiap
deploy. Sensitif terhadap latensi, jadi pertahankan `stagger_seconds: 0`.

### Benchmarking latensi

Jalankan skenario identik pada berbagai tingkatan produk (`spark`,
`bolt`, `storm-base`). Bandingkan skor `call.graded` dan
`duration_seconds` dari setiap log panggilan yang dihasilkan.

---

## Langkah berikutnya

<CardGroup cols={2}>
  <Card title="Referensi panggilan uji" icon="flask" href="/api-reference/test-calls">
    Setiap parameter kueri, kode status, dan struktur batch.
  </Card>
  <Card title="Penilaian AI" icon="chart-line" href="/api-reference/calls#ai-call-grading">
    Beri skor otomatis pada setiap uji untuk melacak kualitas dari waktu ke waktu.
  </Card>
  <Card title="Laporan masalah" icon="triangle-exclamation" href="/api-reference/issue-reports">
    Tandai uji tertentu untuk ditinjau manusia.
  </Card>
  <Card title="Webhook test-call.completed" icon="bolt" href="/id/webhooks/events">
    Alirkan hasil ke CI / Slack / PagerDuty Anda.
  </Card>
</CardGroup>
