---
title: "에이전트를 엔드투엔드로 테스트하기(API)"
description: "ThunderPhone API를 통해 단발성 시뮬레이션, 병렬 시나리오 배치, 릴리스 게이트 스위트를 실행하여 고객이 에이전트 회귀 문제를 듣기 전에 포착합니다."
---

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

AI 에이전트를 반복 개선하려면 프롬프트, 도구, 그리고 예외 상황을 처리하는 방식을
반복적으로 개선해야 합니다. **시뮬레이션 API**는 제공한 시나리오 프롬프트를 사용하여
에이전트를 대상으로 실제 통화를 실행합니다. 에이전트를 대상으로 지정하면 봇 간 실행이
생성되고, 전화번호를 대상으로 지정하면 SIP 루프백 실행이 생성됩니다. 모든 실행에서는
트랜스크립트, 채점, 청구 정보가 포함된 실제 통화 로그가 생성되므로 에이전트의 동작과
비용을 정확히 확인할 수 있습니다.

다음 용도로 사용하세요.

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

## 단일 실행: 한 번의 실행

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

필드:

| 필드 | 유형 | 필수 | 설명 |
|-------|------|----------|-------------|
| `target_type` | 문자열 | 예 | `agent` 또는 `phone_number` |
| `target_id` | 정수 | 예 | 에이전트 ID(또는 전화번호 ID) |
| `direction` | 문자열 | 아니요 | `outbound`(기본값, 테스트 발신자가 전화를 겁니다) 또는 `inbound`(테스트 발신자가 전화를 받습니다) |
| `scenario_prompt` | 문자열 | 아니요 | 테스트 봇이 말하는 내용을 결정합니다 |
| `language` / `primary_language` | 문자열 | 아니요 | 테스트 발신자의 언어입니다. 지원되지 않는 코드는 거부됩니다 |
| `simulator_product` | 문자열 | 아니요 | `testing`(기본값) 또는 웜 트랜스퍼 상담 테스트와 같이 더 사람 같은 시뮬레이션 발신자를 위한 `spark` |
| `consent_to_charge` | 불리언 | **예** | 반드시 `true`여야 합니다. 견적에는 선택한 에이전트와 시뮬레이션 발신자 모두에게 분당 고정 요금과 모든 전화 구간 요금이 청구됩니다 |
| `target_number` | 문자열 | 아니요 | 원격 측에 대한 E.164 재정의입니다. 지정하지 않으면 플랫폼 테스트 번호가 사용됩니다 |

`mode`는 읽기 전용이며 `target_type`에서 파생됩니다. `agent`는
`mode="bot"`을 생성하고, `phone_number`는 `mode="sip"`를 생성합니다.

응답은 `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
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
  }'
```

응답에는 하위 실행 ID로 구성된 `run_ids` 목록이 포함됩니다. 배치 상태를
조회하세요.

```bash
curl https://api.thunderphone.com/v1/simulations/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
#!/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 키의 조직에 연결합니다.

## 일정에 따라 스위트 실행하기

에이전트의 **시뮬레이션** 탭을 열고 **릴리스 게이트 스위트**를 선택한 다음 스위트를 생성하거나 편집합니다. **일정에 따라 실행**을 켜고 **빈도**와
**시간대**를 선택한 다음, 표시된 대로 **매시 분**, **현지 시간** 또는 **요일**을 설정합니다. **스위트 저장**을 선택합니다. **일정에 따라 실행**을 선택 해제하면 대시보드 일정이 제거됩니다.

### API 사용

스위트에 일정을 추가하거나 교체하려면 PATCH 요청을 보냅니다. 전체
스위트 객체와 엔드포인트는 [스위트(릴리스
게이트)](/api-reference/test-scenarios#suites-release-gates)를 참조하세요.

```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`에는 `hourly`, `daily` 또는 `weekly`를 사용할 수 있습니다. IANA 시간대를 사용하세요.
시간별 일정에는 `minute`를 사용하고, 일별 일정에는 `hour`와 `minute`를 사용합니다.
주별 일정에는 `weekday`도 사용하며, 월요일은 `0`, 일요일은 `6`입니다.
스위트 응답에는 `next_run_at` 및 `last_run_at`가 포함됩니다.

시간은 선택한 시간대의 일광 절약 시간 변경을 따릅니다. 예약된 실행은 스위트의 실행 기록에 표시되며 현재 에이전트, 시나리오, 기준 및 승인된 기준선을 사용합니다. 생성되는 각 테스트 통화는
`test-call.completed`를 발생시키며, 스위트 수준의 완료 웹훅은 없습니다. 예약된 통화는 수동 스위트 실행과 동일한 시뮬레이션 요율로 청구되며, 스위트 실행에
`trigger: "schedule"`을 기록합니다.

시간 설정을 변경하지 않고 일정을 일시 중지하려면 완전한 기존 일정 객체에 `"enabled": false`를 포함하여 PATCH 요청을 보냅니다. `frequency`는 필수이며, 시간대 및 시간 필드를 생략하면 기본값으로 재설정되므로 기존 값을 포함하세요. 일정을 제거하려면 `"schedule": null`을 전송합니다.

## 패턴

### 프롬프트별 회귀 코퍼스

`{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>
