Programmatic Tool Calling в GPT-5.6: руководство по миграции для маршрутизации и агентных workflow
GPT-5.6 вводит Programmatic Tool Calling — модель пишет JavaScript для оркестрации ваших инструментов внутри V8-песочницы, сокращая расход token на 24–63% и устраняя накладные расходы на round-trip. Условие: только Responses API. Разбираем миграцию с классического function calling, каждое breaking change и способ маршрутизации GPT-5.6 через OpenAI-совместимый gateway в переходный период.
GPT-5.6 вышел 9 июля 2026 года. Его ключевая фича для разработчиков — не очередной benchmark, а Programmatic Tool Calling: механизм, позволяющий модели писать и выполнять JavaScript для координации ваших инструментов в изолированной V8-песочнице. Вместо того чтобы возвращать каждый результат инструмента обратно модели для повторного reasoning, GPT-5.6 может делать loop, branch, фильтрацию промежуточных данных и возвращать только финальный результат. OpenAI сообщает о сокращении output-token в среднем на 24%, а ранние клиенты видят до 63.5% сокращения на tool-heavy workflow.
Обязательное условие: Programmatic Tool Calling работает только с Responses API. Если ваши agent'ы всё ещё вызывают /v1/chat/completions, вы ничего из этого не получите. Это руководство проведёт вас через миграцию — что меняется, что ломается и как безопасно маршрутизировать трафик в переходный период.
- Меняйте три значения, а не три SDK. Замените
api_key,base_urlиmodelв существующем клиенте OpenAI. Код запроса и ответа оставьте неизменным. - Сопоставьте model ID явно. ID модели у целевого провайдера почти никогда не совпадает с OpenAI ID. Держите словарь
{ openai_id: target_id }вне бизнес-логики. - Проверьте формат streaming. SSE-чанки должны соответствовать контракту OpenAI:
data: {...}+data: [DONE]. Прогоните один streaming вызов до продакшена. - Проверьте rate-limit заголовки. Некоторые провайдеры не возвращают
x-ratelimit-*. Добавьте обёртку с безопасным дефолтом. - Оставьте путь отката. Раскатайте замену под feature flag, гоняйте оба endpoint в shadow-режиме 24 часа, затем переключайтесь.
Источники: Анонс OpenAI GPT-5.6, получено 2026-07-19; Документация Programmatic Tool Calling, получено 2026-07-19; Анализ миграции ByteIota, получено 2026-07-19; Цены OpenAI API, получено 2026-07-19.
TL;DR — до и после
| Измерение | Классический Function Calling (/v1/chat/completions) | Programmatic Tool Calling (Responses API) |
|---|---|---|
| Оркестрация | Разработчик скриптует каждый шаг или модель выдаёт один tool call за ход | Модель пишет JavaScript для координации инструментов |
| Round-trip'ы | Один API-вызов на tool → модель → следующий tool | Одна программа обрабатывает N tool → единый результат |
| Расход token | Каждый промежуточный результат входит в контекст | Только program_output входит в контекст |
| Параллельные вызовы | Управляет разработчик или tool_choice: "auto" | Нативный Promise.all() внутри V8-песочницы |
| Поддерживаемые модели | Все GPT-4/5.x | Только GPT-5.6 Sol, Terra, Luna |
| API endpoint | /v1/chat/completions | /v1/responses |
Что такое Programmatic Tool Calling?
При включении Programmatic Tool Calling GPT-5.6 может вернуть элемент типа program, содержащий JavaScript-код. OpenAI выполняет этот код в чистом изолированном V8-runtime. Программа может:
- Вызывать ваши инструменты через
await tools.your_function_name({ ... }) - Запускать вызовы параллельно с
Promise.all() - Использовать циклы, условия и промежуточные переменные
- Фильтровать или агрегировать результаты перед возвратом
Ваше приложение по-прежнему выполняет фактические tool-функции — V8-песочница не имеет сетевого доступа, Node.js API или persistent state. Она оркестрирует; вы исполняете.
Результат: модель видит единственный program_output вместо 10 отдельных function_call_output. Для 10-шагового workflow это примерно 10× меньше накопления контекста.
Breaking Changes
Миграция с /v1/chat/completions на Responses API вносит несколько структурных изменений:
1. Структура ответа полностью меняется
До (Chat Completions):
{
"choices": [{
"message": {
"role": "assistant",
"tool_calls": [{
"id": "call_abc123",
"function": { "name": "get_weather", "arguments": "{\"city\":\"Shanghai\"}" }
}]
}
}]
}
После (Responses API):
{
"output": [
{
"type": "program",
"call_id": "prog_abc123",
"code": "const weather = await tools.get_weather({city: 'Shanghai'});\ntext(JSON.stringify(weather));",
"fingerprint": "fp_xyz..."
},
{
"type": "function_call",
"call_id": "fc_001",
"name": "get_weather",
"arguments": "{\"city\":\"Shanghai\"}",
"caller": { "caller_id": "prog_abc123" }
}
]
}
Обёртка choices[0].message исчезает. Вы получаете типизированный массив output с разными типами элементов (program, function_call, function_call_output, program_output, message).
2. Декларация tools получает allowed_callers
До:
tools = [
{"type": "function", "function": {"name": "query_db", "parameters": {...}}}
]
После:
tools = [
{"type": "programmatic_tool_calling"}, # Включаем фичу
{
"type": "function",
"name": "query_db",
"parameters": {...},
"output_schema": {...}, # Помогает JS использовать типизированные результаты
"allowed_callers": ["programmatic"] # Или ["direct", "programmatic"]
}
]
Три ключевых дополнения:
- Добавить
{"type": "programmatic_tool_calling"}в список tools - Установить
allowed_callersна каждой функции ("direct","programmatic"или оба) - Добавить
output_schemaдля надёжного доступа к полям возврата из JavaScript
3. Параллельная отправка — теперь default
В Responses API GPT-5.6 по умолчанию выдаёт параллельные tool-вызовы. Если ваши handler'ы предполагают последовательное выполнение (например, tool B зависит от side effect tool A), они сломаются без предупреждения. Проведите аудит графа зависимостей инструментов.
4. Ответы по умолчанию хранятся на сервере
В отличие от Chat Completions (stateless), Responses API хранит ответы на стороне сервера по умолчанию. Для чувствительных к конфиденциальности workflow явно задайте store: false. Обратите внимание: store: false включает stateless continuation, но НЕ активирует Zero Data Retention (ZDR) — ZDR нужно включать на уровне организации или проекта.
5. code_interpreter → namespace tools.runtime
Старый тип code_interpreter заменён namespace'ом tools.runtime с per-call billing. Если вы полагаетесь на выполнение кода, учтите это в бюджете.
Пошаговый checklist миграции
Шаг 1: Аудит текущих паттернов tool calling
# Найти все вызовы chat/completions с tools в кодовой базе
grep -rn "chat.completions\|/v1/chat/completions" --include="*.py" --include="*.ts" .
grep -rn "tool_calls\|function_call" --include="*.py" --include="*.ts" .
Классифицировать каждую точку вызова:
- Один tool call → один результат: Оставить как direct tool calling на Responses API
- Многошаговые tool-цепочки: Кандидат для Programmatic Tool Calling
- Semantic judgment между шагами: Оставить как direct (модель должна рассуждать между каждым результатом)
Шаг 2: Мигрировать на Responses API (без Programmatic Tool Calling)
Поменять endpoint и парсинг ответа:
# До
response = client.chat.completions.create(
model="gpt-5.5",
messages=[{"role": "user", "content": "..."}],
tools=[{"type": "function", "function": {"name": "get_weather", ...}}]
)
tool_call = response.choices[0].message.tool_calls[0]
# После — Responses API, классический прямой вызов
response = client.responses.create(
model="gpt-5.6-terra",
input=[{"role": "user", "content": "..."}],
tools=[{"type": "function", "name": "get_weather", "parameters": {...}}]
)
for item in response.output:
if item.type == "function_call":
result = execute_tool(item.name, item.arguments)
Шаг 3: Включить Programmatic Tool Calling для подходящих workflow
Для tool-heavy ограниченных workflow:
response = client.responses.create(
model="gpt-5.6-terra",
input=[{"role": "user", "content": "Сравни запасы по всем 5 складам"}],
tools=[
{"type": "programmatic_tool_calling"},
{
"type": "function",
"name": "get_inventory",
"parameters": {"type": "object", "properties": {"warehouse_id": {"type": "string"}}},
"output_schema": {
"type": "object",
"properties": {"warehouse_id": {"type": "string"}, "units": {"type": "number"}},
"required": ["warehouse_id", "units"]
},
"allowed_callers": ["programmatic"]
}
]
)
# Обработать tool-вызовы программы
for item in response.output:
if item.type == "function_call":
result = execute_tool(item.name, item.arguments)
# Вернуть результат, связав с программой через caller.caller_id
Шаг 4: Добавить guidance в system prompt
GPT-5.6 хорошо реагирует на явные инструкции по оркестрации:
Используй Programmatic Tool Calling для этапа сбора данных,
применяя только get_inventory и get_metrics.
Независимые вызовы запускай конкурентно.
Обработай промежуточные результаты и верни единый JSON-summary.
При transient failures повтори не более 2 раз.
Для операций записи, требующих одобрения, используй прямые tool-вызовы.
Rollback path
Если Programmatic Tool Calling даёт неожиданные результаты:
- Удалить
{"type": "programmatic_tool_calling"}из tools — модель fallback'нется на direct tool calling на том же Responses API endpoint - Переключить модель на
gpt-5.5— по-прежнему работает на Responses API с direct calling - Полный откат на Chat Completions — сменить endpoint обратно на
/v1/chat/completionsи использовать любую модель GPT-5.x
Responses API поддерживает оба режима одновременно. Можно включить Programmatic Tool Calling для одних tool (allowed_callers: ["programmatic"]) и оставить другие только для прямого вызова (allowed_callers: ["direct"]).
Влияние на стоимость
| Модель | Input / 1M tokens | Output / 1M tokens | Примечания |
|---|---|---|---|
| gpt-5.5 | $5.00 | $25.00 | Текущий baseline |
| gpt-5.6-sol | $5.00 | $30.00 | Frontier; output +20% vs 5.5 |
| gpt-5.6-terra | $2.50 | $15.00 | Рекомендуется; input –50%, output –40% vs 5.5 |
| gpt-5.6-luna | $1.00 | $6.00 | Массовые задачи; input –80%, output –76% vs 5.5 |
Цены из OpenAI, получено 19 июля 2026.
С Programmatic Tool Calling на Terra комбинированный эффект впечатляющий:
- Стоимость модели: input –50% / output –40% (Terra vs GPT-5.5)
- Сокращение token: –24% до –63.5% (меньше round-trip, меньше накопления контекста)
- Итоговая экономия: обычно 60–80% дешевле за завершённый workflow vs GPT-5.5 с классическим tool calling
Когда НЕ использовать Programmatic Tool Calling
Оставить direct tool calling когда:
- Каждый результат меняет план — semantic judgment между шагами требует reasoning модели
- Write-операции требуют approval — сохранить чёткие authorization boundaries
- Инструменты имеют order-зависимые side effects — V8-песочница может распараллелить вызовы
- Нужна полная provenance цитирования — program_output сворачивает промежуточные шаги
- Workflow из одного шага — overhead генерации программы не оправдан для одного вызова
Ограничения V8-песочницы
V8-runtime имеет жёсткие лимиты:
- Нет сетевого доступа (инструменты — единственный внешний интерфейс)
- Нет Node.js API, нет
require(), нет import пакетов - Нет persistent state между выполнениями
- Нет
console.log(используйтеtext()илиimage()для вывода) - Нет subprocess execution или доступа к файловой системе
- Можно вызывать только tool с
allowed_callers: ["programmatic"]
Это security-фичи. Программа может взаимодействовать с внешними системами только через явно opted-in инструменты.
Маршрутизация через OpenAI-совместимый gateway
Если вы маршрутизируете API-трафик через TheRouter или другой OpenAI-совместимый gateway, путь миграции тот же — укажите base_url на ваш gateway и используйте gpt-5.6-terra как model ID. Формат Responses API проходит транспарентно, когда ваш gateway его поддерживает.
Для команд в процессе миграции типичный паттерн:
- Маршрутизировать трафик
gpt-5.6-terraчерез gateway для новых workflow с Programmatic Tool Calling - Оставить
gpt-5.5на fallback-маршруте для существующего Chat Completions кода - Мигрировать call site'ы инкрементально; мониторить расход token по маршрутам
Это избегает big-bang cutover и позволяет сравнивать расходы side-by-side.
Timeline и рекомендации
| Временные рамки | Действие |
|---|---|
| Сейчас | Аудит tool-calling паттернов; классификация на programmatic-eligible или direct-only |
| Неделя 1–2 | Миграция на Responses API с direct tool calling (без Programmatic Tool Calling) |
| Неделя 2–3 | Включение Programmatic Tool Calling на ограниченных tool-heavy workflow |
| Неделя 3–4 | Benchmark экономии token; подбор tier модели (Sol → Terra → Luna) по качеству |
| Q1 2027 | response_format: {"type": "json_object"} теряет guaranteed-shape — миграция на JSON Schema 2025-12 |
FAQ
Q: Обязательно ли использовать Programmatic Tool Calling для работы с GPT-5.6?
Нет. GPT-5.6 работает со стандартным direct tool calling на Responses API. Programmatic Tool Calling — opt-in через тип programmatic_tool_calling.
Q: Можно ли использовать Programmatic Tool Calling с Chat Completions API?
Нет. Требуется Responses API (/v1/responses).
Q: Как со streaming?
Responses API поддерживает streaming. События выполнения программы стримятся по мере их возникновения — вы увидите program, function_call и program_output элементы инкрементально.
Q: GPT-5.6 есть в models-data.ts TheRouter?
На момент написания ещё нет. Model ID GPT-5.6 (gpt-5.6-sol, gpt-5.6-terra, gpt-5.6-luna) подтверждены через API OpenAI, но могут быть не отражены во всех routing-конфигурациях. Проверьте live endpoint /models/ вашего gateway.
GPT-5.6 вышел 9 июля 2026. Документация Programmatic Tool Calling актуальна на момент написания (19 июля 2026). Цены, доступность моделей и ограничения песочницы могут измениться — перед production-deployment проверяйте официальную документацию OpenAI.