Сразу вывод: Agents API хостит цикл. Контракт — нет. 10 сентября 2026 OpenAI выложил разработчикам Agent Harness, который крутит Codex, как public beta. Планирование модели, compaction контекста, subagents и жизнь sandbox ушли из вашего процесса в beta.agents.sessions. У вас в руках почти только JSON: JSON Schema на каждом function-инструменте, arguments, строка в tool_result, MCP inputSchema и поток событий session. Hosted harness, который крутит цикл, — не то же самое, что кто-то другой валидирует ваши поля. Ослабьте контракт — hosted-цикл просто чаще гоняет плохие параметры.
Текст актуален на 18 сентября 2026. На сайте уже есть почему агентам не обойтись без JSON, почему Tool Calling зависит от JSON Schema, станет ли JSON Schema стандартным контрактом, MCP / Skills / Tools / Subagents и что такое MCP. Эта статья отвечает только: почему после Agents API JSON важнее, а не наоборот.
Что на самом деле вышло 10 сентября
Формулировка OpenAI: тот же harness и та же инфраструктура, что крутят Codex — hosted cloud-агент для разработчиков. Публичные доки кладут это в пространство имён beta.agents; запросы несут OpenAI-Beta: agents=v1. Отдельной платы за harness нет. Вы платите за токены модели, инструменты и время sandbox.
Создать session — значит отправить один JSON-документ: модель, инструкции, список инструментов, environment, input. Официальные примеры берут gpt-6-astra. Инструменты — MCP, свои function или встроенный retrieval. Environment: none, openai_hosted или свой sandbox — Blaxel, Cloudflare, Daytona, E2B, Modal, Vercel и подобные. Multi-agent — флаг: multi_agent.enabled плюс max_concurrent_subagents.
Это не ещё один чат-эндпоинт с просьбой «верни JSON». Responses API никуда не делся. Agents SDK никуда не делся. Agents API забирает сам цикл: кто выбирает следующий ход, когда сжимается контекст, когда спавнится subagent. Имена полей в beta ещё могут сдвинуться. Слой уже стабилен: OpenAI крутит harness; вы даёте контракт инструментов и бизнес-результат.
Три входа: Responses, Agents SDK, Agents API
На сентябрь 2026 у OpenAI три пути сделать агента — рядом. Прежде чем смешивать, спросите, где крутится цикл:
| Вход | Где крутится цикл | Где живёт состояние | Что вы всё ещё пишете |
|---|---|---|---|
| Responses API | Ваше приложение | History, который вы собираете / Conversations | Вызовы модели, возврат инструментов, весь цикл |
| Agents SDK | Ваш процесс | SDK sessions плюс ваше хранилище | Approvals, деплой; цикл ещё можно менять |
| Agents API | Hosted Codex harness OpenAI | session / turn / item на сервере | Определения инструментов, результаты function, выбор environment; цикл не меняется |
Разовое completion — по-прежнему Responses. Если approvals и персистентность должны быть вашими — SDK. Если нужны многодневные задачи, compaction, subagents и sandbox, которым управляют за вас — Agents API. Все три описывают параметры инструментов JSON Schema. Разница: в первых двух цикл ещё можно патчить; в третьей патч только на контракт и обратный payload.
Что такое Agent Harness — и что он не подписывает
Harness — рантайм между моделью и побочными эффектами: читает события, выбирает инструменты, кормит результатами, сжимает контекст, держит длинную задачу живой. Codex harness открыт. Agents API — OpenAI крутит ту же логику и версионирует её вместе с моделями. В анонсе названы automatic compaction, Tool search, Programmatic Tool Calling и параллельные subagents.
Он не подписывает ни одно из этого:
- должен ли
customer_idсуществовать и быть UUID; - может ли ваша функция принимать лишние ключи;
- насколько тугой или свободный
inputSchemaу MCP Server; output, который вы возвращаете — объект, строка или абзац чата.
Это по-прежнему JSON Schema плюс проверка, которую вы гоняете сами. Hosted harness поднимает, как долго цикл может крутиться и сколько параллелить. Он не поднимает, легальны ли параметры этого хода. Смешать одно с другим — первое заблуждение, которое эта статья разводит.
Почему hosted-цикл даёт больше JSON-ходов
Когда цикл пишете вы, плохой JSON обычно умирает у вас: parse падает, поля не сходятся — вы стоите. Когда цикл hosted, отказ откладывается, копируется и уходит в больше каналов:
| Ход | Носитель | Кто производит | Кто должен валидировать |
|---|---|---|---|
| Создать session | JSON agent / tools / environment | Ваше приложение | Вы: до отправки |
| Определение function | JSON Schema (parameters) | Ваше приложение | Вы: ужесточить required / additionalProperties |
| Модель инициирует вызов | объект arguments | Hosted harness + модель | Вы: ещё раз до исполнения |
| Вернуть результат | строка tool_result.output | Ваше приложение | Вы: stringify легальное значение |
| MCP | JSON-RPC + inputSchema | Server / harness | Server и ваш белый список |
| Поток событий | JSON-события agent.session.* | Hosted-сервис | Вы: ветвитесь по type; не парсите как чат-прозу |
Плюс Tool search подгружает определения по запросу, Programmatic Tool Calling сцепляет вызовы в коде, у каждого subagent свой контекст — одна пользовательская задача теперь делает больше JSON-кругов, чем один ход Function Calling. Хостинг прячет эти ходы. Скрыто — не значит «можно не валидировать». Пошаговую карту см. от Tool Calling к MCP.
Tool Calling: function-инструменты по-прежнему JSON Schema
Function-инструменты Agents API берут ту же форму, что Responses API. В agent.tools кладёте не абзац. Имя, описание и 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
}
}
Официальный пример заполняет required и ставит additionalProperties в false. Это не привычка вёрстки. Если агенту можно дописать один ключ, этот ключ станет путём, SQL-фрагментом или удалением. Schema — контракт, который модель видит при декодировании, и контракт, который вы должны прогнать ещё раз до исполнения. Про strict mode, ajv и второй проход см. почему Tool Calling зависит от JSON Schema.
Поле description всё ещё помогает модели выбрать инструмент. Оно не заменяет типы, enum и обязательные поля. Чем умнее harness, тем охотнее он берёт «почти тот» инструмент из длинного списка. «Почти» как раз и должна отсечь Schema.
requires_action и tool_result: обратный путь тоже JSON
Когда модели нужна ваша функция, session встаёт на agent.session.requires_action. Ожидающее лежит в required_actions. Пункт function_call в history сам по себе не считается. Типичный pending-вызов выглядит так:
{
"type": "function_call",
"turn_id": "turn_123",
"call_id": "call_123",
"name": "get_customer",
"arguments": { "customer_id": "123" }
}
Документация подаёт arguments как объект. Не заворачивайте его в чат-ответ и не выскребайте JSON.parse — это не тот канал, см. почему JSON.parse падает. Провалидируйте объект той же Schema, исполните функцию, затем отправьте agent.session.input.tool_result на эндпоинт событий session с исходными turn_id и call_id.
При успехе success: true, output — строка или поддерживаемый массив контента. Объекты сначала через JSON.stringify. При отказе success: false и error, который модель прочитает. Не отправляйте стеки, секреты и целую строку базы. Если процесс умер после исполнения, но до того как результат дошёл до OpenAI, ключуйте побочный эффект по session / turn / call и держите идемпотентность: после рестарта сначала читайте pending, потом решайте, гонять ли снова.
Обработчики function всегда крутятся в вашем приложении, даже если у session есть sandbox. Harness не исполнит get_customer за вас. Вы офлайн — ход висит. Это одна из немногих синхронных точек hosted-цикла, которая всё ещё целиком ваша — и ход, на котором JSON обязан быть правильным.
Tool search и Programmatic Tool Calling
Большой список инструментов жжёт токены и бьёт кэш, если каждая Schema сидит в контексте. Agents API по умолчанию грузит function жадно. Редкие можно пометить defer_loading: true и положить {"type": "tool_search"} в agent.tools. Модель сначала находит определение, потом вызывает. Появляется ход, где «само определение — тоже JSON»: Schema из поиска должна совпадать с функцией, которую вы реально реализовали. Не рекламируйте широкий контракт и не исполняйте узкий.
Programmatic Tool Calling даёт поддерживаемым моделям написать короткую программу, которая гоняет подходящие инструменты параллельно или цепочкой, и возвращает в контекст только отфильтрованный результат. Это снижает цену «каждый ход забивает окно». Это повышает требование, что промежуточный JSON легален. Если типы уплывут посередине, фильтры и склейки дальше молча поедут в harness, который вы не видите. В SDK уже есть патч: структурированные ошибки кодируют в JSON. Этот путь ест Schema, не прозу.
MCP и subagents: больше Schema, больше JSON
Положите MCP Server в agent.tools — harness сам обнаружит инструменты, вызовет их и скормит результаты модели. В отличие от function, эти вызовы не проходят через ваше приложение. HTTP по умолчанию соединяет OpenAI; можно соединяться из environment или поднять stdio внутри sandbox. Что вы ещё контролируете: allowed_tools, валит ли отказ инициализации turn (required: true) и насколько тугой inputSchema у самого Server.
Сообщения MCP по-прежнему JSON-RPC. Свободная Schema значит: hosted harness настреляет больше запросов, которых вы не увидите. Это не «протокол вас обезопасил». Это «цикл уехал дальше». Слои протокола — что такое MCP; граница со Skills и Subagents — стек агентов 2026.
У каждого subagent свой контекст; родитель сливает. Параллель режет задержку и разворачивает много объектов arguments. Если сводка всё ещё длинный текст без Schema, вы только отложили «парсить чат» на последний ход. Выводы, которые входят в программу, всё равно должны идти через Structured Output или вашу Schema результата — не ещё одно выскребание прозы. См. что такое Structured Output.
Четыре вещи, которые вы всё равно валидируете локально
После того как harness hosted, список не короче. Он ужеже:
- Schema инструментов. Заполните
required, поставьтеadditionalProperties: false, ужмите enum. Не опирайтесь на description, чтобы остановить побочные эффекты. - arguments до исполнения. Даже если вендор уже применил Schema, прогоните тот же документ ещё раз в своём процессе. Неверные типы, нет полей, лишние ключи — стоп здесь.
- output, который вы возвращаете. Сначала легальный JSON, потом
stringify. Ошибки уходят какsuccess: false. Не отдавайте модели сырое внутреннее исключение. - События и чат — разные каналы. Ветвитесь по
event.type. Не считайте весь SSE-стрим одним JSON-значением. Структурированные ответы пользователю — через Structured Output, неJSON.parseпредложения ассистента.
Со стороны безопасности: строка внутри arguments может быть инъекцией, не «тип сошёлся — исполняй». См. вредоносный JSON и Prompt Injection. Станет ли JSON Schema кросс-вендорным контрактом — статья про стандартный контракт. Agents API этот тезис не ослабляет. Он толкает его на единственный слой, который вы ещё можете менять.
Смотреть контракт локальными JSON-инструментами
Прежде чем отдать работу hosted session, посмотрите в браузере три текста: Schema инструмента, образец объекта arguments и output, который собираетесь вернуть.
- Валидатор JSON — легальна ли грамматика; если есть Schema — сразу поля, required и лишние ключи.
- Форматирование JSON — разверните однострочный
tool_resultи смотрите, не сериализовали ли вы целую строку базы. - JSON Diff — сравните arguments модели с минимальным объектом, который разрешает Schema.
Ничего не уходит из браузера. Так удобно положить рядом упавший payload required_actions, документ parameters и один stringify-результат. Стабилизируйте контракт, потом отдайте hosted harness крутить дни.
FAQ
Agents API значит, что JSON Schema больше не нужна?
Наоборот. Когда цикл hosted, Schema — главный контракт, который у вас ещё в руках. parameters у function, inputSchema у MCP, output который вы возвращаете — всё ещё JSON.
Как выбирать между Agents API, Agents SDK и Responses?
Разовые вызовы — Responses. Если цикл, approvals и хранилище должны быть вашими — SDK. Если длинные задачи, compaction, subagents и sandbox, которым управляет OpenAI — Agents API. Все три берут JSON Schema на параметры инструментов.
arguments уже объект. Всё равно вызывать JSON.parse?
Не парсите окружающий чат ещё раз. Считайте arguments объектом, как в доке, и валидируйте той же JSON Schema. Выскребать arguments из прозы — не тот канал.
Почему tool_result надо stringify?
Документация хочет output строкой или поддерживаемым массивом контента. Сделайте легальный JSON, затем stringify — чтобы не смешать второе кодирование с «похоже на объект, на деле строка».
Проходят ли MCP-инструменты через моё приложение?
По умолчанию нет. Harness говорит с Server напрямую. Ужесточайте inputSchema самого Server, allowed_tools и approvals на необратимые действия внутри этого Server.
Имена полей в beta изменятся?
Могут. Статья по публичным докам на 18 сентября 2026. Слой не сдвинется: harness крутит цикл; вы даёте JSON-контракт. Поле переименуют — обязанность валидировать останется у вас.
Итог
Agents API снижает объём «как довести агента до конца». Повышает вес «каждый JSON-ход должен быть правильным». 10 сентября отдали Codex harness: sessions, compaction, tool search, программные вызовы, subagents, sandbox. Он не проверит, как должен выглядеть customer_id, и не превратит ваш tool_result в легальную строку за вас.
Встроить агента в программу в 2026 — тот же порядок: инструменты на JSON Schema, финальные ответы на Structured Output, чат-проза — не API. Изменилось другое: когда цикл hosted, патчить можно только контракт. Сначала прогоните Schema, arguments и обратный payload в локальном валидаторе, потом отдайте работу hosted session. Модели сменятся. Harness возьмёт новые версии. Контракт ваших полей не должен разъезжаться вместе с ними.