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

Function Tools

Ferramentas de função

Forneça aos seus agentes de IA ferramentas de função que chamam APIs externas durante a conversa — buscam dados de clientes, agendam compromissos, atualizam registros — com parâmetros tipados.

As ferramentas de função permitem que seus agentes de IA invoquem APIs externas durante chamadas telefônicas. Use-as para consultar dados de clientes, verificar disponibilidade, agendar compromissos ou executar qualquer ação compatível com seu backend.

Como funciona

  1. Defina ferramentas com um esquema (quais argumentos a ferramenta aceita)
  2. Forneça uma configuração de endpoint (onde o ThunderPhone chama sua API) — ou omita-a para receber chamadas de ferramenta no webhook da sua organização
  3. Durante uma chamada, a IA decide quando usar uma ferramenta com base na conversa
  4. O ThunderPhone chama seu endpoint com os argumentos da ferramenta
  5. A resposta da sua API é enviada de volta para a IA continuar a conversa

Esquema da ferramenta

Cada ferramenta segue esta estrutura:

{
  "type": "function",
  "function": {
    "name": "search_appointments",
    "description": "Find available appointment slots for a given date",
    "parameters": {
      "type": "object",
      "properties": {
        "date": {
          "type": "string",
          "description": "Date in YYYY-MM-DD format"
        },
        "service": {
          "type": "string",
          "description": "Type of service (e.g., 'consultation', 'follow-up')"
        }
      },
      "required": ["date"]
    }
  },
  "endpoint": {
    "url": "https://api.example.com/appointments/search",
    "method": "POST",
    "headers": {
      "X-Api-Key": "your-api-key"
    }
  },
  "timeout": 120
}

Configuração da ferramenta

CampoTipoObrigatórioDescrição
timeoutnúmeroNãoTempo máximo de execução em segundos (padrão: 20, máximo: 180)

Definição da função

CampoTipoObrigatórioDescrição
namestringSimIdentificador exclusivo da ferramenta
descriptionstringSimExplica à IA quando usar esta ferramenta
parametersobjetoSimEsquema JSON para os argumentos da ferramenta

Configuração do endpoint

CampoTipoObrigatórioDescrição
urlstringSimURL do endpoint da sua API
methodstringNãoMétodo HTTP (padrão: POST)
headersobjetoNãoCabeçalhos personalizados a incluir

Dois caminhos de invocação

A solicitação que seu servidor recebe depende de a ferramenta ter um endpoint:

Ferramenta com endpointFerramenta sem endpoint
Para onde a solicitação vaiDiretamente para endpoint.urlURL de webhook legado da sua organização
CorpoArgumentos da ferramenta sem encapsulamentoEnvelope telephony.tool / web.tool
CabeçalhosSeus endpoint.headers + X-ThunderPhone-Call-ID + X-ThunderPhone-SignatureContent-Type + X-ThunderPhone-Signature
Chave de assinaturaSegredo do webhook da organizaçãoSegredo do webhook da organização

Ambos os caminhos são bloqueantes — a IA está aguardando o resultado no meio da frase. O tempo limite padrão é 20 s; defina o timeout no nível superior da ferramenta para permitir uma execução mais longa, até o máximo da plataforma de 180 s. Mantenha os manipuladores rápidos. Uma combinação é válida: em uma chamada cuja organização tenha uma URL de webhook, as ferramentas com um endpoint são chamadas diretamente, e as demais recorrem ao webhook.

Chamadas diretas de endpoint

Quando a IA invoca uma ferramenta que tem um endpoint, o ThunderPhone envia uma solicitação para sua URL:

Cabeçalhos da solicitação

POST /appointments/search HTTP/1.1
Host: api.example.com
Content-Type: application/json
X-ThunderPhone-Signature: abc123...
X-ThunderPhone-Call-ID: 987654321
X-Api-Key: your-api-key

Os cabeçalhos personalizados de endpoint.headers são sempre incluídos literalmente, além de dois cabeçalhos no namespace do ThunderPhone:

  • X-ThunderPhone-Signature — HMAC-SHA256 dos bytes exatos do corpo da solicitação, usando como chave o segredo de webhook da organização
  • X-ThunderPhone-Call-ID — O ID da chamada atual

Content-Type: application/json é definido, a menos que endpoint.headers o substitua — um Content-Type personalizado tem prioridade.

Corpo da solicitação

Para POST / PUT / PATCH, o corpo contém apenas os argumentos da ferramenta (sem envoltório), serializados canonicamente (chaves ordenadas, separadores compactos):

{"date":"2025-01-02","service":"consultation"}

Para GET / DELETE, os argumentos são enviados como parâmetros de consulta e o corpo fica vazio — a assinatura é então calculada sobre a string de bytes vazia. Consulte Verificar assinaturas de webhook.

Resposta

Retorne uma resposta JSON com o resultado da ferramenta:

{
  "available_slots": ["9:00 AM", "2:00 PM", "4:30 PM"],
  "timezone": "America/Los_Angeles"
}

A resposta é formatada e fornecida à IA para continuar a conversa. Respostas que não são JSON são envolvidas como {"data": "<text>"}; tempos limite e falhas de conexão são informados à IA como erros, para que o agente possa se desculpar e seguir em frente em vez de ficar bloqueado.

Despacho no modo webhook

Ferramentas sem um endpoint são encaminhadas para a URL de webhook legada da sua organização como uma solicitação assinada telephony.tool (chamadas telefônicas) ou web.tool (chamadas web). Diferentemente das notificações de auditoria entregues aos endpoints de webhook após a execução, esta solicitação é a execução — sua resposta HTTP é o resultado da ferramenta.

{
  "type": "telephony.tool",
  "data": {
    "call_id": 987654321,
    "tool_name": "search_appointments",
    "arguments": { "date": "2026-04-21" },
    "from_number": "+14155550199",
    "to_number": "+15551234567"
  }
}

web.tool inclui origin_domain em vez de from_number / to_number. Responda com o resultado da ferramenta em JSON — o mesmo contrato de resposta das chamadas diretas de endpoint. A solicitação é assinada com o segredo de webhook da organização sobre o corpo bruto, como qualquer outro webhook.


Verificação de assinatura

As chamadas diretas de ferramentas são assinadas da mesma forma que os webhooks:

  • HMAC-SHA256 sobre os bytes exatos do corpo da solicitação (o JSON canônico — chaves ordenadas, sem espaços em branco extras)
  • Com chave baseada no segredo de webhook da sua organização
  • Ferramentas GET / DELETE assinam a string de bytes vazia
Python
import hmac
import hashlib
 
def verify_tool_call(body: bytes, signature: str, secret: str) -> bool:
    expected = hmac.new(secret.encode(), body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, signature)
 
@app.post("/appointments/search")
async def search_appointments(request: Request):
    body = await request.body()
    signature = request.headers.get("X-ThunderPhone-Signature", "")
 
    if not verify_tool_call(body, signature, WEBHOOK_SECRET):
        raise HTTPException(status_code=401)
 
    data = json.loads(body)
    date = data["date"]
 
    # Look up availability
    slots = await get_available_slots(date)
 
    return {"available_slots": slots}
Node.js
app.post('/appointments/search', express.raw({type: 'application/json'}), (req, res) => {
  const signature = req.headers['x-thunderphone-signature'] || '';
  const expected = crypto
    .createHmac('sha256', WEBHOOK_SECRET)
    .update(req.body)
    .digest('hex');
 
  if (!signature ||
      signature.length !== expected.length ||
      !crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature))) {
    return res.status(401).send('Invalid signature');
  }
 
  const { date, service } = JSON.parse(req.body);
 
  // Look up availability
  const slots = getAvailableSlots(date, service);
 
  res.json({ available_slots: slots });
});

As receitas completas — incluindo o caso de corpo vazio e a observação sobre não haver segredo — estão em Verificar assinaturas de webhook.


Exemplo: fluxo completo de agendamento

Veja um conjunto de ferramentas para um sistema completo de agendamento de consultas:

{
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "search_appointments",
        "description": "Find available appointment slots",
        "parameters": {
          "type": "object",
          "properties": {
            "date": { "type": "string", "description": "YYYY-MM-DD" },
            "service": { "type": "string" }
          },
          "required": ["date"]
        }
      },
      "endpoint": {
        "url": "https://api.example.com/appointments/search",
        "method": "POST",
        "headers": { "X-Api-Key": "key" }
      }
    },
    {
      "type": "function",
      "function": {
        "name": "book_appointment",
        "description": "Book an appointment at a specific time",
        "parameters": {
          "type": "object",
          "properties": {
            "date": { "type": "string", "description": "YYYY-MM-DD" },
            "time": { "type": "string", "description": "HH:MM format" },
            "customer_name": { "type": "string" },
            "customer_phone": { "type": "string" }
          },
          "required": ["date", "time", "customer_name"]
        }
      },
      "endpoint": {
        "url": "https://api.example.com/appointments/book",
        "method": "POST",
        "headers": { "X-Api-Key": "key" }
      }
    },
    {
      "type": "function",
      "function": {
        "name": "cancel_appointment",
        "description": "Cancel an existing appointment",
        "parameters": {
          "type": "object",
          "properties": {
            "confirmation_number": { "type": "string" }
          },
          "required": ["confirmation_number"]
        }
      },
      "endpoint": {
        "url": "https://api.example.com/appointments/cancel",
        "method": "POST",
        "headers": { "X-Api-Key": "key" }
      }
    }
  ]
}

Boas práticas

Escreva descrições claras

O campo description ajuda a IA a entender quando usar a ferramenta. Especifique o que ela faz e quando é apropriado usá-la.

Trate erros de forma adequada

Retorne mensagens de erro que a IA consiga entender: {"error": "No slots available for that date"} em vez de erros 500 genéricos.

Mantenha as respostas concisas

Retorne apenas o que a IA precisa para continuar a conversa. Payloads grandes reduzem a velocidade de resposta.

Use campos obrigatórios com critério

Marque campos como required apenas quando for realmente necessário. A IA pedirá ao usuário as informações obrigatórias antes de chamar a ferramenta.


Relacionados