ThunderPhone 2.0 já está no ar.Comece por conta própria, a partir de 2¢/min.Leia o anúncio

Developer cookbook

Crie uma integração de ferramenta (API)

Permita que seu agente chame suas APIs durante a conversa — pesquise um banco de dados, crie um ticket, consulte um pedido.

Uma integração de ferramenta é um endpoint HTTP reutilizável que um agente pode invocar durante uma chamada. Você fornece ao ThunderPhone uma descrição em esquema JSON da ferramenta e uma URL de endpoint; o agente decide quando chamá-la com base na conversa, e o ThunderPhone faz a solicitação HTTP de saída a partir de seus servidores e retorna a resposta ao agente.

Este guia mostra como criar uma ferramenta de consulta de previsão do tempo de ponta a ponta.

Anatomia de uma ferramenta

Duas partes:

  1. O esquema — uma definição de função no estilo OpenAI ({type: "function", function: {name, description, parameters}}) que informa ao LLM o que a ferramenta faz e quais argumentos ela aceita.
  2. O endpoint — a URL que os servidores do ThunderPhone chamam quando o LLM decide usar a ferramenta. A solicitação é um POST JSON com os argumentos escolhidos pelo LLM como corpo.

1. Escolha uma estratégia de armazenamento

Em linha no agente

Anexe uma ferramenta pontual ao array tools do agente. Simples, mas não reutilizável.

Integração salva

Armazene a ferramenta como uma integração reutilizável e vincule-a a vários agentes. Recomendado para qualquer coisa usada mais de uma vez.

Este guia usa o caminho da integração salva.

2. Crie a integração

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" }
    ]
  }'

Salve o id retornado (um UUID).

3. Teste o endpoint no sandbox

Antes de vincular a integração a um agente, envie uma solicitação assinada dos servidores do ThunderPhone para confirmar a conectividade:

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, ...}"
}

Este teste também reforça as proteções SSRF do ThunderPhone — solicitações para localhost ou intervalos de IP privados retornam 400 code=url_not_allowed.

4. Vincule a integração a um agente

Anexe via integration_ids ao criar ou atualizar um agente:

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-..."]
  }'

Você pode vincular várias integrações a um agente. O prompt do agente pode referenciá-las pelo nome — "use get_weather quando quem liga perguntar sobre as condições" — ou ele pode descobri-las implicitamente pelas descrições do esquema.

5. Implemente o endpoint

Quando o agente invoca a ferramenta, o ThunderPhone envia um POST assinado ao seu endpoint_url:

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"}

Seu servidor responde com JSON que é repassado ao LLM:

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

O LLM processa essa resposta e fornece um resumo em linguagem natural para quem liga.

6. Teste o ciclo

Execute uma sessão de microfone com o agente e faça a pergunta que sua ferramenta atende ("Como está o tempo em 94110?"). A transcrição da chamada mostra o ciclo completo:

{
  "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." }
  ]
}

Você pode obter isso por meio de GET /v1/calls/{call_id}/transcript; o fluxo de eventos bruto (com tempos por entrada e deslocamentos de áudio) está em GET /v1/calls/{call_id}/history.

Erros comuns

O agente nunca chama a ferramenta

O LLM decide com base na descrição da ferramenta. Se a pergunta de quem liga não corresponder à descrição, o modelo não invocará a ferramenta. Torne a descrição mais específica (adicione sinônimos e formulações comuns) ou mencione-a explicitamente no prompt do agente ("Quando quem liga perguntar sobre o tempo, use get_weather.").

A ferramenta retorna dados demais

Respostas com mais de 6 kB são truncadas na visualização da transcrição. Retorne apenas os campos de que o LLM precisa — não o registro inteiro.

Tempos limite

Endpoints de ferramentas têm um tempo limite padrão de 10 segundos. Se precisar de mais tempo, processe de forma assíncrona: retorne {"status": "pending", "request_id": "..."} e disponibilize o resultado por meio de uma chamada de ferramenta separada.

Versionamento

Cada PATCH de integração cria uma nova revisão. Consulte GET /v1/integrations/{id}/versions para ver quem alterou o quê. Se você quebrar o esquema de uma ferramenta, poderá reverter manualmente aplicando PATCH novamente em um snapshot mais antigo.


Próximas etapas