> ## 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)

> test-calls API를 사용하여 미리 정의된 시나리오를 에이전트로 실행하고, 고객이 문제를 듣기 전에 회귀를 포착합니다.

<Note>
  대시보드를 선호하시나요? AI 시나리오 생성 기능을 포함한 동일한 기능은 **시뮬레이션**
  (`/dashboard/simulations`)에서 사용할 수 있습니다. [통화 시뮬레이션](/ko/guides/simulate-a-call)을
  참조하세요. 이 페이지에서는 프로그래밍 방식의 경로를 다룹니다.
</Note>

AI 에이전트를 개선하려면 프롬프트, 도구, 그리고 예외 상황을 처리하는 방식을 반복적으로 개선해야 합니다. **test-calls API**는 제공한 시나리오 프롬프트를 사용하여 에이전트에 대해 실제 (봇 간 또는 SIP 루프백) 통화를 실행합니다. 모든 실행은 대화 내용, 채점, 청구가 포함된 실제 통화 로그를 생성하므로 에이전트의 정확한 동작과 비용을 확인할 수 있습니다.

다음 용도로 사용합니다.

* 프롬프트를 수정할 때마다 배포 전 스모크 테스트
* CI에 연결된 회귀 테스트 모음 (`test-call.completed` 웹훅 연결
  → 점수가 하락하면 빌드 실패)
* 동시성 제한 스트레스 테스트

## 단일 실행: 한 번 실행

```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  | 아니요   | 봇의 발신자 ID(E.164)를 재정의합니다                  |

응답은 `status="queued"` 상태의 [테스트 통화 실행 객체](/api-reference/test-calls#test-call-run-object)입니다. `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로 시나리오 생성**을 클릭하여 에이전트의 프롬프트를 기반으로 시나리오 초안을 생성합니다(선택적으로 엣지 케이스 검사 포함). 그런 다음 시나리오를 스위트로 그룹화합니다.
스위트는 시나리오와 에이전트, 최소 통과율, 선택적인 치명적 실패 0건 규칙을 고정합니다. 통과한 실행은 승인된 기준선이 되며, 이후 통과→실패 전환은 회귀로 반환됩니다.

CI에서는 [조직 API 키](/api-reference/developer-api-keys)를 사용하세요.
이 스크립트는 스위트를 트리거하고, 채점 및 비교가 완료될 때까지 폴링하며, 판정이 `pass`가 아닌 경우 0이 아닌 종료 코드로 종료합니다.

```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 파일을 유지하세요. 프롬프트가 변경될 때마다 전체 세트를 배치로 실행하고, 이전 실행과 비교하여 트랜스크립트와 등급의 차이를 확인하세요.

### 릴리스별 스모크 테스트

모든 배포 후 실행하는 정상 경로 시나리오 5개로 구성된 단일 배치입니다. 지연 시간에 민감하므로 `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 웹훅" icon="bolt" href="/ko/webhooks/events">
    결과를 CI / Slack / PagerDuty로 스트리밍하세요.
  </Card>
</CardGroup>
