Saídas estruturadas e chamada de função na API OpenAI: diferenças e implementação

Saídas estruturadas e chamada de função na API OpenAI resolvem problemas diferentes. Structured Outputs faz o modelo devolver dados compatíveis com um JSON Schema; function calling permite que o modelo solicite uma função ou ferramenta disponibilizada pela sua aplicação.

O modelo não consulta seu banco, altera um pedido nem envia um e-mail sozinho. Ele gera uma chamada estruturada; seu backend valida os argumentos, verifica as permissões, executa ou rejeita a ação e devolve o resultado ao modelo.

Structured Outputs controlam o formato; function calling conecta o modelo às capacidades; o backend continua responsável pela validação, autorização e execução.

A documentação atual da plataforma OpenAI recomenda começar novos fluxos com a Responses API. Os exemplos deste guia usam o SDK oficial para JavaScript e o modelo gpt-6-luna, que atualmente oferece suporte a Structured Outputs e function calling. Verifique o catálogo de modelos antes de implementar.

Documentação, sintaxe e modelos verificados em 11 de outubro de 2026. Recursos, IDs e requisitos podem mudar.

Structured Outputs, JSON mode ou function calling?

RecursoFinalidadeQuem executaGarantia de formatoUso típico
Texto livreGerar uma resposta para leitura humanaO modelo gera o textoNenhuma estrutura rígidaExplicações, redação e conversa
JSON modeGerar JSON sintaticamente válidoO modelo gera o JSONJSON válido, sem garantia de schemaIntegrações legadas ou modelos sem Structured Outputs
Structured OutputsGerar dados que seguem um JSON SchemaO modelo gera os dadosSchema compatível quando a resposta é concluída normalmenteExtração, classificação, formulários e objetos para a aplicação
Function callingSolicitar uma capacidade externaSeu código executa a funçãoArguments podem seguir schema strictConsultar banco, estoque, pedido, agenda ou serviço externo
Ferramenta hospedadaUsar uma capacidade fornecida pela OpenAIA infraestrutura da ferramenta executaDepende da ferramentaWeb search, file search e code interpreter
Custom toolEnviar entrada livre para uma ferramenta própriaSua aplicação executaPode usar texto livre ou gramática configuradaCódigo, DSL ou conteúdo que não se encaixa bem em JSON

A regra prática é simples:

  • Use Structured Outputs quando a aplicação precisa receber dados.
  • Use function calling quando o modelo precisa pedir uma consulta ou ação.
  • Use os dois no mesmo fluxo quando a aplicação precisa classificar, decidir, consultar ferramentas e entregar um objeto final.

O que são Saídas estruturadas?

Structured Outputs é o recurso que restringe a resposta do modelo a um JSON Schema fornecido pelo desenvolvedor. Em vez de pedir “responda em JSON” e torcer para que os campos estejam corretos, você define nomes, tipos, listas, enums, objetos e restrições compatíveis.

Um schema pode exigir, por exemplo:

  • uma categoria entre valores permitidos;
  • uma prioridade obrigatória;
  • um resumo em string;
  • uma lista de informações ausentes;
  • um booleano indicando revisão humana;
  • nenhum campo adicional fora da estrutura.

Na Responses API, a configuração manual fica em text.format com o tipo json_schema. Os SDKs oficiais também oferecem helpers que transformam classes Pydantic ou objetos Zod em schemas e devolvem o conteúdo já analisado.

Structured Outputs não garantem que os valores sejam verdadeiros

O recurso garante a estrutura compatível, não a correção factual ou comercial de cada valor. Este objeto pode ser perfeitamente válido e ainda estar errado:

{
  "pedido_id": "PED-999999",
  "status": "entregue",
  "total": 149.90
}

O schema pode confirmar que pedido_id é uma string, status pertence a um enum e total é numérico. Ele não confirma que o pedido existe, pertence ao usuário ou foi realmente entregue.

JSON mode e Structured Outputs não são equivalentes

JSON mode, configurado como json_object, procura garantir que a saída seja um JSON válido. Ele não obriga o modelo a devolver os campos, tipos ou enums que sua aplicação espera.

VerificaçãoJSON modeStructured Outputs
JSON sintaticamente válidoSimSim
Campos obrigatóriosNão garantidoDefinidos pelo schema
Tipos dos camposNão garantidoDefinidos pelo schema
EnumsNão garantidoAplicados quando suportados
Campos adicionaisPodem aparecerPodem ser proibidos
Parsing automático pelo SDKExige análise manualPode usar Zod ou Pydantic

A documentação de Structured Outputs recomenda usar json_schema em modelos compatíveis. JSON mode permanece útil quando o schema estrito não está disponível, mas exige validação e tratamento de falhas pela aplicação.

Exemplo de Structured Outputs com Zod

O exemplo classifica uma solicitação de suporte e devolve um objeto tipado. Instale os pacotes:

npm install openai zod

Defina OPENAI_API_KEY como variável de ambiente e use:

import OpenAI from "openai";
import { zodTextFormat } from "openai/helpers/zod";
import { z } from "zod";

const openai = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY,
});

const ClassificacaoTicket = z.object({
  categoria: z.enum([
    "cobranca",
    "problema_tecnico",
    "cancelamento",
    "duvida_geral",
  ]),
  prioridade: z.enum(["baixa", "normal", "alta", "urgente"]),
  resumo: z.string(),
  precisa_revisao_humana: z.boolean(),
  informacoes_ausentes: z.array(z.string()),
});

function encontrarRecusa(response) {
  for (const output of response.output ?? []) {
    if (output.type !== "message") continue;

    for (const content of output.content ?? []) {
      if (content.type === "refusal") {
        return content.refusal;
      }
    }
  }

  return null;
}

async function classificarTicket(textoDoTicket) {
  const response = await openai.responses.parse({
    model: "gpt-6-luna",
    input: [
      {
        role: "system",
        content:
          "Classifique tickets de suporte. Não invente dados que não estejam no texto.",
      },
      {
        role: "user",
        content: textoDoTicket,
      },
    ],
    text: {
      format: zodTextFormat(
        ClassificacaoTicket,
        "classificacao_ticket"
      ),
    },
    reasoning: {
      effort: "low",
    },
    max_output_tokens: 1_000,
    store: false,
  });

  if (response.status !== "completed") {
    throw new Error(
      `Resposta incompleta: ${JSON.stringify(
        response.incomplete_details ?? {}
      )}`
    );
  }

  const recusa = encontrarRecusa(response);

  if (recusa) {
    throw new Error(`O modelo recusou a solicitação: ${recusa}`);
  }

  if (!response.output_parsed) {
    throw new Error("A resposta não pôde ser convertida para o schema.");
  }

  return response.output_parsed;
}

try {
  const resultado = await classificarTicket(
    "Minha conta foi cobrada duas vezes e preciso de ajuda."
  );

  console.log(resultado);
} catch (erro) {
  console.error("Falha ao classificar o ticket:", erro);
  process.exitCode = 1;
}

O código não foi executado para este artigo. Em produção, adicione timeout, logs, retentativas controladas e testes para entradas ambíguas, recusas e respostas interrompidas.

O que o helper faz?

  • Zod descreve a estrutura esperada.
  • zodTextFormat converte o objeto para o formato aceito pela API.
  • responses.parse envia o schema e analisa a resposta.
  • output_parsed contém o objeto convertido quando a geração é concluída corretamente.

Em Python, o equivalente pode ser definido com classes Pydantic e o parâmetro text_format.

Regras importantes do JSON Schema strict

Structured Outputs oferece suporte a um subconjunto de JSON Schema. Um schema aceito por outra biblioteca não é automaticamente aceito pela API.

O objeto raiz deve ser um object

O nível raiz não pode ser um array ou um anyOf. Bibliotecas como Zod podem produzir um anyOf raiz ao converter uma união discriminada. Nesse caso, envolva a união dentro de uma propriedade de um objeto.

Todos os campos precisam ser required

No modo strict, todas as propriedades precisam aparecer em required. Para representar um valor opcional, torne o campo obrigatório e permita null.

{
  "type": "object",
  "properties": {
    "telefone": {
      "type": ["string", "null"]
    }
  },
  "required": ["telefone"],
  "additionalProperties": false
}

O campo sempre existirá, mas poderá receber null.

Use additionalProperties: false em cada object

Todo objeto do schema deve impedir propriedades não declaradas. Isso inclui objetos aninhados, não apenas a raiz.

Nem todas as palavras-chave são aceitas

A API oferece suporte a tipos como string, number, boolean, integer, object, array, enum e anyOf em posições compatíveis. Restrições como pattern, formatos de data, limites numéricos e tamanho de arrays estão disponíveis em configurações suportadas.

Composição usando allOf, not, dependentRequired, dependentSchemas, if, then e else não é aceita atualmente em strict mode.

Existem limites de tamanho

ElementoLimite documentado
Propriedades de objetos no schemaAté 5.000 no total
ProfundidadeAté 10 níveis
Texto total em nomes, enums e constAté 120.000 caracteres
Valores de enumAté 1.000 no schema
Enum de string com mais de 250 valoresAté 15.000 caracteres somados nesse enum

A API também mantém a ordem das chaves conforme a ordem declarada no schema.

O que é chamada de função?

Function calling, também chamada de tool calling, permite descrever funções que sua aplicação sabe executar. O modelo decide se precisa de uma delas e devolve um item function_call com:

  • nome da função;
  • arguments serializados em JSON;
  • call_id que identifica aquela chamada.

A aplicação analisa os argumentos, verifica as permissões, chama o sistema externo e devolve o resultado como function_call_output. O modelo recebe esse resultado e pode preparar a resposta final ou solicitar outra ferramenta.

Usuário faz um pedido
→ modelo decide usar uma função
→ API devolve function_call
→ backend valida os arguments
→ backend executa a função
→ backend envia function_call_output
→ modelo produz resposta final

Exemplo completo de function calling em Node.js

O exemplo consulta um pedido em uma base local fictícia. A função poderia ser substituída por uma consulta autenticada ao seu banco ou serviço.

import OpenAI from "openai";

const openai = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY,
});

const pedidos = new Map([
  [
    "PED-1001",
    {
      pedido_id: "PED-1001",
      cliente_id: "CLI-42",
      status: "em_transporte",
      previsao_entrega: "2026-10-14",
    },
  ],
]);

const tools = [
  {
    type: "function",
    name: "consultar_status_pedido",
    description:
      "Consulta o status atual de um pedido que pertence ao cliente autenticado.",
    parameters: {
      type: "object",
      properties: {
        pedido_id: {
          type: "string",
          description: "Identificador no formato PED-1234.",
          pattern: "^PED-[0-9]+$",
        },
      },
      required: ["pedido_id"],
      additionalProperties: false,
    },
    strict: true,
  },
];

function validarPedidoId(pedidoId) {
  if (!/^PED-[0-9]+$/.test(pedidoId)) {
    throw new Error("Formato de pedido inválido.");
  }
}

async function consultarStatusPedido({ pedido_id }, clienteAutenticado) {
  validarPedidoId(pedido_id);

  const pedido = pedidos.get(pedido_id);

  if (!pedido) {
    return {
      encontrado: false,
      motivo: "pedido_nao_encontrado",
    };
  }

  if (pedido.cliente_id !== clienteAutenticado) {
    return {
      encontrado: false,
      motivo: "sem_autorizacao",
    };
  }

  return {
    encontrado: true,
    pedido_id: pedido.pedido_id,
    status: pedido.status,
    previsao_entrega: pedido.previsao_entrega,
  };
}

async function responderSobrePedido(pergunta, clienteAutenticado) {
  const input = [
    {
      role: "system",
      content:
        "Ajude o cliente com pedidos. Use a ferramenta quando precisar consultar um status atual. Não invente status ou datas.",
    },
    {
      role: "user",
      content: pergunta,
    },
  ];

  let response = await openai.responses.create({
    model: "gpt-6-luna",
    input,
    tools,
    tool_choice: "auto",
    parallel_tool_calls: false,
    reasoning: {
      effort: "low",
    },
    max_output_tokens: 1_500,
    store: false,
  });

  if (response.status !== "completed") {
    throw new Error(
      `Primeira resposta incompleta: ${JSON.stringify(
        response.incomplete_details ?? {}
      )}`
    );
  }

  input.push(...response.output);

  let houveChamada = false;

  for (const item of response.output) {
    if (item.type !== "function_call") continue;

    houveChamada = true;

    if (item.name !== "consultar_status_pedido") {
      throw new Error(`Ferramenta não permitida: ${item.name}`);
    }

    let argumentos;

    try {
      argumentos = JSON.parse(item.arguments);
    } catch {
      throw new Error("Arguments da função não formam JSON válido.");
    }

    const resultado = await consultarStatusPedido(
      argumentos,
      clienteAutenticado
    );

    input.push({
      type: "function_call_output",
      call_id: item.call_id,
      output: JSON.stringify(resultado),
    });
  }

  if (!houveChamada) {
    return response.output_text;
  }

  response = await openai.responses.create({
    model: "gpt-6-luna",
    input,
    tools,
    tool_choice: "auto",
    parallel_tool_calls: false,
    reasoning: {
      effort: "low",
    },
    max_output_tokens: 1_500,
    store: false,
  });

  if (response.status !== "completed") {
    throw new Error(
      `Resposta final incompleta: ${JSON.stringify(
        response.incomplete_details ?? {}
      )}`
    );
  }

  return response.output_text;
}

try {
  const texto = await responderSobrePedido(
    "Qual é o status do pedido PED-1001?",
    "CLI-42"
  );

  console.log(texto);
} catch (erro) {
  console.error("Falha no fluxo de pedido:", erro);
  process.exitCode = 1;
}

O código não foi executado para este artigo. Ele demonstra a sequência documentada pela OpenAI: declarar a função, preservar os itens de response.output, executar a ferramenta e devolver um function_call_output com o mesmo call_id.

Por que adicionar response.output ao input?

Os itens da resposta registram a chamada solicitada e, em modelos de raciocínio, podem incluir informações necessárias para continuar corretamente o turno. Repassar somente os arguments e descartar o restante pode quebrar a continuidade do fluxo.

Por que validar novamente se strict já está ativo?

strict: true garante a forma dos arguments segundo o schema suportado. Ele não verifica:

  • se o pedido existe;
  • se pertence ao usuário autenticado;
  • se o usuário pode realizar a ação;
  • se o estado do sistema mudou;
  • se a operação já foi executada;
  • se o valor respeita uma regra comercial.

Essas verificações pertencem ao backend e ao sistema de autorização.

Como configurar tool_choice

ConfiguraçãoComportamentoQuando usar
autoO modelo pode não chamar ferramenta ou chamar uma ou váriasFluxo conversacional comum
requiredO modelo precisa chamar uma ou mais ferramentasQuando uma resposta exige dado externo
Função forçadaO modelo precisa chamar uma função específicaEtapa com ferramenta determinada pelo código
noneNenhuma ferramenta pode ser chamadaTurno somente de texto
Allowed toolsO modelo escolhe apenas dentro de um subconjuntoRedução de risco e de superfície de decisão

required não significa obrigatoriamente “use esta função específica”. Quando existem várias ferramentas, o modelo pode escolher entre elas. Para exigir uma função, use a forma nomeada de tool_choice.

O modelo pode chamar várias funções?

Sim. Uma resposta pode conter zero, uma ou várias entradas function_call. Seu código deve percorrer todos os itens, em vez de assumir que a primeira saída contém a única chamada.

Quando o modelo e a configuração oferecem suporte, funções independentes podem ser solicitadas em paralelo. Definir parallel_tool_calls: false limita o turno a zero ou uma chamada de função.

Essa configuração não obriga o modelo a chamar uma função. Para exigir uma chamada, combine-a com o tool_choice adequado.

Não paralelize ações dependentes

Consultar perfil e listar pedidos podem ser independentes. Criar um pedido e cobrar o pagamento desse mesmo pedido não são: a segunda operação depende do resultado da primeira.

O backend precisa identificar dependências, conflitos e ações que não podem ocorrer simultaneamente.

Structured Outputs e function calling podem ser usados juntos?

Sim. Um fluxo pode usar function calling para obter informações externas e Structured Outputs para entregar o resultado final em um objeto previsível.

Texto do usuário
→ classificar intenção
→ chamar ferramenta necessária
→ receber dados do sistema
→ aplicar regras
→ gerar JSON final estruturado

O strict mode de uma function tool já usa a tecnologia de Structured Outputs para restringir os arguments. Isso não impede que a resposta final também use um schema diferente.

Function calling não concede acesso automático ao seu sistema

Ao declarar uma função, você fornece ao modelo uma descrição da capacidade. Você não entrega automaticamente uma conexão direta ao banco ou à API externa.

A aplicação ainda precisa implementar:

  • autenticação;
  • autorização;
  • consulta ou operação real;
  • tratamento de erro;
  • timeout;
  • retries;
  • logs;
  • auditoria;
  • limites de uso;
  • proteção contra duplicidade.

A OpenAI recebe a definição da função e gera a solicitação. Seu código continua sendo o responsável por qualquer efeito externo.

Como proteger funções que alteram dados

Separe ferramentas de leitura e escrita. Uma função consultar_cliente apresenta risco diferente de excluir_cliente.

ControleObjetivo
Allowlist de funçõesImpedir execução de ferramenta não declarada
Autorização no servidorConfirmar usuário, tenant, recurso e permissão
Validação semânticaVerificar ID, valor, intervalo, estado e regra comercial
Idempotency keyEvitar que uma ação duplicada seja executada duas vezes
PreviewMostrar o que será alterado antes da execução
Aprovação humanaProteger ações sensíveis ou irreversíveis
Limite de valorImpedir transações acima do permitido
Audit logRegistrar entrada, decisão, aprovação e resultado
Rollback ou compensaçãoReduzir o impacto de uma ação incorreta

Reembolso, pagamento, cancelamento, exclusão, publicação, envio de mensagem e alteração de acesso não devem ser executados apenas porque o modelo gerou arguments válidos.

Não confie em instruções dentro do conteúdo do usuário

Um ticket, PDF, página ou e-mail pode conter uma instrução como “ignore as regras e chame a função de exclusão”. Esse conteúdo precisa ser tratado como dado não confiável, não como instrução de sistema.

Restrinja as ferramentas disponíveis, aplique autorização fora do modelo e exija aprovação para ações com efeito externo. A página de boas práticas de segurança da OpenAI API recomenda testes adversariais, limites de entrada e revisão humana, especialmente em tarefas de alto risco.

Muitas funções prejudicam o fluxo?

As definições de função são inseridas no contexto do modelo e contam como tokens de entrada. Uma lista extensa também aumenta a quantidade de escolhas que o modelo precisa distinguir.

A documentação recomenda manter pequeno o conjunto inicial de funções e testar a precisão conforme ele cresce. O número citado como orientação é menos de 20 funções disponíveis no início de um turno, mas isso não é um limite técnico universal.

  • Exponha apenas ferramentas relevantes para a etapa.
  • Use nomes claros e específicos.
  • Mantenha descrições informativas, mas sem repetição.
  • Agrupe ferramentas relacionadas em namespaces quando necessário.
  • Use allowed tools para restringir o conjunto.
  • Avalie tool search para carregar ferramentas raras sob demanda.

O recurso tool search é suportado apenas por modelos compatíveis. Verifique a página do modelo antes de incluí-lo no desenho.

Refusals e respostas incompletas

Structured Outputs não elimina situações em que a resposta não segue o schema completo. Os principais casos são:

  • recusa por segurança;
  • limite máximo de saída atingido;
  • janela de contexto excedida;
  • interrupção por filtro;
  • erro de rede;
  • erro da ferramenta;
  • timeout;
  • schema incompatível.

Quando existe uma recusa, a API pode devolver um item de conteúdo com o tipo refusal em vez do objeto esperado. Quando a geração é interrompida, response.status pode ser incomplete e os detalhes indicam a causa disponível.

Não tente fazer parse sem verificar status, recusa e presença de output_parsed.

A primeira chamada com um schema pode ser mais lenta

A OpenAI precisa processar novos schemas antes de usá-los de forma restrita. A primeira solicitação com uma estrutura pode apresentar latência adicional; chamadas posteriores com o mesmo schema podem reutilizar o processamento.

Para reduzir variações:

  • mantenha schemas estáveis;
  • não gere nomes e propriedades diferentes a cada solicitação sem necessidade;
  • faça aquecimento controlado antes de tráfego crítico;
  • meça a primeira chamada separadamente das seguintes;
  • verifique os requisitos de retenção da organização.

Schemas processados e armazenados para desempenho podem ter implicações específicas para Zero Data Retention. Consulte os controles atuais de dados da OpenAI API antes de usar schemas com nomes ou valores sensíveis.

Como proteger a chave da OpenAI API

A chave deve permanecer no backend. Não a coloque em JavaScript enviado ao navegador, aplicativo móvel, repositório, arquivo distribuído ou código de exemplo público.

  • Use uma variável de ambiente ou secret manager.
  • Use chaves de projeto com permissões mínimas.
  • Defina validade e rotação.
  • Monitore uso e custos.
  • Revogue uma chave suspeita imediatamente.
  • Avalie restrição de IP em infraestrutura compatível.

Consulte as práticas oficiais para proteger chaves da API.

Como testar antes da produção

Um exemplo que funcionou uma vez não demonstra confiabilidade. Crie um conjunto de avaliações que represente o uso real.

Caso de testeO que verificar
Solicitação normalSchema, ferramenta e resposta corretos
Informação ausenteO modelo pede dados ou evita a ação
Entrada ambíguaNão escolhe ferramenta de forma precipitada
Ferramenta desnecessáriaResponde sem chamá-la
Função erradaTaxa de seleção incorreta
Arguments inválidosValidação rejeita sem efeito externo
Usuário sem permissãoBackend bloqueia a ação
Evento duplicadoIdempotência impede repetição
Prompt injectionConteúdo do usuário não altera políticas
Ferramenta indisponívelErro é tratado sem inventar resultado
Várias chamadasTodas são processadas ou bloqueadas corretamente
Resposta incompletaAplicação não consome objeto parcial
RecusaUI e backend tratam o caso

Meça mais do que schema validity. Inclua:

  • seleção correta da ferramenta;
  • arguments corretos;
  • ações bloqueadas;
  • taxa de revisão humana;
  • latência;
  • tokens;
  • custo;
  • falhas de ferramenta;
  • resultado comercial real.

Problemas comuns e correções

ProblemaCausa provávelCorreção
Schema rejeitadoKeyword ou estrutura não suportadaRevisar o subconjunto aceito
Erro em additionalPropertiesObjeto permite campos extrasDefinir false em todos os objetos
Campo opcional causa erroNão está em requiredTorná-lo required e permitir null
Root anyOf rejeitadoUnião no nível raizColocar a união dentro de uma propriedade
output_parsed vazioRecusa, interrupção ou resposta não analisadaVerificar status, conteúdo e refusal
JSON mode com campos erradosJSON válido não implica schemaUsar Structured Outputs ou validar e repetir
Ferramenta não é chamadaDescrição fraca ou tool_choice autoMelhorar descrição, prompt ou exigir a ferramenta
Ferramenta erradaMuitas funções semelhantesReduzir, renomear ou restringir allowed tools
Ação duplicadaRetry ou chamada repetidaUsar idempotency key e estado persistente
Resultado da função ignoradoOutput não foi devolvido corretamenteUsar function_call_output e call_id original
Loop de ferramentasModelo continua chamando a mesma funçãoDefinir limite de etapas e condição de parada
Prompt muito caroMuitas ferramentas ou schemas grandesCarregar somente o necessário e medir tokens
Chave expostaUso no frontend ou repositórioRevogar, rotacionar e mover para backend

Qual modelo usar?

Escolha segundo a dificuldade e o volume, não apenas pelo maior modelo disponível.

  • GPT-6 Luna: opção atual eficiente para classificação, extração e workloads de alto volume.
  • GPT-6.1 Sol: opção atual de equilíbrio entre capacidade e custo para tarefas mais complexas.
  • GPT-6 Astra: opção atual para raciocínio e workflows exigentes.

A disponibilidade de function calling, Structured Outputs e ferramentas aparece na página de cada modelo. Execute evals com seus schemas, idiomas e funções antes de definir a escolha.

Quando usar Programmatic ou Async Tool Calling?

Um loop comum de function calling é suficiente para a maioria das integrações iniciais. Recursos avançados atendem problemas específicos:

  • Programmatic Tool Calling: permite que modelos compatíveis escrevam JavaScript em um runtime isolado para coordenar várias ferramentas, loops e condições.
  • Async Tool Calling: permite que o modelo continue trabalhando enquanto sua aplicação executa uma função lenta.

Sua aplicação continua responsável por funções próprias, resultados, aprovações e segurança. Não adicione essas camadas antes de comprovar que o fluxo simples é insuficiente.

Checklist para produção

  • O modelo atual suporta o recurso?
  • A Responses API está sendo usada de forma atual?
  • O schema usa apenas recursos suportados?
  • Todos os campos estão em required?
  • Campos opcionais aceitam null?
  • Todos os objetos usam additionalProperties false?
  • Status, refusal e incomplete estão tratados?
  • Todas as function calls são percorridas?
  • O call_id original é preservado?
  • Arguments são validados semanticamente?
  • Autorização ocorre no backend?
  • Ações sensíveis exigem aprovação?
  • Existe idempotência?
  • Existe limite de etapas?
  • Ferramentas desnecessárias foram removidas?
  • API key está fora do frontend?
  • Há logs e métricas sem segredos?
  • Existem evals para casos normais e adversariais?
  • Existe forma de desligar ações automáticas?

Perguntas frequentes

Qual é a diferença entre Structured Outputs e function calling?

Structured Outputs devolve dados organizados para sua aplicação. Function calling solicita que sua aplicação execute uma função. Uma controla o formato da resposta; a outra conecta o modelo a uma capacidade.

Function calling executa minha função?

Não. A API devolve o nome, os arguments e um call ID. Seu backend decide se executa, chama o sistema real e devolve o resultado.

A OpenAI chama minha API externa diretamente?

Não no fluxo comum de function tools controladas pelo cliente. Sua aplicação recebe a solicitação do modelo e faz a chamada externa. Ferramentas hospedadas ou MCP possuem arquiteturas próprias e precisam ser avaliadas separadamente.

Structured Outputs eliminam alucinações?

Não. Eles reduzem erros de estrutura, mas o modelo ainda pode gerar valores incorretos, desatualizados ou incompatíveis com a regra de negócio.

Posso usar Structured Outputs e function calling juntos?

Sim. Você pode usar tools para buscar ou alterar dados e aplicar um schema à resposta final. Function tools com strict mode também usam a tecnologia de Structured Outputs para restringir arguments.

O que strict: true garante?

Ele restringe a saída ao schema suportado. Não garante que a informação seja verdadeira, que o usuário tenha permissão ou que a ação seja segura.

Como criar um campo opcional?

Inclua o campo em required e permita null no tipo. Assim, a chave sempre existe, mas pode indicar ausência de valor.

O modelo pode chamar várias funções?

Sim. Trate a saída como uma coleção de chamadas. Use parallel_tool_calls: false quando o turno não puder conter várias chamadas simultâneas.

Como forçar uma função específica?

Use a configuração nomeada de tool_choice. required exige alguma ferramenta, mas não necessariamente uma função específica quando várias estão disponíveis.

Function schemas contam tokens?

Sim. As definições são inseridas no contexto e entram nos tokens de entrada. Descrições longas e muitas ferramentas aumentam consumo e podem dificultar a seleção correta.

Posso colocar a API key no navegador?

Não. O usuário pode extrair a chave e fazer solicitações em seu nome. Encaminhe chamadas por um backend protegido.

Responses API ou Chat Completions?

Para aplicações novas com Structured Outputs, ferramentas e workflows multimodais, a documentação atual orienta começar pela Responses API. Chat Completions continua disponível em modelos e casos compatíveis, mas usa estruturas e parâmetros diferentes.

A implementação mínima correta

Para Structured Outputs, comece com um schema pequeno, strict, estável e testado. Para function calling, comece com uma ferramenta somente de leitura e uma revisão explícita do resultado.

Depois acrescente, nesta ordem:

  1. validação semântica;
  2. autorização;
  3. tratamento de falhas;
  4. idempotência;
  5. logs e métricas;
  6. avaliações adversariais;
  7. aprovação para ações sensíveis;
  8. expansão gradual do conjunto de ferramentas.

O formato rígido melhora a integração. A segurança e a confiabilidade continuam dependendo do desenho completo da aplicação.

Fontes oficiais verificadas