> ## Documentation Index
> Fetch the complete documentation index at: https://docs.thunderphone.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 端到端测试智能体（API）

> 通过测试通话 API 对您的智能体运行预设场景，以便在客户听到问题之前捕捉回归问题。

<Note>
  更倾向于使用控制台？**Simulations**
  （`/dashboard/simulations`）中提供相同功能，包括 AI 场景生成——请参阅
  [模拟通话](/zh/guides/simulate-a-call)。本页面介绍编程方式。
</Note>

迭代 AI 智能体意味着迭代其提示词、工具以及处理边界情况的方式。**test-calls API** 会使用您提供的场景提示词，对智能体发起真实的
（机器人对机器人或 SIP 回环）通话——每次运行都会生成包含转录、评分和计费信息的真实通话日志，因此您可以准确了解智能体的行为及其成本。

可用于：

* 每次编辑提示词后的部署前冒烟测试
* 接入 CI 的回归测试套件（挂接 `test-call.completed` Webhook
  → 如果评分下降则使构建失败）
* 对并发限制进行压力测试

## 单次运行：单个场景

```bash theme={null}
curl -X POST https://api.thunderphone.com/v1/test-calls \
  -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
  }'
```

字段：

| 字段                  | 类型      | 必填    | 说明                                  |
| ------------------- | ------- | ----- | ----------------------------------- |
| `target_type`       | string  | 是     | `agent` 或 `phone_number`            |
| `target_id`         | integer | 是     | 智能体 ID（或电话号码 ID）                    |
| `direction`         | string  | 是     | `outbound`（机器人拨打）或 `inbound`（机器人接听） |
| `scenario_prompt`   | string  | 否     | 决定测试机器人的说话内容                        |
| `mode`              | string  | 否     | `bot`（机器人对机器人，默认）或 `sip`（SIP 回环）    |
| `consent_to_charge` | boolean | **是** | 必须为 `true`。测试通话的费用为正常费率的 2 倍        |
| `target_number`     | string  | 否     | 覆盖机器人的主叫号码（E.164）                   |

响应为一个 [测试通话运行对象](/api-reference/test-calls#test-call-run-object)，
其 `status="queued"`。轮询直到 `status` 变为 `completed` 或
`failed`；设置 `call_id` 后，通过
[`GET /v1/calls/{call_id}/transcript`](/api-reference/calls#get-transcript) 加载转录内容。

## 批次：并行场景

并发运行 N 个场景——适用于并行覆盖所有已知边界情况的回归测试套件：

```bash theme={null}
curl -X POST https://api.thunderphone.com/v1/test-call-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
  }'
```

响应包含子运行 ID 的 `run_ids` 列表。获取批次
状态：

```bash theme={null}
curl https://api.thunderphone.com/v1/test-call-batches/{batch_id} \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY"
```

`run_count` 上限为 20；`stagger_seconds` 会错开启动时间，
以避免对智能体造成过高压力（0–60 秒）。

## 接入 CI

在 **模拟** 页面
（`/dashboard/simulations`）创建发布门禁套件——选择智能体，手动添加场景，或点击 **使用 AI 生成场景**，根据智能体的提示词起草场景（可选择额外进行边界情况检查），然后将其归入一个套件。
套件会固定其场景和智能体，以及最低通过率和可选的零严重失败规则。通过的运行会成为已接受的基线；后续从通过→失败的变化将作为回归返回。

在 CI 中使用[组织 API 密钥](/api-reference/developer-api-keys)。
此脚本会触发套件，轮询直到评分和比较完成，并且仅当判定结果为 `pass` 时才以零状态码退出：

```bash theme={null}
#!/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` 返回包含运行 ID 的 `202`。
`GET /v1/orgs/{org_id}/suites/{suite_id}/runs/{run_id}` 返回
`status`、`verdict`、`pass_rate`、`critical_failure_count` 以及基线
`regressions` 列表。两个端点都会将 URL 中的组织绑定到 API 密钥所属的组织。

## 模式

### 按提示词维护的回归语料库

维护一个包含 `{name, scenario_prompt, expected_outcome}`
元组的 JSON 文件。每次提示词变更时，将完整集合以批次形式运行；将转录文本和评分与上一次运行进行差异比较。

### 每次发布的冒烟测试

每次部署后运行一批包含五个正常路径场景的测试。该测试对延迟敏感，因此请保持 `stagger_seconds: 0`。

### 延迟基准测试

针对不同产品层级（`spark`、
`bolt`、`storm-base`）运行相同的场景。比较 `call.graded` 分数以及每个生成的通话日志中的
`duration_seconds`。

***

## 后续步骤

<CardGroup cols={2}>
  <Card title="测试通话参考" icon="flask" href="/api-reference/test-calls">
    所有查询参数、状态码和批次格式。
  </Card>

  <Card title="AI 评分" icon="chart-line" href="/api-reference/calls#ai-call-grading">
    自动为每次测试运行评分，以持续跟踪质量。
  </Card>

  <Card title="问题报告" icon="triangle-exclamation" href="/api-reference/issue-reports">
    标记特定测试以供人工审核。
  </Card>

  <Card title="test-call.completed Webhook" icon="bolt" href="/zh/webhooks/events">
    将结果流式传输到您的 CI / Slack / PagerDuty。
  </Card>
</CardGroup>
