Processando chamadas de ferramentas na sua aplicação
Detecte finish_reason tool_calls na resposta da API, extraia os nomes e argumentos das funções, execute a função Python correspondente e envie o resultado de volta ao modelo.
Processando chamadas de ferramentas na sua aplicação é uma aula grátis de AI Engineering Academy no CoddyKit. Esta é a aula 2 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de AI Engineering Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de AI Engineering Academy inclui 4 aulas no total.
O objeto de resposta de uma chamada de ferramenta
Quando o modelo decide chamar uma função, a resposta da API contém uma lista tool_calls no objeto da mensagem. Cada chamada de ferramenta tem um id exclusivo, o function.name a ser chamado e function.arguments — uma string JSON com os argumentos que o modelo deseja enviar. O código da sua aplicação é responsável por analisar esses dados e executar a função.
from openai import OpenAI
import json
client = OpenAI()
response = client.chat.completions.create(
model='gpt-4o',
messages=[{'role': 'user', 'content': 'What is the weather in Paris?'}],
tools=tools # defined previously
)
message = response.choices[0].message
if response.choices[0].finish_reason == 'tool_calls':
for tool_call in message.tool_calls:
print('Call ID:', tool_call.id)
print('Function name:', tool_call.function.name)
print('Arguments (JSON string):', tool_call.function.arguments)Analisando argumentos de funções
O campo function.arguments é uma string codificada em JSON, não um dict do Python. Você precisa analisá-lo com json.loads(). Sempre envolva essa operação em um bloco try/except — ocasionalmente, o modelo produz JSON inválido apesar das orientações do esquema, e você precisa lidar com isso de forma adequada.
import json
def parse_tool_call(tool_call) -> dict:
'''Parse a tool call's arguments from JSON string to dict.'''
try:
args = json.loads(tool_call.function.arguments)
return args
except json.JSONDecodeError as e:
print(f'Failed to parse arguments for {tool_call.function.name}: {e}')
print(f'Raw arguments: {tool_call.function.arguments}')
return {}
# Usage
tool_call = message.tool_calls[0]
args = parse_tool_call(tool_call)
print('Parsed args:', args) # {'location': 'Paris', 'unit': 'celsius'}Encaminhando para a função correta
Use function.name para encaminhar a chamada à função Python correta. Um padrão organizado é manter suas funções em um dicionário que mapeie o nome para o objeto chamável. Isso evita cadeias frágeis de if/elif e facilita a adição de novas ferramentas posteriormente.
def get_current_weather(location: str, unit: str = 'celsius') -> str:
# Real implementation calls a weather API
return f'{location}: 18{chr(176)}C, partly cloudy'
def create_calendar_event(title: str, start_time: str, duration_minutes: int, **kwargs) -> str:
return f'Event created: {title} at {start_time} for {duration_minutes} minutes'
# Tool registry: maps function names to callables
TOOL_REGISTRY = {
'get_current_weather': get_current_weather,
'create_calendar_event': create_calendar_event
}
def execute_tool_call(tool_call) -> str:
name = tool_call.function.name
args = parse_tool_call(tool_call)
if name not in TOOL_REGISTRY:
return f'Unknown function: {name}'
try:
result = TOOL_REGISTRY[name](**args)
return str(result)
except Exception as e:
return f'Function {name} raised an error: {str(e)}'Enviando os resultados de volta ao modelo
Depois de executar a função, você precisa enviar o resultado de volta ao modelo em uma chamada subsequente à API. Adicione a mensagem do assistente (que contém os tool_calls) à conversa e, em seguida, adicione uma nova mensagem com role='tool', o tool_call_id e o resultado da função como conteúdo. Depois, chame a API novamente.
def run_tool_call_loop(messages: list, tools: list) -> str:
response = client.chat.completions.create(
model='gpt-4o',
messages=messages,
tools=tools
)
message = response.choices[0].message
messages.append(message) # Add assistant's tool_calls message
# Execute all tool calls and collect results
for tool_call in (message.tool_calls or []):
result = execute_tool_call(tool_call)
# Add each tool result as a 'tool' role message
messages.append({
'role': 'tool',
'tool_call_id': tool_call.id,
'content': result
})
# Second API call with results appended
final_response = client.chat.completions.create(
model='gpt-4o',
messages=messages,
tools=tools
)
return final_response.choices[0].message.contentO turno completo da conversa
Uma interação completa de chamada de ferramenta envolve quatro mensagens no histórico da conversa: a mensagem do usuário, a mensagem do assistente solicitando uma chamada de ferramenta, a mensagem com o resultado da ferramenta e a resposta final do assistente incorporando o resultado. Compreender essa estrutura é essencial para criar assistentes que usam ferramentas em várias etapas.
# The full message history for a tool-calling conversation:
conversation = [
{'role': 'user', 'content': 'What is the weather in Tokyo?'},
# Model requests a tool call (added by run_tool_call_loop)
# {'role': 'assistant', 'content': None, 'tool_calls': [...]},
# Application sends tool result back
# {'role': 'tool', 'tool_call_id': 'call_abc123', 'content': 'Tokyo: 22C, sunny'},
# Model produces final human-readable response
# {'role': 'assistant', 'content': 'The weather in Tokyo is 22 degrees Celsius and sunny.'}
]
final_answer = run_tool_call_loop(
[{'role': 'user', 'content': 'What is the weather in Tokyo?'}],
tools
)
print(final_answer)Lidando com o caso em que nenhuma ferramenta é chamada
Às vezes, o modelo responde diretamente sem chamar nenhuma ferramenta — finish_reason será 'stop', em vez de 'tool_calls'. Sempre verifique esse caso antes de tentar processar chamadas de ferramentas. Uma implementação robusta lida corretamente com os dois caminhos.
def smart_complete(user_message: str) -> str:
messages = [{'role': 'user', 'content': user_message}]
response = client.chat.completions.create(
model='gpt-4o',
messages=messages,
tools=tools
)
choice = response.choices[0]
if choice.finish_reason == 'stop':
# Model answered directly without calling a tool
return choice.message.content
elif choice.finish_reason == 'tool_calls':
# Process tool calls
messages.append(choice.message)
for tc in choice.message.tool_calls:
result = execute_tool_call(tc)
messages.append({'role': 'tool', 'tool_call_id': tc.id, 'content': result})
# Get final answer
final = client.chat.completions.create(model='gpt-4o', messages=messages)
return final.choices[0].message.content
return 'Unexpected finish reason: ' + choice.finish_reasonValidando argumentos antes da execução
O modelo pode ocasionalmente enviar argumentos que não passam na validação da lógica de negócio — uma duração negativa, um e-mail inválido ou uma data no passado. Valide os argumentos antes de chamar a função real e retorne uma string de erro descritiva se a validação falhar. Assim, o modelo poderá corrigir seus argumentos no turno seguinte.
from pydantic import BaseModel, ValidationError
from datetime import datetime
class CreateEventArgs(BaseModel):
title: str
start_time: str # ISO 8601
duration_minutes: int
def safe_create_event(tool_call) -> str:
try:
raw_args = json.loads(tool_call.function.arguments)
validated = CreateEventArgs(**raw_args)
# Additional business rule
event_time = datetime.fromisoformat(validated.start_time)
if event_time < datetime.now():
return 'Error: start_time must be in the future.'
return create_calendar_event(**validated.dict())
except ValidationError as e:
return f'Invalid arguments: {e}'Registrando interações de chamadas de ferramentas
Sempre registre as interações de chamadas de ferramentas para depuração e análise. Registre o nome da função, os argumentos, o resultado e o tempo de execução. Esses dados ajudam a identificar quais ferramentas são chamadas com mais frequência, quais falham e quais padrões de argumentos o modelo produz — informações valiosas para melhorar seus esquemas e implementações de funções.
import time
import logging
logger = logging.getLogger('tool_calls')
def logged_execute(tool_call) -> str:
name = tool_call.function.name
args_str = tool_call.function.arguments
start = time.time()
result = execute_tool_call(tool_call)
elapsed = time.time() - start
logger.info(
'Tool call executed',
extra={
'function': name,
'arguments': args_str,
'result_length': len(result),
'elapsed_ms': round(elapsed * 1000)
}
)
return resultConsiderações de segurança para chamadas de ferramentas
Nunca execute funções arbitrárias com base na saída do modelo sem validação. Sempre inclua na lista de permissões os nomes exatos das funções no seu TOOL_REGISTRY, valide todos os argumentos e verifique a autorização antes de executar ações. O modelo é um chamador não confiável — um comando malicioso pode tentar invocar funções destrutivas se a sua lógica de encaminhamento for permissiva demais.
- Permita somente funções explicitamente listadas em TOOL_REGISTRY
- Valide as entradas com Pydantic antes da execução
- Exija autorização para operações de escrita/exclusão
Retornando resultados estruturados e detalhados
Os resultados das ferramentas não precisam ser strings simples. Você pode retornar dados formatados em JSON, tabelas ou resumos. Retornar dados estruturados como JSON permite que o modelo analise e consulte campos específicos na resposta final. Para resultados grandes, retorne um resumo com os fatos principais em vez de despejar todos os dados brutos no contexto.
def get_order_status(order_id: str) -> str:
# Fetch from real database
order = {'id': order_id, 'status': 'shipped', 'estimated_delivery': '2024-03-15', 'carrier': 'FedEx', 'tracking': 'FX123456'}
# Return concise summary, not raw DB record
return (
f'Order {order_id}: Status={order["status"]}, '
f'Estimated delivery: {order["estimated_delivery"]}, '
f'Carrier: {order["carrier"]}, Tracking: {order["tracking"]}'
)Conversas com ferramentas em várias etapas
Um padrão poderoso é uma conversa em várias etapas na qual o modelo chama ferramentas ao longo de várias mensagens do usuário, acumulando contexto. Sempre mantenha o histórico completo da conversa, incluindo chamadas de ferramentas e resultados anteriores, para que o modelo possa consultar respostas anteriores sem chamar as ferramentas novamente de forma desnecessária.
Verificação rápida
Teste sua compreensão sobre o processamento de chamadas de ferramentas na sua aplicação.
Recapitulação da lição
Nesta lição, você aprendeu que: os argumentos das chamadas de ferramentas chegam como uma string JSON que deve ser analisada com json.loads(), um dicionário TOOL_REGISTRY mapeia nomes de funções para objetos chamáveis, permitindo um encaminhamento organizado e os resultados retornam ao modelo como mensagens com role='tool' e tool_call_ids correspondentes. A seguir, veremos como lidar com o caso em que o modelo chama várias funções simultaneamente usando chamadas de funções em paralelo.
Perguntas Frequentes
A aula “Processando chamadas de ferramentas na sua aplicação” é grátis?
Sim — o texto completo de “Processando chamadas de ferramentas na sua aplicação” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de AI Engineering Academy, atualize para CoddyKit PRO. O curso de AI Engineering Academy inclui 4 aulas no total.
O que vou aprender em “Processando chamadas de ferramentas na sua aplicação”?
Detecte finish_reason tool_calls na resposta da API, extraia os nomes e argumentos das funções, execute a função Python correspondente e envie o resultado de volta ao modelo. Você pratica AI Engineering Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar AI Engineering Academy?
Nenhuma experiência prévia é necessária. AI Engineering Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 2 de 4.
Quanto tempo leva a aula “Processando chamadas de ferramentas na sua aplicação”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de AI Engineering Academy?
Sim. Cada aula de AI Engineering Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Definindo esquemas de funções para a API
- Processando chamadas de ferramentas na sua aplicação
- Chamadas de funções em paralelo
- Criando uma interface de banco de dados em linguagem natural