Chamada de funções (também chamada de chamada de ferramentas ou uso de ferramentas) é como você dá a um modelo acesso ao seu código. Você descreve funções como "consultar um pedido" ou "calcular o frete". O modelo decide qual chamar e com quais argumentos; seu código a executa e envia o resultado de volta. Todo agente, de um bot de suporte de loja ao Claude Code, é baseado nesse loop.
Na GetVibe API, a chamada de funções funciona pelo endpoint padrão /v1/chat/completions no formato da OpenAI e por /v1/messages no formato da Anthropic. Abaixo está um loop completo que executamos em três modelos de três fabricantes diferentes.
Como o loop funciona
- Você envia mensagens junto com uma lista de
tools. Cada ferramenta tem um nome, uma descrição e um JSON Schema para seus parâmetros. - Em vez de texto, o modelo retorna
tool_calls: qual função chamar e com quais argumentos.finish_reasonétool_calls. - Seu código executa as funções e acrescenta uma mensagem com o papel
toolpara cada chamada, contendo o mesmotool_call_id. - Você envia o histórico novamente. O modelo pode pedir mais chamadas ou responder ao usuário em texto.
O modelo nunca executa nada por conta própria. Ele apenas solicita uma chamada. O que é realmente executado e com quais permissões é decidido pelo seu código.
Um exemplo completo: um assistente de suporte de loja
Duas funções: status do pedido e uma cotação de frete. O usuário pergunta sobre os dois ao mesmo tempo, e o modelo chama ambas em uma única rodada.
import json
import os
from openai import OpenAI
client = OpenAI(base_url="https://getvibeapi.com/v1", api_key=os.environ["GETVIBE_API_KEY"])
MODEL = "gpt-6-luna"
def get_order_status(order_id: str) -> dict:
# sua consulta ao banco de dados ou CRM entra aqui
return {"order_id": order_id, "status": "out for delivery", "eta": "2026-10-24"}
def get_shipping_quote(zip_code: str) -> dict:
return {"zip_code": zip_code, "price_usd": 7.5, "days": 2}
TOOLS = [
{"type": "function", "function": {
"name": "get_order_status",
"description": "Look up an order by its ID",
"parameters": {"type": "object",
"properties": {"order_id": {"type": "string", "description": "Order ID, e.g. A-1042"}},
"required": ["order_id"]}}},
{"type": "function", "function": {
"name": "get_shipping_quote",
"description": "Courier shipping price and delivery time to a US ZIP code",
"parameters": {"type": "object",
"properties": {"zip_code": {"type": "string"}},
"required": ["zip_code"]}}},
]
FUNCTIONS = {"get_order_status": get_order_status, "get_shipping_quote": get_shipping_quote}
messages = [
{"role": "system", "content": "Você é um assistente de suporte de loja. Seja breve."},
{"role": "user", "content": "Onde está meu pedido A-1042? E quanto custa o frete para 94110?"},
]
for _ in range(5): # limite o número de rodadas
resp = client.chat.completions.create(model=MODEL, messages=messages, tools=TOOLS)
msg = resp.choices[0].message
if not msg.tool_calls:
print(msg.content)
break
messages.append(msg.model_dump(exclude_none=True))
for call in msg.tool_calls:
args = json.loads(call.function.arguments)
result = FUNCTIONS[call.function.name](**args)
messages.append({"role": "tool", "tool_call_id": call.id, "content": json.dumps(result)})
Executamos este código sem alterações em gpt-6-luna, deepseek-v4.1-flash e claude-haiku-5.5, alterando apenas MODEL. Na primeira rodada, os três chamaram ambas as funções, get_order_status com A-1042 e get_shipping_quote com 94110. Na segunda rodada, os três responderam em texto com o status da entrega, a previsão, o preço de 7.50 e o prazo de entrega de dois dias.
O que importa neste código
- Acrescente a mensagem de chamada de ferramenta do modelo completa ao histórico. Sem isso, sua mensagem
toolresponde a uma chamada que o modelo não consegue ver, e muitos modelos simplesmente chamam a mesma função novamente, fazendo o loop ficar travado. - Uma mensagem
toolpor chamada, com otool_call_idcorrespondente. O modelo pode solicitar várias chamadas de uma vez, como aconteceu aqui. - Os argumentos chegam como uma string.
argumentsé um JSON dentro de uma string. Faça o parse e valide-o, porque o modelo pode fornecer um valor incorreto. - Limite as rodadas. Sem um limite, um bug em uma função pode transformar o loop em um processo infinito e gerar uma cobrança infinita de tokens.
tool_choice: quando uma chamada é obrigatória
Por padrão, o modelo decide se deve chamar uma ferramenta ou responder em texto ("auto"). tool_choice altera esse comportamento:
"none"— nunca chama ferramentas;"required"— chama pelo menos uma ferramenta;{"type": "function", "function": {"name": "..."}}— chama esta função específica.
A última forma é útil para extração de dados. O schema de parâmetros da função se torna o formato da resposta:
curl https://getvibeapi.com/v1/chat/completions \
-H "Authorization: Bearer $GETVIBE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-v4.1-flash",
"messages": [{"role": "user", "content": "Jane Doe, [email protected], quer uma demonstração na quinta-feira"}],
"tools": [{
"type": "function",
"function": {
"name": "save_lead",
"description": "Save a sales lead to the CRM",
"parameters": {
"type": "object",
"properties": {"name": {"type": "string"}, "email": {"type": "string"}, "request": {"type": "string"}},
"required": ["name", "email", "request"]
}
}
}],
"tool_choice": {"type": "function", "function": {"name": "save_lead"}}
}'
A resposta foi uma chamada save_lead com name "Jane Doe", email "[email protected]" e request "Quer uma demonstração na quinta-feira".
Uma ressalva: alguns modelos Claude, incluindo Claude Sonnet 5.5 e Claude Opus 5.5, não aceitam uma escolha de ferramenta forçada. A GetVibe transforma essa solicitação em auto com as mesmas ferramentas, para que você receba uma resposta em vez de um erro, mas então o modelo decide por conta própria se deve chamar a ferramenta. Para obter JSON estrito desses modelos, use saídas estruturadas.
O formato da Anthropic: /v1/messages
Com o SDK da Anthropic, as ferramentas têm uma aparência um pouco diferente: o schema de parâmetros vai em input_schema, e a chamada retorna como um bloco de conteúdo tool_use.
curl https://getvibeapi.com/v1/messages \
-H "x-api-key: $GETVIBE_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-haiku-5.5",
"max_tokens": 512,
"tools": [{
"name": "get_order_status",
"description": "Look up an order by its ID",
"input_schema": {"type": "object", "properties": {"order_id": {"type": "string"}}, "required": ["order_id"]}
}],
"messages": [{"role": "user", "content": "Onde está o pedido A-1042?"}]
}'
A resposta tinha stop_reason tool_use e um bloco tool_use chamando get_order_status com order_id A-1042. Você envia o resultado de volta como um bloco tool_result na próxima mensagem do usuário, com o mesmo tool_use_id.
Qual modelo usar para ferramentas
- Bots de alto volume e ferramentas simples — DeepSeek V4.1 Flash ($0.0112 entrada · $0.0445 saída por 1M de tokens) ou Claude Haiku 5.5 ($0.0267 entrada · $0.1334 saída por 1M de tokens).
- Agentes com muitas ferramentas e planos longos — GPT-6 Luna ($0.0055 entrada · $0.0274 saída por 1M de tokens) ou Claude Sonnet 5.5.
Os loops de agentes reenviam o mesmo prefixo longo a cada rodada, então o cache de prompts é muito importante aqui. Mais detalhes sobre os campos da solicitação estão na documentação de chamada de ferramentas.
