A chamada programática de ferramentas permite que um modelo escreva e execute JavaScript para coordenar suas ferramentas. Um programa pode chamar ferramentas em paralelo, usar loops e condições e manter resultados intermediários no ambiente de execução hospedado. Isso é útil quando uma tarefa precisa de uma sequência de chamadas de ferramentas relacionadas ou precisa processar grandes volumes de saída das ferramentas antes de retornar um resultado.
Na API Responses, seu aplicativo decide se a chamada programática de ferramentas está disponível e quais ferramentas elegíveis o modelo pode chamar diretamente, por meio de um programa ou das duas formas. O aplicativo continua executando todas as chamadas de ferramentas sob responsabilidade do cliente. A API de Agentes habilita a chamada programática de ferramentas por padrão e gerencia o loop do agente para você.
Consulte a página do modelo antes de habilitar a chamada programática de ferramentas.
Entenda o ambiente de execução
A OpenAI executa cada programa gerado em um novo ambiente de execução V8 isolado. O ambiente oferece suporte a JavaScript com await no nível superior, mas não disponibiliza Node.js, instalação de pacotes, acesso direto à rede, um sistema de arquivos de uso geral, execução de subprocessos, um console nem estado JavaScript persistente entre execuções de programas. Os programas só podem interagir com sistemas externos por meio das ferramentas habilitadas na requisição e podem emitir saídas com text(...) ou image(...).
Para requisições à API Responses, a chamada programática de ferramentas oferece suporte a fluxos de trabalho com zero retenção de dados (ZDR) sem exigir um contêiner persistente de execução de código. A ZDR precisa estar habilitada para a organização ou o projeto; definir store: false permite a continuação sem estado, mas não habilita a ZDR por si só. A elegibilidade e a retenção dependem da requisição completa, incluindo o modelo, as ferramentas e os serviços de terceiros utilizados; consulte os controles de dados.
Escolha quando usar a chamada programática de ferramentas
Use a chamada programática de ferramentas quando uma etapa tiver um fluxo de controle previsível e o código puder retornar um resultado estruturado menor. Use a chamada direta de ferramentas quando uma única chamada for suficiente, cada resultado exigir uma nova avaliação do modelo ou o trabalho exigir aprovação ou preservação de citações ou artefatos nativos.
| Tipo de tarefa | Modo recomendado |
|---|---|
| Uma única consulta ou ação | Use a chamada direta de ferramentas. |
| Vários resultados que o código pode filtrar, combinar, classificar, agregar, validar ou dos quais pode remover duplicatas | Use a chamada programática de ferramentas quando o programa puder retornar um resultado estruturado menor. |
| Chamadas dependentes com fluxo de dados previsível | Use a chamada programática de ferramentas quando o código puder determinar os argumentos das chamadas seguintes e os limites e o comportamento em caso de falha forem explícitos. |
| Pesquisa adaptativa ou avaliação semântica | Use a chamada direta de ferramentas quando cada resultado precisar influenciar a próxima decisão do modelo. |
| Operações de escrita ou ações que exigem atenção à aprovação | Use a chamada direta de ferramentas por padrão para manter um limite claro de autorização. |
| Validação final de citações ou artefatos nativos | Use a chamada direta de ferramentas, a menos que o programa preserve a saída nativa e valide todos os itens exigidos. |
Configure a chamada programática de ferramentas
Para a API Responses, adicione a ferramenta hospedada programmatic_tool_calling à requisição. Em seguida, defina allowed_callers em cada ferramenta elegível que o programa pode invocar.
[
{
"type": "function",
"name": "get_inventory",
"description": "Return an object with sku (string) and available_units (number).",
"parameters": {
"type": "object",
"properties": {
"sku": { "type": "string" }
},
"required": ["sku"],
"additionalProperties": false
},
"output_schema": {
"type": "object",
"properties": {
"sku": { "type": "string" },
"available_units": { "type": "number" }
},
"required": ["sku", "available_units"],
"additionalProperties": false
},
"allowed_callers": ["programmatic"]
},
{
"type": "programmatic_tool_calling"
}
]allowed_callers controla como o modelo pode invocar uma ferramenta:
| Valor | Comportamento |
|---|---|
Omitido ou ["direct"] | O modelo pode chamar a ferramenta diretamente. |
["programmatic"] | Somente o código em um item program pode chamar a ferramenta. |
["direct", "programmatic"] | O modelo pode chamar a ferramenta diretamente ou a partir de um programa. |
parameters descreve os argumentos da função. Quando uma função retorna dados estruturados previsíveis, output_schema descreve o objeto JSON codificado na string function_call_output.output dessa função. Defina ambos para que o JavaScript gerado possa usar os campos retornados de forma confiável.
Ferramentas compatíveis
Os seguintes tipos de ferramentas oferecem suporte a allowed_callers: ["programmatic"]:
functionecustommcpapply_patchshelllocal e hospedadocode_interpreter
Para ferramentas MCP, a política require_approval da ferramenta pode pausar o programa até que você aprove a chamada.
Para ferramentas hospedadas pela OpenAI, consulte as orientações de retenção de dados e segurança da ferramenta antes de habilitá-la em um programa.
Combine com a pesquisa de ferramentas
A pesquisa de ferramentas é executada como uma ferramenta de nível superior da Responses API, e não de dentro do JavaScript gerado. Ferramentas de função, personalizadas e MCP com defer_loading: true não estão disponíveis inicialmente para um programa. Depois que o modelo carrega uma ferramenta correspondente, um programa posterior pode invocá-la por meio de tools.* quando o allowed_callers dela inclui "programmatic". Um programa que já está em execução não pode invocar a pesquisa de ferramentas, portanto o modelo precisa carregar as ferramentas com carregamento adiado antes de iniciar um programa que precise delas.
Oriente o roteamento quando os dois modos estiverem disponíveis
Quando seu aplicativo permitir que o modelo chame uma função diretamente ou a partir de um programa, associe cada caminho a uma etapa específica do fluxo de trabalho. Instruções genéricas como "use a chamada programática de ferramentas com eficiência" não deixam claro o limite pretendido. Por exemplo:
<tool_orchestration>
Use Programmatic Tool Calling for [bounded stage] using only [eligible tools].
Run independent calls concurrently when safe. Use only documented tool input
and output fields.
Process and reduce the intermediate results, then emit exactly [program result shape],
including the evidence needed for the final answer.
Stop when [condition] is met. Retry transient failures at most [R] times.
Do not repeat completed calls or perform side-effecting actions. If a required
result is still missing, return a clear structured failure.
Use direct tool calls for [semantic judgment, approval, or final validation].
</tool_orchestration>
Veja um exemplo de como usar este modelo:
<tool_orchestration>
Use Programmatic Tool Calling to compare inventory with demand for sku_123
using only get_inventory and get_demand. Run both calls concurrently. Use
only documented tool input and output fields.
Process and reduce the intermediate results, then emit exactly one JSON object
with sku, available_units, requested_units, and shortage_units, where
shortage_units is max(requested_units - available_units, 0). Include
available_units and requested_units as evidence for the calculation.
Stop when both tool results contain the required fields. Retry transient
failures at most 1 time. Do not repeat completed calls or perform
side-effecting actions. If a required result is still missing, return a clear
structured failure.
Use direct tool calls only for approval before any inventory-changing action.
</tool_orchestration>
Para fluxos de trabalho que precisam dos dois modos, defina um único ponto de transição e evite alternar entre caminhos ou repetir o trabalho. Se houver uma alternativa segura, defina-a uma única vez e limite as novas tentativas.
Entenda os itens de resposta do programa
Cada chamada à API continua retornando o objeto padrão da Responses API. A chamada programática de ferramentas não introduz um envelope de resposta separado. Quando o modelo usa a chamada programática de ferramentas, o array output da resposta pode conter:
- Um item
programcontendo o JavaScript gerado, umcall_ide umfingerprintopaco usado para retomar ou reexecutar o programa. - Um item
function_callcriado pelo programa. Ele tem seu própriocall_id, que seu aplicativo usa para retornar o resultado da função. Seucaller.caller_idcorresponde aocall_iddo programa. - Um item
program_outputcontendo o resultado final e o status do programa. Seucall_idcorresponde aocall_iddo programa, e seustatusécompletedouincomplete.
Esses são itens separados de nível superior em response.output; o campo caller registra a relação de execução entre eles.
Por exemplo, um programa pode pausar enquanto seu aplicativo executa get_inventory e get_demand:
[
{
"type": "program",
"id": "prog_123",
"call_id": "call_prog_123",
"code": "const [stock, demand] = await Promise.all([tools.get_inventory({ sku: 'sku_123' }), tools.get_demand({ sku: 'sku_123' })]); text(JSON.stringify({ sku: stock.sku, available_units: stock.available_units, requested_units: demand.requested_units, shortage_units: Math.max(demand.requested_units - stock.available_units, 0) }));",
"fingerprint": "opaque_replay_state"
},
{
"type": "function_call",
"id": "fc_123",
"call_id": "call_inventory_123",
"name": "get_inventory",
"arguments": "{\"sku\":\"sku_123\"}",
"caller": {
"type": "program",
"caller_id": "call_prog_123"
}
},
{
"type": "function_call",
"id": "fc_456",
"call_id": "call_demand_123",
"name": "get_demand",
"arguments": "{\"sku\":\"sku_123\"}",
"caller": {
"type": "program",
"caller_id": "call_prog_123"
}
}
]Estes exemplos mostram apenas os itens relevantes de response.output; eles omitem o objeto padrão Responses que os contém. Depois que seu aplicativo retorna os resultados das funções aninhadas, uma resposta posterior pode conter o item program_output completo:
{
"type": "program_output",
"id": "prog_out_123",
"call_id": "call_prog_123",
"result": "{\"sku\":\"sku_123\",\"available_units\":42,\"requested_units\":31,\"shortage_units\":0}",
"status": "completed"
}A string JSON em program_output.result segue a estrutura de resultado do programa definida nas suas instruções. O item program_output que a contém segue o contrato da API mostrado acima. Esses contratos são distintos. Um item message final pode chegar junto com a saída do programa ou em uma resposta posterior, então continue até receber essa mensagem.
A OpenAI executa o JavaScript gerado pelo modelo no ambiente de execução hospedado. Seu aplicativo executa as chamadas de função retornadas que são de responsabilidade do cliente; ele não executa o JavaScript gerado.
Retorne o resultado da função como um function_call_output. Copie caller da chamada de função sem alterá-lo. O serviço usa esse valor para retomar o programa correto.
Continue após chamadas de função de responsabilidade do cliente
Um programa pode pausar mais de uma vez ao chegar a ferramentas de responsabilidade do cliente. Continue até que a resposta contenha uma mensagem final do assistente:
- Envie a solicitação com a ferramenta hospedada e as funções que permitem chamadas programáticas.
- Execute todas as chamadas de função retornadas que sejam de responsabilidade do cliente.
- Retorne o resultado de cada função com os valores originais de
call_idecaller. - Trate uma resposta incompleta antes de continuar.
- Se a resposta não contiver itens
function_callpendentes nem um itemmessagefinal, continue a partir dessa resposta. Comstore: false, reenvie os itens de saída; para uma resposta armazenada, useprevious_response_id. - Pare quando a resposta contiver um item
messagefinal. Leiaresponse.output_textou o conteúdo de recusa da mensagem.
O exemplo a seguir usa store: false, preserva todos os itens da resposta e retorna o resultado de cada função ao programa:
import json
from openai import OpenAI
client = OpenAI()
model = "gpt-6-astra"
def get_inventory(sku):
return {"sku": sku, "available_units": 42}
def get_demand(sku):
return {"sku": sku, "requested_units": 31}
implementations = {
"get_inventory": get_inventory,
"get_demand": get_demand,
}
tools = [
{
"type": "function",
"name": "get_inventory",
"description": "Return an object with sku (string) and available_units (number).",
"parameters": {
"type": "object",
"properties": {"sku": {"type": "string"}},
"required": ["sku"],
"additionalProperties": False,
},
"output_schema": {
"type": "object",
"properties": {
"sku": {"type": "string"},
"available_units": {"type": "number"},
},
"required": ["sku", "available_units"],
"additionalProperties": False,
},
"allowed_callers": ["programmatic"],
},
{
"type": "function",
"name": "get_demand",
"description": "Return an object with sku (string) and requested_units (number).",
"parameters": {
"type": "object",
"properties": {"sku": {"type": "string"}},
"required": ["sku"],
"additionalProperties": False,
},
"output_schema": {
"type": "object",
"properties": {
"sku": {"type": "string"},
"requested_units": {"type": "number"},
},
"required": ["sku", "requested_units"],
"additionalProperties": False,
},
"allowed_callers": ["programmatic"],
},
{"type": "programmatic_tool_calling"},
]
input_items = [
{
"role": "user",
"content": "Compare inventory with demand for sku_123.",
}
]
while True:
response = client.responses.create(
model=model,
store=False,
input=input_items,
tools=tools,
)
if response.status != "completed":
raise RuntimeError(f"Response ended with status {response.status}")
# Preserve every output item, including program and reasoning items.
input_items.extend(item.model_dump(exclude_none=True) for item in response.output)
calls = [item for item in response.output if item.type == "function_call"]
if not calls:
message = next(
(item for item in response.output if item.type == "message"), None
)
if message:
refusal = next(
(part.refusal for part in message.content if part.type == "refusal"),
"",
)
print(response.output_text or refusal)
break
continue
for call in calls:
run = implementations.get(call.name)
if run is None:
raise ValueError(f"Unknown tool: {call.name}")
result = run(**json.loads(call.arguments))
input_items.append(
{
"type": "function_call_output",
"call_id": call.call_id,
"output": json.dumps(result),
# Preserve caller so the runtime can resume the correct program.
"caller": call.caller.model_dump() if call.caller else None,
}
)Ao armazenar respostas, você pode continuar a partir de previous_response_id em vez de reenviar todos os itens das respostas anteriores. Envie os novos itens function_call_output como a próxima entrada. Com store: false, reenvie a sequência completa na ordem, incluindo todos os itens de program, raciocínio, chamada de função, saída de chamada de função e program_output.
Para solicitações sem estado a modelos de raciocínio, reenvie todos os itens de raciocínio retornados. Cada item inclui encrypted_content por padrão. Consulte estado da conversa para conhecer o padrão geral de uso sem estado.
Projete ferramentas para programas
- Retorne dados estruturados e compactos que o JavaScript possa inspecionar sem precisar interpretar texto em prosa.
- Use
output_schemapara definir os campos e tipos esperados no retorno de cada ferramenta e documente seu comportamento em caso de erro. Se a estrutura de retorno não for conhecida de antemão, mantenha a chamada direta à ferramenta para que o modelo possa inspecionar o resultado. - Defina a estrutura exata do resultado do programa e as evidências necessárias. Retorne uma indicação de falha clara e estruturada quando o programa não conseguir produzir um resultado válido.
- Torne as chamadas de função idempotentes sempre que possível. Uma nova tentativa ou reexecução não deve repetir um efeito colateral inseguro.
- Verifique os argumentos e as permissões de cada chamada no seu aplicativo, mesmo quando ela vier de um programa hospedado.
- Dê nomes e descrições específicos às ferramentas para que o modelo possa combiná-las corretamente.
- Exija aprovação no nível do aplicativo antes de ações de alto impacto, independentemente de quem fizer a chamada.
Avalie a chamada programática de ferramentas
A chamada programática de ferramentas pode reduzir a quantidade de saídas intermediárias de ferramentas adicionadas ao contexto do modelo, mas o efeito depende da tarefa e das respostas das ferramentas. Comece usando a chamada direta de ferramentas como referência e depois compare as duas abordagens em tarefas representativas.
Defina o nível de qualidade da resposta final e as evidências necessárias antes de medir a eficiência. Avalie o uso de tokens e as chamadas de ferramentas junto com a correção, a completude e a cobertura das evidências, e deixe explícita qualquer concessão de qualidade aceita.
Meça:
- Correção, completude e cobertura das evidências na resposta final.
- Tokens de entrada e totais, latência de ponta a ponta e custo.
- Turnos do modelo, chamadas de ferramentas, novas tentativas e comportamento de recuperação.
- Resultados de segurança, especialmente quanto a efeitos colaterais e requisitos de aprovação.
- Se o caminho executado correspondeu à etapa pretendida do fluxo de trabalho.
API de Agentes
Na API de Agentes, a chamada programática de ferramentas é executada no harness do agente gerenciado pela OpenAI e está habilitada por padrão. O harness fornece ao agente uma ferramenta exec e disponibiliza suas ferramentas existentes no código JavaScript gerado. Você não precisa encapsular essas ferramentas como programas de linha de comando nem instalá-las no sandbox.
Para desabilitar a chamada programática de ferramentas, inclua esta entrada em agent.tools:
{
"type": "programmatic_tool_calling",
"enabled": false
}
Omitir a entrada ou seu campo enabled mantém a chamada programática de ferramentas habilitada. Uma entrada que contém apenas o tipo, { "type": "programmatic_tool_calling" }, também a mantém habilitada. A configuração de allowed_callers e o loop de continuação da Responses apresentados acima descrevem a integração com a API Responses.
A chamada programática de ferramentas também funciona em sessões somente de conversa com environment.type definido como none. Bash, servidores MCP executores e outras ferramentas que são executadas em um sandbox continuam exigindo um ambiente de execução.
Orquestrar uma ferramenta em JavaScript não muda onde ela é executada. Uma chamada de shell executa comandos no sandbox; o ambiente de execução JavaScript não inicia processos do sistema por conta própria. Os servidores MCP executores continuam usando o sandbox, e as ferramentas de função continuam chamando o servidor do seu aplicativo. O agente processa os resultados dessas ferramentas antes de decidir o que entra no contexto do modelo.
Use as orientações de roteamento acima para definir quais etapas do fluxo de trabalho devem usar código. Siga as instruções em Funções e Conexões MCP para configurar a API de Agentes e tratar as chamadas.
Guias relacionados
- Use a chamada de função para definir funções de responsabilidade do cliente.
- Use a pesquisa de ferramentas para adiar o carregamento de definições extensas de ferramentas até que um modelo precise delas.
- Use o estado da conversa para dar continuidade a solicitações armazenadas ou sem estado da Responses API.
- Consulte os controles de dados antes de escolher um modo de armazenamento.