Tool Calling / Function Calling
Tool calling permite que o modelo “chame funções” que você define. O modelo não executa código — ele retorna o nome da função e os argumentos em JSON, e você executa a função no seu código. Isso habilita agentes, pesquisa em banco de dados, chamadas a APIs externas, e qualquer integração programática.
Como funciona
O fluxo tem 4 passos:
- 1. Você envia a mensagem do usuário + a lista de tools disponíveis
- 2. O modelo decide se precisa chamar uma tool e retorna
tool_callscom nome e argumentos - 3. Você executa a função localmente e envia o resultado de volta como mensagem
role: "tool" - 4. O modelo usa o resultado para compor a resposta final ao usuário
Definindo tools
Cada tool tem um name, description e parameters (JSON Schema). A description é fundamental — é o que o modelo lê para decidir quando usar a tool.
tools = [
{
"type": "function",
"function": {
"name": "consultar_clima",
"description": "Consulta a previsão do tempo para uma cidade brasileira",
"parameters": {
"type": "object",
"properties": {
"cidade": {
"type": "string",
"description": "Nome da cidade, ex: 'Brasília'"
},
"dias": {
"type": "integer",
"description": "Quantos dias de previsão (1-7)",
"default": 1
}
},
"required": ["cidade"]
}
}
}
]Exemplo completo (Python)
from openai import OpenAI
import json
client = OpenAI(
api_key="sk-...",
base_url="https://api.usetokia.com/v1",
)
# 1. Definir tools
tools = [
{
"type": "function",
"function": {
"name": "consultar_clima",
"description": "Consulta a temperatura atual de uma cidade",
"parameters": {
"type": "object",
"properties": {
"cidade": {"type": "string", "description": "Nome da cidade"}
},
"required": ["cidade"]
}
}
}
]
# Implementação local da função
def consultar_clima(cidade: str) -> dict:
# Na prática, chamaria uma API de clima
return {"cidade": cidade, "temperatura": 28, "condicao": "ensolarado"}
# 2. Enviar mensagem + tools
messages = [{"role": "user", "content": "Qual a temperatura em Brasília?"}]
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=messages,
tools=tools,
)
# 3. Verificar se o modelo quer chamar uma tool
message = response.choices[0].message
if message.tool_calls:
# Adicionar a mensagem do assistente ao histórico
messages.append(message)
for tool_call in message.tool_calls:
# Executar a função localmente
args = json.loads(tool_call.function.arguments)
result = consultar_clima(**args)
# 4. Enviar resultado de volta
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"content": json.dumps(result),
})
# 5. Obter resposta final
final = client.chat.completions.create(
model="gpt-4o-mini",
messages=messages,
tools=tools,
)
print(final.choices[0].message.content)
# → "A temperatura em Brasília está em 28°C, com tempo ensolarado."
else:
print(message.content)Exemplo completo (TypeScript)
import OpenAI from "openai";
const client = new OpenAI({
apiKey: process.env.TOKIA_KEY,
baseURL: "https://api.usetokia.com/v1",
});
const tools: OpenAI.ChatCompletionTool[] = [
{
type: "function",
function: {
name: "consultar_clima",
description: "Consulta a temperatura atual de uma cidade",
parameters: {
type: "object",
properties: {
cidade: { type: "string", description: "Nome da cidade" },
},
required: ["cidade"],
},
},
},
];
function consultarClima(cidade: string) {
return { cidade, temperatura: 28, condicao: "ensolarado" };
}
const messages: OpenAI.ChatCompletionMessageParam[] = [
{ role: "user", content: "Qual a temperatura em Brasília?" },
];
const response = await client.chat.completions.create({
model: "gpt-4o-mini",
messages,
tools,
});
const message = response.choices[0].message;
if (message.tool_calls) {
messages.push(message);
for (const toolCall of message.tool_calls) {
const args = JSON.parse(toolCall.function.arguments);
const result = consultarClima(args.cidade);
messages.push({
role: "tool",
tool_call_id: toolCall.id,
content: JSON.stringify(result),
});
}
const final = await client.chat.completions.create({
model: "gpt-4o-mini",
messages,
tools,
});
console.log(final.choices[0].message.content);
} else {
console.log(message.content);
}Múltiplas tools e chamadas paralelas
Você pode definir várias tools. O modelo pode chamar mais de uma na mesma resposta (chamada paralela). Itere sobre tool_calls e envie todos os resultados antes de pedir a resposta final:
tools = [
{
"type": "function",
"function": {
"name": "consultar_clima",
"description": "Consulta temperatura de uma cidade",
"parameters": {
"type": "object",
"properties": {"cidade": {"type": "string"}},
"required": ["cidade"]
}
}
},
{
"type": "function",
"function": {
"name": "consultar_cotacao",
"description": "Consulta cotação do dólar em BRL",
"parameters": {"type": "object", "properties": {}}
}
}
]
# O modelo pode retornar tool_calls com ambas as funções
# Trate cada uma e envie os resultadosForçando ou impedindo tool calls
Use tool_choice para controlar quando o modelo usa tools:
| Valor | Comportamento |
|---|---|
"auto" | O modelo decide se usa tool ou não (padrão) |
"none" | O modelo nunca usa tool, responde só com texto |
"required" | O modelo é obrigado a chamar pelo menos uma tool |
{"type":"function","function":{"name":"X"}} | O modelo é obrigado a chamar a tool X especificamente |
Tool calling com streaming
Tool calls também funcionam com stream: true. Os argumentos chegam em chunks parciais que você precisa concatenar:
stream = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "Qual o clima em SP?"}],
tools=tools,
stream=True,
)
tool_calls_acc = {}
for chunk in stream:
delta = chunk.choices[0].delta
if delta.tool_calls:
for tc in delta.tool_calls:
idx = tc.index
if idx not in tool_calls_acc:
tool_calls_acc[idx] = {"id": tc.id, "name": tc.function.name, "args": ""}
if tc.function.arguments:
tool_calls_acc[idx]["args"] += tc.function.arguments
# Agora tool_calls_acc tem as chamadas completas
for tc in tool_calls_acc.values():
args = json.loads(tc["args"])
print(f"Tool: {tc['name']}, Args: {args}")Modelos com suporte a tool calling
A maioria dos modelos de chat suporta tool calling, mas nem todos. Modelos populares com suporte:
- OpenAI: gpt-4o, gpt-4o-mini, gpt-4-turbo, o1, o3-mini
- Anthropic: claude-sonnet-4-20250514, claude-opus-4-20250514, claude-3.5-sonnet, claude-3-haiku
- Google: gemini-2.0-flash, gemini-2.5-pro
- Meta: llama-3.1-70b, llama-3.3-70b
- Mistral: mistral-large, mistral-small
- DeepSeek: deepseek-chat (V3)
Boas práticas
- Descriptions claras: O modelo decide qual tool usar baseado na description. Seja específico.
- JSON Schema restrito: Use
required,enume tipos precisos para evitar argumentos inválidos. - Valide argumentos: Mesmo com schema, valide os argumentos antes de executar.
- Limite o loop: Em agentes, defina um máximo de iterações para evitar loops infinitos.
- Trate erros: Se a execução da tool falhar, envie o erro como resultado — o modelo pode tentar outra abordagem.
Próximos passos
- Structured Outputs — force respostas em JSON Schema
- Streaming (SSE) — respostas em tempo real
- /v1/chat/completions — referência completa