---
title: "Kiểm thử tác nhân AI từ đầu đến cuối (API)"
description: "Chạy mô phỏng một lần, lô kịch bản song song và bộ kiểm thử cổng phát hành qua API ThunderPhone để phát hiện lỗi hồi quy của tác nhân AI trước khi khách hàng gặp phải."
---

<Note>
  Bạn thích dùng dashboard hơn? Khả năng tương tự có trong **Mô phỏng**
  (`/dashboard/simulations`), bao gồm tạo kịch bản bằng AI — xem
  [Mô phỏng cuộc gọi](/vi/guides/simulate-a-call). Trang này trình bày cách
  thực hiện qua lập trình.
</Note>

Lặp lại cải tiến một tác nhân AI nghĩa là lặp lại cải tiến prompt, công cụ
và cách tác nhân xử lý các trường hợp biên. **API mô phỏng** thực hiện các
cuộc gọi thực đến tác nhân bằng prompt kịch bản do bạn cung cấp. Nhắm đến
một tác nhân sẽ tạo lượt chạy bot-đến-bot; nhắm đến một số điện thoại sẽ tạo
lượt chạy vòng lặp SIP. Mỗi lượt chạy tạo nhật ký cuộc gọi thực kèm
bản chép lời, chấm điểm và tính phí, để bạn thấy chính xác tác nhân
hoạt động thế nào và chi phí là bao nhiêu.

Dùng tính năng này để:

- Kiểm tra nhanh trước khi triển khai sau mỗi lần chỉnh sửa prompt
- Bộ kiểm thử hồi quy tích hợp vào CI (gắn webhook `test-call.completed`
  → làm bản dựng thất bại nếu điểm giảm)
- Kiểm thử áp lực giới hạn đồng thời

## Chạy một lần: lượt chạy đơn

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

Trường:

| Trường | Loại | Bắt buộc | Mô tả |
|-------|------|----------|-------------|
| `target_type` | chuỗi | có | `agent` hoặc `phone_number` |
| `target_id` | số nguyên | có | ID tác nhân AI (hoặc ID số điện thoại) |
| `direction` | chuỗi | không | `outbound` (mặc định; người gọi thử nghiệm thực hiện cuộc gọi) hoặc `inbound` (người gọi thử nghiệm trả lời) |
| `scenario_prompt` | chuỗi | không | Xác định nội dung bot thử nghiệm nói |
| `language` / `primary_language` | chuỗi | không | Ngôn ngữ cho người gọi thử nghiệm; mã không được hỗ trợ sẽ bị từ chối |
| `simulator_product` | chuỗi | không | `testing` (mặc định) hoặc `spark` cho người gọi mô phỏng giống người hơn, chẳng hạn kiểm thử tư vấn chuyển máy có thông báo trước |
| `consent_to_charge` | boolean | **có** | Phải là `true`. Ước tính tính phí cả tác nhân AI được chọn và người gọi mô phỏng theo mức phí cố định mỗi phút, cộng thêm mọi chặng viễn thông |
| `target_number` | chuỗi | không | Ghi đè E.164 cho phía từ xa; nếu không, số thử nghiệm của nền tảng sẽ được dùng |

`mode` là chỉ đọc và được suy ra từ `target_type`: `agent` tạo ra
`mode="bot"`, trong khi `phone_number` tạo ra `mode="sip"`.

Phản hồi là một [đối tượng lượt chạy mô phỏng](/api-reference/test-calls#test-call-run-object)
với `status="queued"`. Thăm dò cho đến khi `status` chuyển thành `completed` hoặc
`failed`; sau khi `call_id` được đặt, tải bản chép lời qua
[`GET /v1/calls/{call_id}/transcript`](/api-reference/calls#get-transcript).

## Lô: các kịch bản song song

Chạy đồng thời N kịch bản — hữu ích cho các bộ kiểm thử hồi quy
xử lý song song mọi trường hợp biên đã biết:

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

Phản hồi chứa danh sách `run_ids` gồm các ID lượt chạy con. Lấy trạng thái
lô:

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

`run_count` bị giới hạn ở 20; `stagger_seconds` giãn cách thời điểm khởi tạo
để tránh gây tải quá mức cho tác nhân (0–60 giây).

## Tích hợp vào CI

Tạo bộ thử nghiệm chặn phát hành trên trang **Mô phỏng**
(`/dashboard/simulations`) — chọn tác nhân AI, thêm kịch bản thủ công hoặc
nhấp vào **Tạo kịch bản bằng AI** để phác thảo từ prompt của tác nhân AI
(kèm tùy chọn rà soát trường hợp biên), rồi nhóm chúng thành một bộ thử nghiệm.
Một bộ thử nghiệm cố định kịch bản và tác nhân AI của nó, cùng với tỷ lệ đạt tối
thiểu và quy tắc tùy chọn không có lỗi nghiêm trọng. Các lần chạy đạt sẽ trở thành
baseline được chấp nhận; các chuyển đổi đạt→không đạt về sau được trả về dưới dạng hồi quy.

Sử dụng [key API của tổ chức](/api-reference/developer-api-keys) trong CI.
Script này kích hoạt bộ thử nghiệm, thăm dò cho đến khi chấm điểm và so sánh hoàn
tất, rồi thoát với mã khác 0 trừ khi kết luận là `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` trả về `202` cùng id của lần
chạy. `GET /v1/orgs/{org_id}/suites/{suite_id}/runs/{run_id}` trả về
`status`, `verdict`, `pass_rate`, `critical_failure_count` và danh sách
`regressions` của baseline. Cả hai endpoint đều liên kết tổ chức trong URL
với tổ chức của key API.

## Chạy bộ thử nghiệm theo lịch

Mở tab **Mô phỏng** của tác nhân AI, chọn **Bộ thử nghiệm chặn phát hành**, rồi tạo
hoặc chỉnh sửa một bộ thử nghiệm. Bật **Chạy theo lịch**, chọn **Tần suất** và
**Múi giờ**, sau đó đặt **Phút sau mỗi giờ**, **Giờ địa phương** hoặc **Ngày** như
hiển thị. Chọn **Lưu bộ thử nghiệm**. Bỏ chọn **Chạy theo lịch** sẽ xóa lịch
trong dashboard.

### Qua API

Gửi PATCH cho bộ thử nghiệm để thêm hoặc thay thế lịch của bộ. Xem [Bộ thử nghiệm
(chặn phát hành)](/api-reference/test-scenarios#suites-release-gates) để biết đối
tượng bộ thử nghiệm hoàn chỉnh và các endpoint.

```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` có thể là `hourly`, `daily` hoặc `weekly`. Sử dụng múi giờ IANA.
Lịch theo giờ sử dụng `minute`; lịch hằng ngày sử dụng `hour` và `minute`;
lịch hằng tuần cũng sử dụng `weekday`, trong đó Thứ Hai là `0` và Chủ Nhật là `6`.
Phản hồi của bộ thử nghiệm bao gồm `next_run_at` và `last_run_at`.

Thời gian tuân theo các thay đổi giờ mùa hè của múi giờ đã chọn. Các lần chạy theo
lịch xuất hiện trong lịch sử chạy của bộ thử nghiệm và sử dụng tác nhân AI, kịch
bản, tiêu chí và baseline được chấp nhận hiện tại. Mỗi cuộc gọi kiểm thử được tạo
sẽ phát ra `test-call.completed`; không có webhook hoàn tất ở cấp bộ thử nghiệm.
Các cuộc gọi theo lịch được tính phí theo cùng mức phí mô phỏng như các lần chạy
bộ thử nghiệm thủ công và ghi nhận `trigger: "schedule"` trên lần chạy bộ thử nghiệm.

Để tạm dừng lịch mà không thay đổi thời gian, hãy PATCH toàn bộ đối tượng lịch
hiện có với `"enabled": false`. `frequency` là bắt buộc; múi giờ và các trường
thời gian bị bỏ qua sẽ đặt lại về giá trị mặc định, vì vậy hãy bao gồm các giá trị
hiện có. Gửi `"schedule": null` để xóa lịch.

## Mẫu

### Kho hồi quy theo từng prompt

Duy trì một tệp JSON gồm các bộ `{name, scenario_prompt, expected_outcome}`.
Mỗi khi thay đổi prompt, hãy chạy toàn bộ tập dưới dạng một batch; so sánh bản
ghi hội thoại và điểm đánh giá với lần chạy trước.

### Kiểm thử smoke theo từng bản phát hành

Một batch gồm năm kịch bản thành công mà bạn chạy sau mỗi lần triển khai.
Nhạy cảm với độ trễ, vì vậy hãy giữ `stagger_seconds: 0`.

### Đo hiệu năng độ trễ

Chạy các kịch bản giống hệt nhau trên các gói sản phẩm khác nhau (`spark`,
`bolt`, `storm-base`). So sánh điểm `call.graded` và `duration_seconds`
từ từng nhật ký cuộc gọi tạo ra.

---

## Bước tiếp theo

<CardGroup cols={2}>
  <Card title="Tài liệu tham khảo về cuộc gọi kiểm thử" icon="flask" href="/api-reference/test-calls">
    Mọi tham số truy vấn, mã trạng thái và cấu trúc batch.
  </Card>
  <Card title="Chấm điểm bằng AI" icon="chart-line" href="/api-reference/calls#ai-call-grading">
    Tự động chấm điểm mỗi lần chạy kiểm thử để theo dõi chất lượng theo thời gian.
  </Card>
  <Card title="Báo cáo sự cố" icon="triangle-exclamation" href="/api-reference/issue-reports">
    Đánh dấu các kiểm thử cụ thể để con người xem xét.
  </Card>
  <Card title="Webhook test-call.completed" icon="bolt" href="/vi/webhooks/events">
    Truyền kết quả vào CI / Slack / PagerDuty của bạn.
  </Card>
</CardGroup>
