Function Calling na Prática: Tutorial Python para Chatbots com LLMs que Executam Ações em 2026
Seu chatbot sabe responder perguntas. Mas ele consegue agir? Em 2026, essa é a linha que separa um protótipo de um produto de verdade.
Dados da OpenAI mostram que 70% dos desenvolvedores já usam function calling em chatbots de produção (OpenAI DevDay 2025). O motivo é simples: sem isso, o LLM é apenas um papagaio digital. Com function calling, ele vira um orquestrador de sistemas.
Neste tutorial, você vai aprender a implementar function calling na prática com Python. Vamos usar as APIs das três principais plataformas — OpenAI, Anthropic Claude e Google Gemini — para construir um chatbot que consulta clima, acessa banco de dados e envia notificações.
O que é Function Calling (e por que você precisa disso)
Function calling, também chamado de tool use, é a capacidade do LLM de identificar quando deve chamar uma função externa. O modelo não executa o código — ele retorna um objeto JSON estruturado com os parâmetros da função. Seu sistema executa a função e devolve o resultado para o modelo.
"Function calling transforma LLMs de geradores de texto em agentes de software. É a ponte entre linguagem natural e APIs." — Documentação oficial da Anthropic sobre tool use (2025)
O fluxo básico é:
- Você define funções com descrições e parâmetros (como um schema JSON).
- O modelo decide se deve chamar alguma função com base no prompt do usuário.
- Seu código executa a função real e retorna o resultado.
- O modelo incorpora esse resultado na resposta final.
O custo médio de uma chamada de função via LLM é de US$ 0,003 (Anthropic pricing, 2025). Para chatbots de alto volume, isso representa um custo operacional baixo comparado ao ganho em utilidade.
Mão na massa: Implementação com OpenAI
A OpenAI foi pioneira em function calling. A API é madura e bem documentada. Vamos criar um assistente que consulta o clima e gerencia tarefas.
Primeiro, instale a biblioteca:
pip install openai
Agora, defina as funções que o modelo poderá chamar:
import json
from openai import OpenAI
client = OpenAI(api_key="sua-chave-aqui")
tools = [ { "type": "function", "function": { "name": "get_weather", "description": "Obtém a temperatura atual de uma cidade", "parameters": { "type": "object", "properties": { "city": { "type": "string", "description": "Nome da cidade, ex: São Paulo" }, "unit": { "type": "string", "enum": ["celsius", "fahrenheit"] } }, "required": ["city"] } } }, { "type": "function", "function": { "name": "add_task", "description": "Adiciona uma tarefa à lista do usuário", "parameters": { "type": "object", "properties": { "task": { "type": "string", "description": "Descrição da tarefa" }, "priority": { "type": "string", "enum": ["alta", "media", "baixa"] } }, "required": ["task", "priority"] } } } ]
Crie as funções reais que serão executadas:
def get_weather(city: str, unit: str = "celsius"):
# Simulação de consulta a API externa
temperaturas = {"São Paulo": 22, "Rio de Janeiro": 30, "Brasília": 25}
temp = temperaturas.get(city, 20)
if unit == "fahrenheit":
temp = temp * 9/5 + 32
return json.dumps({"city": city, "temperature": temp, "unit": unit})
def add_task(task: str, priority: str): # Simulação de inserção em banco de dados return json.dumps({"status": "sucesso", "task": task, "priority": priority})
Agora, o loop principal de conversação:
messages = [{"role": "user", "content": "Qual a temperatura no Rio e adicione 'comprar leite' como prioridade alta"}]
response = client.chat.completions.create( model="gpt-4o", messages=messages, tools=tools, tool_choice="auto" )
assistant_message = response.choices[0].message tool_calls = assistant_message.tool_calls
if tool_calls: for tool_call in tool_calls: function_name = tool_call.function.name arguments = json.loads(tool_call.function.arguments)
if function_name == "get_weather":
result = get_weather(**arguments)
elif function_name == "add_task":
result = add_task(**arguments)
messages.append({
"tool_call_id": tool_call.id,
"role": "tool",
"name": function_name,
"content": result
})
final_response = client.chat.completions.create(
model="gpt-4o",
messages=messages
)
print(final_response.choices[0].message.content)
Perceba que o modelo pode chamar múltiplas funções em paralelo. Ele entende que precisa do clima e também adicionar uma tarefa. Isso é nativo na API da OpenAI.
Implementação com Anthropic Claude
A Anthropic chama de tool use. A API é similar, mas tem diferenças importantes. Vamos ao código.
pip install anthropic
from anthropic import Anthropic
client = Anthropic(api_key="sua-chave")
tools = [ { "name": "get_weather", "description": "Obtém a temperatura atual de uma cidade", "input_schema": { "type": "object", "properties": { "city": {"type": "string", "description": "Nome da cidade"}, "unit": {"type": "string", "enum": ["celsius", "fahrenheit"]} }, "required": ["city"] } }, { "name": "add_task", "description": "Adiciona uma tarefa à lista", "input_schema": { "type": "object", "properties": { "task": {"type": "string"}, "priority": {"type": "string", "enum": ["alta", "media", "baixa"]} }, "required": ["task", "priority"] } } ]
message = client.messages.create( model="claude-3-5-sonnet-20241022", max_tokens=1024, messages=[{"role": "user", "content": "Qual a temperatura em Brasília?"}], tools=tools )
Claude retorna stop_reason="tool_use" quando quer chamar uma função
if message.stop_reason == "tool_use": for content_block in message.content: if content_block.type == "tool_use": tool_name = content_block.name tool_input = content_block.input
if tool_name == "get_weather":
result = get_weather(**tool_input)
# Envia o resultado de volta
response = client.messages.create(
model="claude-3-5-sonnet-20241022",
messages=[
{"role": "user", "content": "Qual a temperatura em Brasília?"},
{"role": "assistant", "content": message.content},
{"role": "user", "content": [
{
"type": "tool_result",
"tool_use_id": content_block.id,
"content": result
}
]}
],
tools=tools
)
print(response.content[0].text)
A diferença principal: Claude usa stop_reason e blocos de conteúdo estruturados. Ele não aceita múltiplas chamadas paralelas na mesma rodada — cada tool_use precisa ser processada sequencialmente.
Implementação com Google Gemini
O Gemini também oferece function calling nativo. A sintaxe é um pouco diferente, mas o conceito é o mesmo.
pip install google-generativeai
import google.generativeai as genai
genai.configure(api_key="sua-chave")
model = genai.GenerativeModel("gemini-2.0-flash")
Define as funções como dicionário Python
get_weather_tool = { "function_declarations": [ { "name": "get_weather", "description": "Obtém a temperatura atual de uma cidade", "parameters": { "type_": "OBJECT", "properties": { "city": {"type_": "STRING"}, "unit": {"type_": "STRING", "enum": ["celsius", "fahrenheit"]} }, "required": ["city"] } }, { "name": "add_task", "description": "Adiciona uma tarefa à lista", "parameters": { "type_": "OBJECT", "properties": { "task": {"type_": "STRING"}, "priority": {"type_": "STRING", "enum": ["alta", "media", "baixa"]} }, "required": ["task", "priority"] } } ] }
chat = model.start_chat()
response = chat.send_message( "Qual a temperatura em São Paulo?", tools=[get_weather_tool] )
Gemini retorna function_call na resposta
if response.candidates[0].content.parts[0].function_call: function_call = response.candidates[0].content.parts[0].function_call tool_name = function_call.name args = {key: value for key, value in function_call.args.items()}
if tool_name == "get_weather":
result = get_weather(**args)
# Envia o resultado
response = chat.send_message(
genai.protos.Content(
parts=[
genai.protos.Part(
function_response=genai.protos.FunctionResponse(
name=tool_name,
response={"result": result}
)
)
]
)
)
print(response.text)
O Gemini usa function_declarations e FunctionResponse. Ele também suporta chamadas paralelas, mas a implementação é mais verbosa que a da OpenAI.
Comparação entre as três plataformas
| Característica | OpenAI | Anthropic Claude | Google Gemini |
|---|---|---|---|
| Chamadas paralelas | Sim (nativo) | Não (sequencial) | Sim (mas verboso) |
| Formato do schema | JSON Schema | JSON Schema | Dicionário Python |
| Identificação da chamada | tool_calls | stop_reason: tool_use | function_call |
| Retorno de resultado | role: tool | tool_result | FunctionResponse |
| Modelo recomendado | gpt-4o | claude-3-5-sonnet | gemini-2.0-flash |
| Custo por chamada | ~US$0,005 | ~US$0,003 | ~US$0,002 |
A OpenAI leva vantagem em maturidade e suporte a paralelismo. A Anthropic oferece o menor custo por chamada. O Gemini se destaca pela integração com o ecossistema Google.
Boas práticas para produção
Function calling em produção exige cuidados extras. Aqui vão três regras essenciais.
Valide os parâmetros antes de executar. O modelo pode alucinar valores. Sempre verifique se os parâmetros estão dentro do esperado.
def safe_get_weather(city, unit="celsius"):
if unit not in ["celsius", "fahrenheit"]:
unit = "celsius" # fallback seguro
# continua...
Defina descrições claras e detalhadas. Quanto melhor a descrição da função e dos parâmetros, maior a chance de o modelo chamar a função correta. Use exemplos.
"description": "Obtém a temperatura de uma cidade. Ex: 'São Paulo' retorna 22°C."
Implemente timeouts e fallbacks. APIs externas podem falhar. Se a chamada de função demorar mais que 5 segundos, retorne um erro amigável para o modelo.
import asyncio
async def call_with_timeout(func, timeout=5): try: return await asyncio.wait_for(func, timeout=timeout) except asyncio.TimeoutError: return json.dumps({"error": "Serviço indisponível no momento"})
O futuro é agêntico
Function calling é a base para agentes autônomos. Em 2026, os chatbots que não executam ações estão fadados a serem substituídos. A diferença entre um assistente útil e um brinquedo tecnológico está na capacidade de integrar sistemas.
Comece pequeno: uma função de clima, uma de banco de dados. Depois adicione envio de email, consulta a CRM, execução de scripts. O padrão é o mesmo. A complexidade vem da orquestração.
O código deste tutorial está disponível em um repositório público. Use como base para seu próximo chatbot. E lembre-se: o LLM é o cérebro, mas as funções são os músculos.
Artigos Relacionados
Confira também: Agentes de IA Autônomos em 2026: como funcionam, onde estão sendo usados e o que esperar Confira também: 7 Passos para um Chatbot sem Alucinação: CoT, Self-Consistency e DSPy em Python Confira também: A Crise Silenciosa dos Multimodais: Por que 1 em Cada 3 Respostas Visuais de LLMs em 2026 é Alucinação
NeuralPulse
Blog profissional sobre Inteligencia Artificial. Exploramos tendencias, ferramentas, tutoriais e analises profundas sobre como a IA esta transformando negocios, tecnologia e o dia a dia.
Receba as novidades sobre IA
Junte-se a milhares de leitores que acompanham as ultimas tendencias em inteligencia artificial.
Artigos Relacionados
Automação de Licitações com IA: Guia Prático para Órgãos Públicos
Aprenda a usar IA gratuita para automatizar a análise de editais e propostas em licitações públicas com Python, dados abertos e modelos como Sabiá-4 e Gemini.
IA no Varejo Brasileiro em 2026: 3 Cases Reais que Aumentaram as Vendas em 35% (e Como Sua Loja Pode Fazer o Mesmo)
Cases reais de adoção de IA no varejo brasileiro mostram aumento de 35% nas vendas. Aprenda o passo a passo para implementar um sistema de recomendação simpl...
Árvore de Decisão vs Random Forest vs XGBoost: Tutorial Prático de Machine Learning em 2026 (com Código Python e Dados Reais)
Comparação prática entre Árvore de Decisão, Random Forest e XGBoost para classificação em 2026, com implementação passo a passo em Python e análise de perfor...
Comentarios
Powered by Disqus
Para ativar os comentarios, configure seu shortname do Disqus no componente.
<div id="disqus_thread"></div>