Chamadas de funções: Responses API e Chat Completions em comparação

Comparação ao nível do protocolo entre definições de funções, identificadores de chamada, resultados, argumentos em transmissão contínua, autorização, idempotência e rotas.

Chamadas de funções: Responses API e Chat Completions em comparação

Responses e Chat Completions podem pedir que uma aplicação execute uma função, mas representam o ciclo de ferramentas de formas diferentes. Chat Completions define funções em tools[].function, devolve message.tool_calls e recebe resultados como mensagens role: "tool". Responses usa definições planas, itens de saída function_call e resultados function_call_output ligados por call_id.

O modelo não executa a função. O código da aplicação deve validar argumentos, autorizar a operação, executá-la, devolver o resultado e impedir efeitos secundários duplicados quando houver uma repetição do pedido.

O ciclo de ferramentas tem quatro etapas

1. Declarar uma função permitida e o respetivo esquema de argumentos
2. Receber uma ou mais chamadas propostas pelo modelo
3. Validar, autorizar e executar na aplicação
4. Devolver cada resultado com o identificador de correlação da chamada

Só depois da quarta etapa o modelo pode responder com base no resultado. Outra ferramenta inicia uma nova ronda com um novo ID de chamada. O guia OpenAI sobre Function Calling descreve este intercâmbio em vários passos.

Compare os contratos de transporte

Aspecto Responses API Chat Completions
Definição Item plano em tools[] Campos em tools[].function
Chamada proposta Item de saída function_call tool_calls[] da mensagem do assistente
Correlação call_id id, devolvido como tool_call_id
Nome function_call.name tool_calls[].function.name
Argumentos Cadeia em function_call.arguments Cadeia em tool_calls[].function.arguments
Resultado function_call_output Mensagem role: "tool"
Streaming Eventos de argumentos tipados Fragmentos delta.tool_calls[]
Texto final Itens de saída / função auxiliar choices[0].message.content

Não relacione chamadas pela posição na lista. As chamadas paralelas e os fragmentos podem terminar noutra ordem. O ID explícito é a chave estável.

Defina um esquema de função estrito

{
  "type": "object",
  "properties": {
    "order_id": {
      "type": "string",
      "pattern": "^ORDER-[0-9]{4}$"
    }
  },
  "required": ["order_id"],
  "additionalProperties": false
}

strict: true exige conformidade ao modelo, mas a análise e a validação continuam na aplicação. O suporte de pattern varia, por isso aplique o mesmo teste de compatibilidade de Structured Outputs.

Implemente com Responses API

import OpenAI from "openai";

const client = new OpenAI({
  apiKey: process.env.MODELFLARE_API_KEY,
  baseURL: "https://modelflare.dev/v1",
});

const model = process.env.MODEL_ID;
if (!model) throw new Error("MODEL_ID é obrigatório");

const orders = new Map([
  ["ORDER-1001", { status: "in_transit", eta: "2026-08-06" }],
]);

const tools = [
  {
    type: "function",
    name: "get_delivery_status",
    description: "Devolve o estado atual de entrega de uma encomenda.",
    parameters: {
      type: "object",
      properties: {
        order_id: { type: "string", pattern: "^ORDER-[0-9]{4}$" },
      },
      required: ["order_id"],
      additionalProperties: false,
    },
    strict: true,
  },
];

function executeTool(name, rawArguments) {
  if (name !== "get_delivery_status") {
    throw new Error(`Ferramenta não permitida: ${name}`);
  }

  const args = JSON.parse(rawArguments);
  if (!/^ORDER-[0-9]{4}$/.test(args.order_id)) {
    throw new Error("order_id inválido");
  }

  return orders.get(args.order_id) ?? { status: "not_found" };
}

const first = await client.responses.create({
  model,
  input: "Onde está a encomenda ORDER-1001?",
  tools,
  parallel_tool_calls: false,
});

const calls = first.output.filter((item) => item.type === "function_call");
if (calls.length === 0) {
  console.log(first.output_text);
  process.exit(0);
}

const toolOutputs = calls.map((call) => ({
  type: "function_call_output",
  call_id: call.call_id,
  output: JSON.stringify(executeTool(call.name, call.arguments)),
}));

const final = await client.responses.create({
  model,
  input: [...first.output, ...toolOutputs],
  tools,
  parallel_tool_calls: false,
});

console.log(final.output_text);

call.call_id e o call_id do resultado devem ser idênticos. Numa troca sem estado, devolva os itens de saída anteriores com os resultados. Não presuma que qualquer rota compatível com OpenAI guarda o estado da resposta.

Implemente com Chat Completions

import OpenAI from "openai";

const client = new OpenAI({
  apiKey: process.env.MODELFLARE_API_KEY,
  baseURL: "https://modelflare.dev/v1",
});

const model = process.env.MODEL_ID;
if (!model) throw new Error("MODEL_ID é obrigatório");

const orders = new Map([
  ["ORDER-1001", { status: "in_transit", eta: "2026-08-06" }],
]);

const tools = [
  {
    type: "function",
    function: {
      name: "get_delivery_status",
      description: "Devolve o estado atual de entrega de uma encomenda.",
      parameters: {
        type: "object",
        properties: {
          order_id: { type: "string", pattern: "^ORDER-[0-9]{4}$" },
        },
        required: ["order_id"],
        additionalProperties: false,
      },
      strict: true,
    },
  },
];

function executeTool(name, rawArguments) {
  if (name !== "get_delivery_status") {
    throw new Error(`Ferramenta não permitida: ${name}`);
  }

  const args = JSON.parse(rawArguments);
  if (!/^ORDER-[0-9]{4}$/.test(args.order_id)) {
    throw new Error("order_id inválido");
  }

  return orders.get(args.order_id) ?? { status: "not_found" };
}

const messages = [
  { role: "user", content: "Onde está a encomenda ORDER-1001?" },
];

const first = await client.chat.completions.create({
  model,
  messages,
  tools,
  parallel_tool_calls: false,
});

const assistant = first.choices[0].message;
const calls = assistant.tool_calls ?? [];
if (calls.length === 0) {
  console.log(assistant.content);
  process.exit(0);
}

messages.push(assistant);
for (const call of calls) {
  const result = executeTool(call.function.name, call.function.arguments);
  messages.push({
    role: "tool",
    tool_call_id: call.id,
    content: JSON.stringify(result),
  });
}

const final = await client.chat.completions.create({
  model,
  messages,
  tools,
  parallel_tool_calls: false,
});

console.log(final.choices[0].message.content);

A mensagem do assistente com as chamadas tem de surgir antes dos resultados. Omiti-la ou usar um tool_call_id incorreto cria um histórico inválido.

Trate argumentos de streaming como fragmentos

{"order é JSON incompleto, não inválido. Mantenha uma memória intermédia por chamada, acrescente cada incremento, aguarde a conclusão dos argumentos ou da resposta, analise a cadeia uma vez e execute apenas depois de validar. Responses usa eventos tipados; Chat Completions usa choices[].delta.tool_calls[]. Nunca execute ao receber o primeiro fragmento. Consulte o guia de streaming de APIs de IA.

Torne a execução segura e idempotente

  • aceite apenas nomes de funções registados;
  • limite o tamanho e valide o esquema completo;
  • autorize o utilizador ou a carga de trabalho para o recurso;
  • separe leitura de efeitos colaterais;
  • remova segredos do resultado;
  • defina prazos e limite as repetições em serviços dependentes;
  • registre uma referência segura.

Para efeitos secundários, derive uma chave de idempotência do pedido estável e do ID de chamada. Guarde o resultado antes de o devolver. Uma repetição devolve o resultado guardado em vez de iniciar outro reembolso, mensagem, deployment ou alteração de dados.

O nome da função e os argumentos produzidos pelo modelo são dados não fiáveis. Um esquema válido não concede autorização nem substitui uma transação.

Decida como tratar múltiplas chamadas

parallel_tool_calls: false simplifica a máquina de estados. Com paralelismo, relacione por ID de chamada, limite o número de chamadas e a concorrência, defina o impacto das falhas, devolva um resultado por chamada e serialize os efeitos cuja ordem importe. O paralelismo acelera leituras independentes, mas complica a autorização, as repetições e as falhas parciais.

Entenda o limite de compatibilidade do Modelflare

A Modelflare preserva definições estritas e estabelece correspondências entre os formatos suportados de Responses e Chat Completions nas rotas OpenAI/Codex elegíveis. Esta correspondência abrange deliberadamente menos do que todas as ferramentas de Responses.

As funções da aplicação podem ser representadas nos dois formatos. As ferramentas alojadas executadas pelo fornecedor, como pesquisa ou execução de código, não são equivalentes. Noutras famílias compatíveis com OpenAI, o Chat Completions é transmitido sem transformação até haver verificação; o contrato do fornecedor determina o suporte de tools, strict, chamadas paralelas, argumentos transmitidos e tool_choice.

Teste Evidência necessária
Chamada de leitura Nome, argumentos, ID de chamada, ligação do resultado e texto final
Argumentos inválidos Falha explícita sem execução
Função desconhecida Rejeição pela lista de permissões
Sem ferramenta Texto normal sem chamada inventada
Streaming Argumentos reconstruídos e ID correta
Pedido repetido Um efeito ou resultado guardado
Várias chamadas Relação independente da ordem
Rota de recurso Mesmo modelo, protocolo, esquema e contrato

Use Encaminhamento fiável de APIs de IA para mudanças explícitas e Segurança das chaves de API de IA para separar cargas de trabalho e permissões.

Escolha o formato pelo contrato da aplicação

Use Responses para itens de saída tipados, o modelo de eventos, a continuação com estado e outros recursos verificados. Use Chat Completions quando a aplicação já possui um histórico estável e o contrato de ferramentas do fornecedor foi testado. Consulte Responses API e Chat Completions.

O padrão é o mesmo: lista explícita de ferramentas permitidas, esquema de argumentos estrito, validação na aplicação, autorização antes da execução, relação por ID de chamada, idempotência dos efeitos e resultado completo para o modelo. Estes controlos, e não o nome do endpoint, tornam o fluxo de trabalho fiável.