Open in
Ferramentas de função
Ofereç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
- Defina ferramentas com um schema (quais argumentos a ferramenta aceita)
- 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 - Durante uma chamada, a IA decide quando usar uma ferramenta com base na conversa
- O ThunderPhone chama seu endpoint com os argumentos da ferramenta
- A resposta da sua API é enviada de volta à IA para continuar a conversa
| Recurso | Onde é executado | Configuração |
|---|---|---|
| Ferramentas integradas | ThunderPhone | Instruções de prompt; algumas ferramentas também exigem uma configuração do agente |
| Conexões de apps | ThunderPhone e o provedor conectado | Conecte a conta e anexe ações aprovadas |
| Conexões de API e ferramentas de função | Sua API HTTP | Defina o endpoint e o schema ou receba chamadas de função por meio de um webhook |
| Servidores MCP | Um servidor MCP remoto | Adicione o servidor, descubra suas ferramentas e anexe-o ao agente |
Schema 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
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
timeout | número | Não | Tempo máximo de execução em segundos (padrão: 20, máximo: 180) |
Definição da função
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
name | string | Sim | Identificador exclusivo da ferramenta |
description | string | Sim | Explica à IA quando usar esta ferramenta |
parameters | objeto | Sim | Schema JSON para argumentos da ferramenta |
Configuração do endpoint
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
url | string | Sim | URL do endpoint da sua API |
method | string | Não | Método HTTP (padrão: POST) |
headers | objeto | Não | Cabeç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 endpoint | Ferramenta sem endpoint | |
|---|---|---|
| Destino da solicitação | Diretamente para endpoint.url | URL de webhook legada da sua organização |
| Corpo | Formato de solicitação selecionado (argumentos sem wrapper por padrão) | Envelope telephony.tool / web.tool |
| Cabeçalhos | Seus endpoint.headers + X-ThunderPhone-Call-ID + X-ThunderPhone-Signature-V2 + X-ThunderPhone-Signature | Content-Type + X-ThunderPhone-Signature-V2 + X-ThunderPhone-Signature |
| Chave de assinatura | Segredo do webhook da organização | Segredo do webhook da organização |
Ambos os caminhos são bloqueantes — a IA aguarda o
resultado em meio à frase. O tempo limite padrão é de 20 s; defina o
timeout de nível superior da ferramenta para permitir uma execução mais longa, até o máximo da
plataforma de 180 s. Mantenha os handlers rápidos. Uma combinação é aceitável:
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-V2: t=1767225600,v1=5f2c...
X-ThunderPhone-Signature: abc123...
X-ThunderPhone-Call-ID: 987654321
X-Api-Key: your-api-keyCabeçalhos personalizados de endpoint.headers são sempre incluídos
literalmente, além destes cabeçalhos no namespace do ThunderPhone:
X-ThunderPhone-Signature-V2— HMAC-SHA256 com carimbo de data e hora sobre o método, caminho, consulta e corpo, com chave no seu segredo de webhook da organização. Verifique este e rejeite solicitações com mais de 5 minutos; consulte Verificar assinaturas de webhookX-ThunderPhone-Signature— HMAC-SHA256 legado dos bytes exatos do corpo da solicitação, mesma chave, ainda enviado para verificadores existentesX-ThunderPhone-Call-ID— O ID da chamada atual
Content-Type: application/json é definido, a menos que endpoint.headers
o substitua — um Content-Type personalizado prevalece.
Formato da solicitação
Cada conexão de API tem uma configuração request_format. Escolha vapi ou
retell quando uma ferramenta importada precisar continuar chamando um endpoint criado para
essa plataforma. Conexões novas e existentes usam standard por padrão.
Para POST / PUT / PATCH, o ThunderPhone serializa o
envelope selecionado canonicamente (chaves ordenadas, separadores compactos). Ambas as assinaturas
abrangem exatamente esses bytes.
Padrão
standard envia apenas os argumentos da ferramenta, sem um invólucro. Este é o
padrão e preserva o corpo da solicitação original do ThunderPhone byte por byte:
{"date":"2025-01-02","service":"consultation"}Vapi
vapi envia a mensagem de servidor tool-calls do Vapi
no formato documentado pelo Vapi. O call.id é o ID da chamada do ThunderPhone. O
id da chamada de ferramenta é exclusivo da invocação e é reutilizado para associar o
resultado do endpoint. A chamada aparece em toolCallList e
toolWithToolCallList, com function.arguments como um objeto JSON:
{
"message": {
"type": "tool-calls",
"timestamp": 1725000000123,
"call": { "id": "987654321" },
"toolCallList": [
{
"id": "call_00112233445566778899aabbccddeeff",
"type": "function",
"function": {
"name": "search_appointments",
"arguments": { "date": "2025-01-02", "service": "consultation" }
}
}
],
"toolWithToolCallList": [
{
"type": "function",
"function": { "name": "search_appointments" },
"toolCall": {
"id": "call_00112233445566778899aabbccddeeff",
"type": "function",
"function": {
"name": "search_appointments",
"arguments": { "date": "2025-01-02", "service": "consultation" }
}
}
}
]
}
}Campos exclusivos do Vapi, como assistant, artifact e o objeto call completo,
não são enviados.
Retorne o envelope de resposta do Vapi com o ID correspondente da chamada de ferramenta:
{
"results": [
{
"toolCallId": "call_00112233445566778899aabbccddeeff",
"result": "{\"available_slots\":[\"9:00 AM\",\"2:00 PM\"]}"
}
]
}O ThunderPhone fornece à IA a string result sem o envelope. Ele também aceita um
valor JSON para compatibilidade com endpoints que já retornam um. Um
error no lugar de result é retornado à IA como um erro de ferramenta. Se o
endpoint retornar um envelope do Vapi malformado ou incompatível, o ThunderPhone registra
um aviso e usa a análise padrão de respostas em vez de falhar
a chamada.
Retell
retell envia a solicitação documentada para uma função personalizada do
Retell:
{
"name": "search_appointments",
"call": { "call_id": "987654321" },
"args": { "date": "2025-01-02", "service": "consultation" }
}O objeto call inclui apenas call_id. O ThunderPhone não inclui
campos específicos do Retell que não pode fornecer de maneira confiável no envio, como
agent_id, transcript, transcript_object, metadata ou variáveis
dinâmicas. O Retell aceita qualquer corpo de resposta; o ThunderPhone
o encaminha usando o tratamento padrão de respostas.
Para GET / DELETE, os argumentos são enviados como parâmetros de consulta
e o corpo fica vazio, independentemente de request_format. A assinatura V2
abrange a string de consulta conforme enviada; a assinatura legada é calculada sobre
a string de bytes vazios. 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 encapsuladas como {"data": "<text>"};
tempos limite e falhas de conexão são informados à IA como erros, para que
o agente possa pedir desculpas e seguir em frente em vez de ficar bloqueado.
Despacho no modo webhook
Ferramentas sem um endpoint são despachadas para a URL de webhook legado
da sua organização como uma solicitação assinada telephony.tool (chamadas telefônicas) ou web.tool
(chamadas pela 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 ao endpoint. A solicitação é assinada com o segredo de webhook da organização, usando ambos os cabeçalhos de assinatura, como qualquer outro webhook.
Verificação de assinatura
As chamadas diretas de ferramentas são assinadas da mesma forma que os webhooks, usando o segredo de webhook da sua organização:
X-ThunderPhone-Signature-V2assina o carimbo de data e hora, o método, o caminho e a consulta conforme enviados, além dos bytes exatos do corpo. Rejeite solicitações cujo carimbo de data e hora esteja a mais de 5 minutos do seu relógio.X-ThunderPhone-Signature(legado) assina apenas os bytes do corpo, ou a string de bytes vazia paraGET/DELETE. Ele ainda é enviado, sem alterações.
Os auxiliares do SDK verificam o cabeçalho V2, incluindo a janela de 5 minutos:
import json
from fastapi import FastAPI, HTTPException, Request
from thunderphone import verify_signature
app = FastAPI()
@app.post("/appointments/search")
async def search_appointments(request: Request):
body = await request.body()
query = request.scope.get("query_string", b"").decode("latin-1")
path = request.url.path + (f"?{query}" if query else "")
if not verify_signature(
request.headers.get("X-ThunderPhone-Signature-V2"),
secret=WEBHOOK_SECRET,
method=request.method,
path=path,
body=body,
):
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}import express from "express";
import { verifySignature } from "@thunderphone/sdk";
app.post('/appointments/search', express.raw({type: 'application/json'}), (req, res) => {
const ok = verifySignature({
header: req.header('X-ThunderPhone-Signature-V2'),
secret: WEBHOOK_SECRET,
method: req.method,
path: req.originalUrl,
body: req.body,
});
if (!ok) 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 — a string assinada, um exemplo detalhado, código sem o SDK, o caso GET / DELETE e a observação sobre a ausência de segredo — estão em Verificar assinaturas de webhook.
Exemplo: fluxo completo de agendamento
Este é um conjunto de ferramentas para um sistema completo de agendamento:
{
"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. Seja específico sobre o que ela faz e quando é apropriada.
Trate erros adequadamente
Retorne mensagens de erro que a IA possa 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. Cargas úteis grandes tornam os tempos de resposta mais lentos.
Use campos obrigatórios com critério
Marque campos como required apenas quando for realmente necessário. A IA solicitará a informação obrigatória ao usuário antes de chamar a ferramenta.
Relacionados
Acione ações de chamada gerenciadas pela plataforma sem definir um endpoint.
Ferramentas gerenciadas pela plataforma para HubSpot, Salesforce, Slack, Google Calendar, Google Sheets e Cal.com — nenhum endpoint necessário.
Conecte um servidor MCP e permita que o agente chame suas ferramentas.
Integrações REST reutilizáveis que você pode conectar aos agentes.
Um único auxiliar de verificação para webhooks e chamadas de ferramentas.