Function calling em Python: conecte a IA a ferramentas com segurança

Aprenda a usar function calling na Responses API para permitir que uma IA consulte dados e acione funções Python com validação e controle.

Compartilhe

Fluxo seguro de function calling conectando uma inteligência artificial a ferramentas externas validadas

Python + IA: Fundamentos e Projetos Práticos

Ambiente, sintaxe e variáveis em Python

Ambiente, Sintaxe Básica e Variáveis em Python — Bootcamp Dia 1

Tipos de dados, entrada e conversão em Python

Tipos de Dados, Entrada e Conversão no Python — Bootcamp Dia 2

Operadores em Python

Operadores Aritméticos, Relacionais e Lógicos em Python — Bootcamp Dia 3

Estruturas condicionais em Python

Estrutura Condicional com if, elif e else em Python — Bootcamp Dia 4

Loops e estruturas de repetição em Python

Repetição com for, while e range() no Python — Bootcamp Dia 5

Listas em Python

Como Trabalhar com Listas no Python — Bootcamp Dia 6

Tuplas e sets em Python

Tuplas e Sets em Python — Estruturas Imutáveis e Conjuntos Inteligentes | Bootcamp Dia 7

Dicionários em Python

Dicionários em Python: chave e valor, o jeito inteligente de armazenar dados

Funções em Python

Funções em Python: Escreva Menos, Faça Mais

Tratamento de erros em Python

Tratamento de Erros em Python: programe com segurança

Leitura e Escrita de Arquivos em Python

Leitura e Escrita de Arquivos em Python: salve seus dados no mundo real

Como Salvar Listas de Dicionários em Arquivo JSON com Python

Salvando Dados Estruturados com JSON em Python

Como Trabalhar com Datas em Python — Idade, Diferença e Formatação

Trabalhando com Datas e Horários em Python

Funções com Múltiplos Retornos em Python — Análise de Dados com Elegância

Funções com Múltiplos Retornos em Python: eficiência e organização

Parâmetros Opcionais e Valores Padrão em Python

Parâmetros Opcionais e Valores Padrão em Python

Como Usar args e kwargs em Funções Python

*args e **kwargs em Python: flexibilidade total nas funções

Como Usar List Comprehensions em Python

List Comprehensions em Python: código elegante e eficiente

Como Manipular Arquivos CSV com Python

Manipulando Arquivos CSV com Python: automatize leitura e escrita de dados

Como Usar Pandas em Python para Análise de Dados

Começando com Pandas em Python: análise de dados para IA e automações

Como Limpar e Preparar Dados com Pandas | Bootcamp Dia 20

Limpeza e Transformação de Dados com Pandas: preparando para IA

Como usar a OpenAI com Python (API Atualizada, GPT-3.5)

Inteligência Artificial com Python: Fundamentos e Primeira Integração com a OpenAI

Como fazer Análise de Sentimentos com Python e IA (Passo a Passo)

Análise de Sentimentos com IA: Classificando Emoções em Textos com Python

Como Classificar Textos com IA e Python (Zero-Shot Classification)

Classificação de Texto com IA: Detectando Temas e Categorias

Como Criar Textos com Python e IA (NLP + GPT-2)

Geração de Texto com IA: Criando Respostas Inteligentes com Python

Como Criar um Chatbot com IA em Python (com DialoGPT)

Chatbot com IA em Python: Construindo um Assistente Inteligente

Como Detectar Fake News com Python e IA — Projeto Prático

Como Detectar Fake News com Python e IA

Como Criar uma Interface com IA em Python para Detectar Fake News

Como Criar uma Interface com IA em Python para Detectar Fake News

Como Avaliar a Qualidade de um Modelo de IA com Python

Como Avaliar a Qualidade de um Modelo de IA com Python — Além da Acurácia

Como Balancear Dados e Validar Modelos com Python e IA

Como Balancear Dados e Validar Modelos com Python e IA

Classificador de Fake News com Interface Web em Python (Streamlit)

Projeto Final: Criando um Classificador de Fake News com Interface Web em Python (Streamlit)

Ambiente de desenvolvimento Python organizado com árvore de arquivos, dependências conectadas e lockfile protegido

Python com uv: ambientes virtuais e dependências reproduzíveis

Fluxo de inteligência artificial transformando dados desorganizados em blocos estruturados para automação

Saídas estruturadas com IA: JSON confiável para automações em Python

Fluxo seguro de function calling conectando uma inteligência artificial a ferramentas externas validadas

Function calling em Python: conecte a IA a ferramentas com segurança

Uma IA que apenas escreve texto é útil. Uma IA que consulta um pedido, calcula um frete ou busca dados do seu sistema pode participar de fluxos reais. O recurso que conecta esses dois mundos é o function calling: o modelo identifica quando precisa de uma ferramenta, devolve uma solicitação estruturada e deixa seu código Python decidir se e como a função será executada.

Nesta aula 33 da série Python + IA: Fundamentos e Projetos Práticos, vamos construir um assistente que consulta o status de um pedido. O exemplo usa a Responses API, esquema estrito, lista de funções permitidas e validação antes da execução. A implementação segue o fluxo atual da documentação oficial de function calling da OpenAI.

Do JSON estruturado para uma ação controlada

Na aula anterior, vimos como gerar JSON confiável com saídas estruturadas. Ali, o formato organiza a resposta final do modelo. No function calling, o JSON tem outra função: descrever uma solicitação para que a sua aplicação execute uma ferramenta.

Essa diferença é fundamental. O modelo não chama diretamente o banco de dados e não executa uma função Python por conta própria. Ele pode responder algo equivalente a “use a ferramenta consultar_pedido com o número AM-1042”. Seu programa recebe a solicitação, verifica o nome, valida os argumentos, executa a função permitida e devolve o resultado ao modelo.

O fluxo completo tem cinco etapas:

  1. seu código oferece uma lista de ferramentas e seus esquemas;
  2. o usuário faz uma pergunta;
  3. o modelo produz uma chamada de ferramenta quando necessário;
  4. a aplicação valida e executa a função;
  5. o resultado volta ao modelo, que redige a resposta final.

A separação mantém a aplicação no controle. O modelo propõe; o código autoriza e executa.

Prepare o projeto e crie a função local

Você pode continuar o ambiente organizado com uv e pyproject.toml. No terminal, crie um projeto e instale o SDK:

uv init assistente-pedidos
cd assistente-pedidos
uv add openai

Configure OPENAI_API_KEY no ambiente, sem gravar a chave no arquivo Python. Em seguida, crie uma fonte de dados local para o tutorial:

PEDIDOS = {
    "AM-1042": {"status": "em transporte", "previsao": "12/08/2026"},
    "AM-1057": {"status": "separando itens", "previsao": "13/08/2026"},
}


def consultar_pedido(numero: str) -> dict:
    pedido = PEDIDOS.get(numero)
    if pedido is None:
        return {"encontrado": False, "numero": numero}

    return {
        "encontrado": True,
        "numero": numero,
        **pedido,
    }

Em produção, essa função poderia consultar uma API interna. Para aprender o fluxo, o dicionário em memória elimina dependências e deixa claro onde termina a IA e começa a regra de negócio.

Descreva a ferramenta com um esquema estrito

O modelo precisa conhecer o nome da função, sua finalidade e os argumentos aceitos. Na Responses API, a ferramenta pode ser descrita assim:

tools = [
    {
        "type": "function",
        "name": "consultar_pedido",
        "description": "Consulta o status de um pedido pelo número.",
        "strict": True,
        "parameters": {
            "type": "object",
            "properties": {
                "numero": {
                    "type": "string",
                    "description": "Identificador no formato AM-1234",
                }
            },
            "required": ["numero"],
            "additionalProperties": False,
        },
    }
]

Com strict: True, a chamada deve respeitar o esquema. A documentação oficial recomenda o modo estrito e exige que os campos sejam declarados em required e que objetos usem additionalProperties: false. Isso reduz argumentos inesperados, mas não substitui a validação da sua aplicação.

Uma string pode estar correta para o JSON Schema e ainda ser inválida para o negócio. AM-1042 atende ao formato esperado; qualquer-coisa continua sendo uma string. Por isso, vamos verificar o padrão antes de consultar os dados.

Detecte, valide e execute a chamada

Agora envie a pergunta junto com a definição da ferramenta. Desativaremos chamadas paralelas para que este exemplo aceite no máximo uma função por rodada:

import json
import re

from openai import OpenAI

client = OpenAI()

funcoes_permitidas = {
    "consultar_pedido": consultar_pedido,
}

input_list = [
    {"role": "user", "content": "Onde está o pedido AM-1042?"}
]

response = client.responses.create(
    model="gpt-5.6",
    input=input_list,
    tools=tools,
    parallel_tool_calls=False,
)

input_list += response.output

for item in response.output:
    if item.type != "function_call":
        continue

    if item.name not in funcoes_permitidas:
        resultado = {"erro": "ferramenta_nao_permitida"}
    else:
        try:
            argumentos = json.loads(item.arguments)
            numero = argumentos["numero"].strip().upper()

            if not re.fullmatch(r"AM-\d{4}", numero):
                raise ValueError("Número de pedido inválido")

            resultado = funcoes_permitidas[item.name](numero=numero)
        except (KeyError, ValueError, json.JSONDecodeError) as erro:
            resultado = {"erro": str(erro)}

    input_list.append(
        {
            "type": "function_call_output",
            "call_id": item.call_id,
            "output": json.dumps(resultado, ensure_ascii=False),
        }
    )

Nunca use eval() para executar o nome ou os argumentos enviados pelo modelo. O dicionário funcoes_permitidas é uma lista explícita de capacidades. Se aparecer outro nome, a aplicação recusa. O call_id liga o resultado à solicitação correta.

Devolva o resultado e gere a resposta final

O retorno de uma ferramenta deve ser uma string; JSON serializado funciona bem porque preserva campos e erros. Depois de adicionar function_call_output à lista, faça uma segunda chamada:

final = client.responses.create(
    model="gpt-5.6",
    input=input_list,
    tools=tools,
    instructions=(
        "Responda em português, de forma objetiva. "
        "Não invente status ou previsão ausentes no resultado da ferramenta."
    ),
)

print(final.output_text)

Para o pedido do exemplo, a resposta poderá informar que ele está em transporte e apresentar a previsão. Se o número não existir, o modelo recebe encontrado: false e deve explicar isso, sem criar dados. A qualidade depende tanto das instruções quanto da clareza do resultado devolvido pela função.

Em uma aplicação real, encapsule esse ciclo em uma função ou serviço. Também trate falhas temporárias da API interna, tempo limite e respostas sem chamada de ferramenta. O modelo pode responder diretamente quando não precisa consultar nada.

Proteja ferramentas com efeitos reais

Consultar um pedido é uma operação de leitura e oferece um bom primeiro projeto. Cancelar compra, enviar e-mail, emitir reembolso ou alterar cadastro exige controles adicionais. Um argumento bem formatado não prova que o usuário tem permissão para a ação.

Adote estas regras antes de disponibilizar ferramentas de escrita:

  • Autorização fora do modelo: valide usuário, conta e escopo no backend.
  • Confirmação explícita: mostre o efeito, o destinatário e o valor antes de uma ação irreversível.
  • Idempotência: use uma chave para impedir reembolsos ou envios duplicados.
  • Limites: defina valores máximos, formatos, tempo de execução e quantidade de chamadas.
  • Logs seguros: registre ferramenta, resultado e duração, removendo chaves e dados sensíveis.
  • Privilégio mínimo: cada ferramenta deve acessar apenas os dados necessários.

Também separe ferramentas de leitura das que causam efeitos. Comece com consultas, observe erros reais e só depois adicione ações. Function calling não transforma o modelo em autoridade; ele cria uma interface estruturada entre a intenção do usuário e uma capacidade controlada pelo sistema.

Checklist prático e próximo passo

Antes de colocar o fluxo em produção, confirme:

  • o nome e a descrição da ferramenta são específicos;
  • o esquema usa modo estrito, campos obrigatórios e bloqueio de propriedades extras;
  • os argumentos passam por validação de formato e regra de negócio;
  • apenas funções presentes na lista permitida podem ser executadas;
  • o resultado referencia o call_id recebido;
  • erros viram respostas controladas, sem expor segredos;
  • ações sensíveis exigem autorização, confirmação e idempotência;
  • logs e métricas permitem investigar o fluxo.

Execute o exemplo, troque o número do pedido e teste três cenários: pedido existente, identificador inválido e pedido não encontrado. Depois, substitua o dicionário por uma função de leitura do seu próprio sistema. Na próxima evolução, você poderá oferecer mais de uma ferramenta e criar um roteador seguro, mantendo validação e observabilidade em cada chamada.

Python + IA: Fundamentos e Projetos Práticos

Saídas estruturadas com IA: JSON confiável para automações em Python

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Este site utiliza o Akismet para reduzir spam. Saiba como seus dados em comentários são processados.