ThunderPhone 2.0을 출시했습니다.별도 문의 없이 분당 2¢부터.출시 소식 보기

Developer cookbook

도구 통합(API) 구축

에이전트가 대화 중에 API를 호출하도록 설정합니다. 데이터베이스를 검색하고, 티켓을 생성하고, 주문을 조회할 수 있습니다.

도구 통합은 에이전트가 통화 중에 호출할 수 있는 재사용 가능한 HTTP 엔드포인트입니다. 도구의 JSON 스키마 설명과 엔드포인트 URL을 ThunderPhone에 제공하면, 에이전트는 대화 내용을 바탕으로 호출 시점을 결정하고 ThunderPhone은 자체 서버에서 외부 HTTP 요청을 수행한 뒤 응답을 에이전트에 반환합니다.

이 가이드에서는 날씨 조회 도구를 처음부터 끝까지 구축합니다.

도구의 구성 요소

두 가지 구성 요소가 있습니다.

  1. 스키마 — 도구의 기능과 인수로 받는 값을 LLM에 알려 주는 OpenAI 스타일 함수 정의 ({type: "function", function: {name, description, parameters}})입니다.
  2. 엔드포인트 — LLM이 도구 사용을 결정했을 때 ThunderPhone 서버가 호출하는 URL입니다. 요청은 LLM이 선택한 인수를 본문으로 포함하는 JSON POST 요청입니다.

1. 저장 전략 선택

에이전트에 인라인으로 추가

일회성 도구를 에이전트의 tools 배열에 연결합니다. 간단하지만 재사용할 수 없습니다.

저장된 통합

도구를 재사용 가능한 통합으로 저장하고 여러 에이전트에서 연결합니다. 두 번 이상 사용하는 모든 항목에 권장됩니다.

이 가이드에서는 저장된 통합 경로를 사용합니다.

2. 통합 생성

curl -X POST https://api.thunderphone.com/v1/integrations \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "display_name": "Weather API",
    "spec": {
      "type": "function",
      "function": {
        "name": "get_weather",
        "description": "Return the current weather for a zip code.",
        "parameters": {
          "type": "object",
          "properties": {
            "zip": { "type": "string", "description": "5-digit US ZIP code" }
          },
          "required": ["zip"]
        }
      }
    },
    "endpoint_url":    "https://api.example.com/weather",
    "endpoint_method": "GET",
    "headers": [
      { "key": "X-Api-Key", "value": "your-provider-key" }
    ]
  }'

반환된 id(UUID)를 저장합니다.

3. 샌드박스에서 엔드포인트 테스트

통합을 에이전트에 연결하기 전에 ThunderPhone 서버에서 서명된 요청을 보내 연결을 확인합니다.

curl -X POST https://api.thunderphone.com/v1/integrations/test-request \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url":    "https://api.example.com/weather?zip=94110",
    "method": "GET",
    "headers": { "X-Api-Key": "your-provider-key" }
  }'
Response
{
  "ok": true,
  "status": 200,
  "elapsed_ms": 187,
  "response_headers": { "content-type": "application/json" },
  "response_preview": "{\"temperature_f\": 64, ...}"
}

이 테스트는 ThunderPhone의 SSRF 보호 기능도 강화합니다. localhost 또는 비공개 IP 범위에 대한 요청은 400 code=url_not_allowed를 반환합니다.

4. 통합을 에이전트에 연결

에이전트를 생성하거나 업데이트할 때 integration_ids를 통해 연결합니다.

curl -X PATCH https://api.thunderphone.com/v1/agents/12 \
  -H "Authorization: Bearer sk_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "integration_ids": ["f9b5a1a4-..."]
  }'

하나의 에이전트에 여러 통합을 연결할 수 있습니다. 에이전트의 프롬프트에서 이름으로 참조할 수 있습니다. 예: "발신자가 날씨 상태를 물어보면 get_weather를 사용합니다." 또는 스키마 설명을 통해 암시적으로 탐색하도록 할 수 있습니다.

5. 엔드포인트 구현

에이전트가 도구를 호출하면 ThunderPhone이 endpoint_url로 서명된 POST 요청을 전송합니다.

POST /weather HTTP/1.1
Host: api.example.com
X-Api-Key: your-provider-key
X-ThunderPhone-Signature: <HMAC-SHA256 hex>
X-ThunderPhone-Call-ID: 987654321
Content-Type: application/json

{"zip": "94110"}

서버는 LLM에 다시 전달되는 JSON으로 응답합니다.

{"temperature_f": 64, "condition": "Partly cloudy", "wind_mph": 8}

LLM은 해당 응답을 처리하고 발신자에게 사람이 이해하기 쉬운 요약을 말합니다.

6. 루프 테스트

에이전트를 대상으로 마이크 세션을 실행하고 도구가 처리하는 질문을 합니다("94110의 날씨는 어떤가요?"). 통화 기록에는 전체 왕복 과정이 표시됩니다.

{
  "call_id": 987654321,
  "transcripts": [
    { "role": "user",
      "content": "What's the weather in 94110?" },
    { "role": "tool_call",
      "content": "{\"tool_call\": \"get_weather\", \"arguments\": {\"zip\": \"94110\"}}" },
    { "role": "tool_response",
      "content": "{\"tool_name\": \"get_weather\", \"response\": {\"temperature_f\": 64, \"condition\": \"Partly cloudy\"}}" },
    { "role": "agent",
      "content": "It's 64 degrees and partly cloudy." }
  ]
}

다음 엔드포인트를 통해 이를 가져올 수 있습니다. GET /v1/calls/{call_id}/transcript에서 가져올 수 있으며, 항목별 타이밍과 오디오 오프셋을 포함한 원시 이벤트 스트림은 GET /v1/calls/{call_id}/history에서 확인할 수 있습니다.

일반적인 주의 사항

에이전트가 도구를 호출하지 않음

LLM은 도구 설명을 기준으로 결정합니다. 발신자의 질문이 설명과 일치하지 않으면 모델은 도구를 호출하지 않습니다. 설명을 더 구체적으로 작성하거나(일반적인 동의어와 표현 추가) 에이전트 프롬프트에 명시적으로 언급합니다("발신자가 날씨를 물어보면 get_weather를 사용합니다.").

도구가 너무 많은 데이터를 반환함

6kB를 초과하는 응답은 기록 미리보기에서 잘립니다. 전체 행이 아니라 LLM에 필요한 필드만 반환합니다.

시간 초과

도구 엔드포인트의 기본 시간 초과는 10초입니다. 더 긴 시간이 필요하면 비동기적으로 처리합니다. {"status": "pending", "request_id": "..."}를 반환하고 별도의 도구 호출을 통해 결과를 표시합니다.

버전 관리

모든 통합 PATCH는 새 리비전을 생성합니다. GET /v1/integrations/{id}/versions를 검사하여 누가 무엇을 변경했는지 확인합니다. 도구의 스키마를 손상한 경우 이전 스냅샷을 다시 PATCH하여 수동으로 롤백할 수 있습니다.


다음 단계