Conclusão primeiro: a Agents API hospeda o loop. Ela não hospeda o contrato. Em 10 de setembro de 2026, a OpenAI colocou o Agent Harness que move o Codex na frente dos desenvolvedores como public beta. Agendamento do modelo, compactação de contexto, subagents e o ciclo de vida do sandbox saíram do seu processo e foram para beta.agents.sessions. O que você ainda segura é quase tudo JSON: o JSON Schema de cada function tool, arguments, a string em tool_result, o inputSchema do MCP e o stream de eventos da session. Um harness hospedado rodando o loop não é a mesma coisa que outra pessoa validar os seus campos. Afrouxe o contrato, e o loop hospedado só roda parâmetros ruins com mais frequência.
Escrito em 18 de setembro de 2026. Este site já tem por que agentes não vivem sem JSON, por que o Tool Calling depende de JSON Schema, se o JSON Schema vira o contrato padrão, MCP / Skills / Tools / Subagents e o que é MCP. Este texto só responde por que o JSON importa mais depois da Agents API, e não menos.
O que de fato saiu em 10 de setembro
Nas palavras da OpenAI: o mesmo harness e a mesma infraestrutura que movem o Codex, como um agent em nuvem hospedado para desenvolvedores. A documentação pública coloca isso no namespace beta.agents; as requests levam OpenAI-Beta: agents=v1. O harness não tem taxa à parte. Você paga tokens do modelo, tools e tempo de sandbox.
Criar uma session é enviar um documento JSON: model, instructions, lista de tools, environment, input. Os exemplos oficiais usam gpt-6-astra. Tools podem ser MCP, functions customizadas ou retrieval embutido. O environment pode ser none, openai_hosted ou um sandbox que você traz — Blaxel, Cloudflare, Daytona, E2B, Modal, Vercel e similares. Multi-agent é uma flag: multi_agent.enabled mais max_concurrent_subagents.
Isto não é mais um endpoint de chat pedindo «por favor, emita JSON». A Responses API continua lá. O Agents SDK continua lá. O que a Agents API leva é o loop em si: quem escolhe o próximo salto, quando o contexto é compactado, quando um subagent é criado. Nomes de campo ainda podem mudar no beta. A divisão já está estável: a OpenAI roda o harness; você entrega o contrato da ferramenta e o resultado de negócio.
Três portas: Responses, Agents SDK, Agents API
Em setembro de 2026, a OpenAI deixa três caminhos de agent lado a lado. Antes de misturar, pergunte onde o loop roda:
| Porta | Onde o loop roda | Onde o estado mora | O que você ainda escreve |
|---|---|---|---|
| Responses API | Seu app | History que você monta / Conversations | Chamadas de modelo, retornos de tool, o loop inteiro |
| Agents SDK | Seu processo | sessions do SDK mais o seu armazenamento | Aprovações, deploy, e você ainda pode mudar o loop |
| Agents API | O Codex harness hospedado da OpenAI | session / turn / item no servidor | Definições de tool, resultados de function, escolha de environment; você não muda o loop |
Completion de um tiro só continua no Responses. Se você precisa ser dono de aprovações e persistência, use o SDK. Se quer trabalho de vários dias, compaction, subagents e um sandbox operado por eles, use a Agents API. As três ainda descrevem parâmetros de ferramenta com JSON Schema. A diferença: nas duas primeiras você ainda remenda o loop; na terceira só remenda o contrato e o payload de volta.
O que é um Agent Harness — e o que ele não assina
Um harness é o runtime entre o modelo e os efeitos colaterais: lê eventos, escolhe tools, devolve resultados, compacta contexto, mantém um job longo vivo. O harness do Codex é open source. A Agents API é a OpenAI operando a mesma lógica e versionando com os modelos. O anúncio cita compaction automática, Tool search, Programmatic Tool Calling e subagents em paralelo.
Ele não assina nenhuma destas:
- se um
customer_idprecisa existir, ou precisa ser UUID; - se a sua function pode aceitar chaves a mais;
- se o
inputSchemade um MCP server está apertado ou frouxo; - se o
outputque você devolve é um objeto, uma string ou um parágrafo de chat.
Isso continua sendo JSON Schema mais uma checagem que você roda. Um harness hospedado aumenta quanto tempo o loop aguenta e quanto ele paraleliza. Não aumenta se os parâmetros deste salto são legais. Tratar as duas coisas como a mesma é a primeira confusão que este texto separa.
Por que um loop hospedado significa mais saltos JSON
Quando você escreve o loop, JSON ruim em geral morre do seu lado: o parse falha, os campos não batem, você para. Com o loop hospedado, a falha é adiada, copiada e mandada por mais canais:
| Salto | Payload | Quem produz | Quem precisa validar |
|---|---|---|---|
| Criar session | agent / tools / environment JSON | Seu app | Você, antes de enviar |
| Definição de function | JSON Schema (parameters) | Seu app | Você: aperte required / additionalProperties |
| O modelo dispara uma chamada | objeto arguments | Harness hospedado + modelo | Você: valide de novo antes de executar |
| Devolver um resultado | string tool_result.output | Seu app | Você: faça stringify de um valor legal |
| MCP | JSON-RPC + inputSchema | Server / harness | O server e a sua allow list |
| Stream de eventos | eventos JSON agent.session.* | O serviço hospedado | Você: ramifique no type; não faça parse como prosa de chat |
Some Tool search carregando definições sob demanda, Programmatic Tool Calling encadeando chamadas no código, e subagents cada um com o próprio contexto — uma tarefa do usuário agora faz mais idas e voltas de JSON do que um único salto de Function Calling. Hospedar esconde esses saltos. Escondido não é o mesmo que opcional de validar. Para um mapa salto a salto, veja do Tool Calling ao MCP.
Tool Calling: function tools ainda são JSON Schema
Function tools na Agents API reusam o formato da Responses API. O que você põe em agent.tools não é um parágrafo. É um nome, uma description e um JSON Schema:
{
"type": "function",
"name": "get_customer",
"description": "Look up a customer by ID.",
"parameters": {
"type": "object",
"properties": { "customer_id": { "type": "string" } },
"required": ["customer_id"],
"additionalProperties": false
}
}
O exemplo oficial preenche required e põe additionalProperties em false. Não é hábito de formatação. Se o agent pode acrescentar uma chave a mais, essa chave vira um path, um fragmento SQL ou um delete. O schema é o contrato que o modelo vê na decodificação, e o contrato que você deveria rodar de novo antes de executar. Para modo estrito, ajv e um pipeline de segunda passagem, veja por que o Tool Calling depende de JSON Schema.
A description ainda ajuda o modelo a escolher a ferramenta. Ela não substitui types, enums e campos required. Quanto mais esperto o harness, mais ele pega uma ferramenta «quase isso» numa lista longa. «Quase isso» é o que o schema existe para recusar.
requires_action e tool_result: o caminho de volta também é JSON
Quando o modelo precisa da sua function, a session para em agent.session.requires_action. O trabalho pendente mora em required_actions. Um item function_call no history sozinho não basta. Uma chamada pendente típica é assim:
{
"type": "function_call",
"turn_id": "turn_123",
"call_id": "call_123",
"name": "get_customer",
"arguments": { "customer_id": "123" }
}
A documentação apresenta arguments como objeto. Não embrulhe num reply de chat e raspe com JSON.parse — é o canal errado, coberto em por que o JSON.parse falha. Valide o objeto contra o mesmo schema, rode a function e poste agent.session.input.tool_result no endpoint de eventos da session com o turn_id e o call_id originais.
No sucesso, success: true e output como string ou um array de conteúdo suportado. Objetos passam por JSON.stringify primeiro. Na falha, success: false e um error que o modelo consiga ler. Não mande stack, segredo nem uma linha inteira de banco de volta. Se o processo morrer depois da function rodar e antes do resultado chegar na OpenAI, chaveie o efeito colateral por session / turn / call e fique idempotente: no restart, leia as actions pendentes antes de rodar de novo.
Handlers de function sempre rodam no seu aplicativo, mesmo com sandbox na session. O harness não executa get_customer por você. Se você estiver offline, o salto fica bloqueado. É um dos poucos pontos síncronos de um loop hospedado que ainda é inteiramente seu — e o salto em que o JSON tem de estar certo.
Tool search e Programmatic Tool Calling
Uma lista grande de tools queima tokens e quebra cache se todo schema fica no contexto. A Agents API carrega functions no modo eager por padrão. As raras podem pôr defer_loading: true, com {"type": "tool_search"} em agent.tools. O modelo acha a definição e depois chama. Isso acrescenta um salto em que «a definição também é JSON»: o schema que a busca devolve tem de bater com a function que você de fato implementou. Não anuncie um contrato largo e execute um estreito.
Programmatic Tool Calling deixa modelos suportados escreverem um programa curto que roda tools elegíveis em paralelo ou em cadeia, e só traz resultados filtrados de volta ao contexto. Isso corta o custo de encher a janela a cada salto. Sobe a exigência de que o JSON intermediário seja legal. Se os tipos derivam no meio, filtros e merges seguintes erram dentro de um harness que você não vê. O SDK já tem um conserto que codifica erros estruturados como JSON. Esse caminho come schema, não prosa.
MCP e subagents: mais schemas, mais JSON
Ponha um MCP server em agent.tools e o harness descobre tools, chama e devolve resultados. Diferente das functions, essas chamadas não passam pelo seu aplicativo. HTTP conecta a partir da OpenAI por padrão; você também pode conectar a partir do environment, ou subir stdio dentro do sandbox. O que você ainda controla é allowed_tools, se um init falho derruba o turn (required: true), e quão apertado está o inputSchema do próprio server.
Mensagens MCP ainda são JSON-RPC. Schema frouxo significa que o harness hospedado dispara mais requests que você nunca vê. Isso não é «o protocolo te deixou seguro». É «o loop foi para mais longe». Para as camadas do protocolo, veja o que é MCP; para o limite com Skills e Subagents, veja a pilha de agentes de 2026.
Cada subagent guarda o próprio contexto; o pai faz o merge. Trabalho em paralelo corta latência e também espalha muitos objetos arguments. Se o merge ainda for um ensaio sem schema, você só adiou «fazer parse do chat» para o último salto. Conclusões que entram num programa ainda devem usar Structured Output ou um schema de resultado que você define — não mais uma raspagem de prosa. Veja o que é Structured Output.
Quatro coisas que você ainda valida no local
Com o harness hospedado, a lista não encurta. Ela estreita:
- Schemas de ferramenta. Preencha
required, ponhaadditionalProperties: false, aperte enums. Não apoie na description para barrar efeitos colaterais. - Arguments antes de executar. Mesmo se o fornecedor já aplicou o schema, rode o mesmo documento de novo no seu processo. Tipos errados, campos faltando, chaves a mais param aqui.
- O output que você devolve. Faça JSON legal, depois
stringify. Erros saem comosuccess: false. Não entregue ao modelo uma exception interna crua. - Mantenha eventos e chat em canais separados. Ramifique em
event.type. Não trate um stream SSE inteiro como um valor JSON. Respostas estruturadas ao usuário vão por Structured Output, nãoJSON.parsenuma frase do assistant.
No lado de segurança: uma string dentro de arguments pode ser injeção, não «o tipo bateu, então execute». Veja JSON malicioso e prompt injection. Se o JSON Schema vira o contrato entre fornecedores é o texto do contrato padrão — a Agents API não enfraquece essa tese. Ela empurra a tese para a única camada que você ainda pode mudar.
Inspecione o contrato com ferramentas JSON locais
Antes de entregar o trabalho a uma session hospedada, olhe três textos no navegador: o schema da ferramenta, um objeto arguments de amostra e o output que você pretende devolver.
- Validador JSON — a gramática é legal; se você tem schema, cheque campos, required e chaves a mais juntos.
- Formatador JSON — expanda um
tool_resultnuma linha e veja se você serializou uma linha inteira de banco. - JSON Diff — compare os arguments que o modelo mandou com o menor objeto que o schema permite.
Nada sai do navegador. É o lugar certo para sentar um payload falho de required_actions, um documento parameters e um resultado depois do stringify um ao lado do outro. Estabilize o contrato, depois deixe o harness hospedado rodar por dias.
FAQ
A Agents API significa que eu posso parar de escrever JSON Schema?
O contrário. Com o loop hospedado, o schema é o contrato principal que você ainda segura. parameters de function, inputSchema do MCP e o output que você devolve ainda são JSON.
Como escolher entre Agents API, Agents SDK e Responses?
Chamadas de um tiro só vão no Responses. Se você precisa ser dono do loop, das aprovações e do armazenamento, use o SDK. Se quer jobs longos, compaction, subagents e um sandbox operado pela OpenAI, use a Agents API. As três ainda pedem JSON Schema nos parâmetros de ferramenta.
Arguments já são um objeto. Ainda chamo JSON.parse?
Não faça parse do chat em volta de novo. Trate arguments como objeto, como a documentação faz, e valide com o mesmo JSON Schema. Raspar arguments da prosa é o canal errado.
Por que tool_result precisa de stringify?
A documentação quer output como string ou um array de conteúdo suportado. Faça JSON legal, depois stringify, para não misturar uma segunda encoding com «parece objeto, na verdade é string».
Tools MCP passam pelo meu aplicativo?
Por padrão, não. O harness fala com o server. O que você aperta é o inputSchema do próprio server, allowed_tools, e qualquer aprovação de ações irreversíveis dentro desse server.
Nomes de campo vão mudar no beta?
Podem. Este texto segue a documentação pública de 18 de setembro de 2026. A divisão não muda: o harness roda o loop; você fornece o contrato JSON. Se um campo for renomeado, o dever de validar continua do seu lado.
Resumo
A Agents API corta o trabalho de «como levar um agent até o fim». Sobe o peso de «cada salto JSON tem de estar certo». O que saiu em 10 de setembro é o harness do Codex: sessions, compaction, tool search, chamadas programáticas, subagents, sandboxes. Ele não checa como um customer_id deve parecer, e não transforma o seu tool_result numa string legal por você.
Ligar um agent a um programa em 2026 ainda segue a mesma ordem: tools no JSON Schema, respostas finais no Structured Output, prosa de chat não é API. O que mudou: com o loop hospedado, o único lugar em que você ainda aplica um patch é o contrato. Cheque o schema, os arguments e o payload de volta num validador local primeiro, depois entregue o trabalho a uma session hospedada. Modelos vão mudar. O harness vai pegar versões novas. O seu contrato de campos não deveria afrouxar junto.