AI Agent

Почему AI-агентам нужен JSON: от Function Calling до MCP

Ноутбук с редактором кода и логами терминала, руки на клавиатуре
Рабочий стол с несколькими мониторами: вызовы инструментов агента всё равно попадают в реальную среду исполнения.

Симптом: агент умеет болтать, но аргументы инструментов не проходят проверку, повтор вызова дублирует заказ, а MCP-сервер запущен и инструментов не видно.
Самый быстрый шаг: считать JSON единственным контрактом между моделью и инструментами: входы ограничивать JSON Schema, результаты возвращать стабильными полями, а MCP использовать только чтобы этот контракт можно было обнаружить между процессами.

Текст для разработчиков, платформенных инженеров и архитекторов, которые подключают языковую модель к живым системам. Важен не новый термин, а путь одного и того же JSON через Function Calling, Tool Calling и MCP и тот hop, на котором цепочка рвётся.

Если вы ещё выбираете фреймворк, сначала прочитайте Как выбрать фреймворк для AI Agent. Про изоляцию при исполнении — AI Sandbox, Docker и виртуальная файловая система.

Почему AI Agent не живёт без JSON

Модель порождает язык. Боевые системы принимают структурированные команды. Как только агенту нужно проверить склад, сменить заявку, прогнать тесты или открыть браузер, намерение должно стать данными, которые можно проверить, отклонить и запротоколировать. JSON сидит в этом шве: его читает человек, парсит машина, его уже едят HTTP, логи, очереди и базы.

Главное — проверяемость. Проза не скажет шлюзу, что order_id — строка, amount — положительное число, currency — перечисление. JSON Schema скажет. Руководство OpenAI по Function Calling описывает параметры функции как JSON Schema, чтобы модель уже при сэмплировании шла к законной структуре. Открыть руководство OpenAI Function Calling

Типы, обязательные поля, enum и additionalProperties — не академическая мелочь. Это первый шлагбаум против выдуманных полей, строк в числах и потерянного ключа идемпотентности. Открыть документацию JSON Schema

  • Диалог: «сделай тот заказ со склада в Шанхае срочным».
  • Контракт: {"name":"update_order","arguments":{"order_id":"A938","priority":"expedited"}}.
  • Исполнение: схема, права, бизнес-API, JSON обратно модели.

Без слоя контракта агент — чат. С ним он может стать управляемым исполнителем.

⚠️ Правило с площадки: если аргументы всё ещё «свободный текст + regex», протокола нет, есть удача промпта. Сначала схема, потом оркестрация.

Function Calling: модель учится заполнять форму

Function Calling значит: до ответа пользователю модель может выбрать объявленную функцию и выдать аргументы по схеме. Счастливый путь из пяти шагов, на каждом поле может пропасть.

  1. Регистрация: tools с name, description, parameters как JSON Schema.
  2. Решение: вызвать функцию или ответить сразу.
  3. Заполнение: tool_calls, arguments как JSON-строка или объект.
  4. Исполнение: parse, проверка, права, живая система.
  5. Возврат: tool-сообщение, затем ответ человеку.

Description — сигнал маршрутизации, не реклама. «Погода» будет драться с «доставкой». «Вызывать только если есть город; не для исторического климата» снижает ложные срабатывания. Описания полей в схеме тоже промпт: «order_id — бизнес-номер заказа, не payment intent» должно жить в JSON Schema.

Strict mode и Structured Outputs поднимают «похоже на JSON» до «совпадает со схемой». JSON mode обещает только разбираемые скобки. Схема-валидность — не бизнес-валидность. Отрицательная сумма, неизвестный склад, чужой заказ должны падать в вашем коде.

Минимальный исполнимый контракт

Схема ниже фиксирует enum и ключ идемпотентности. Модель может не вызывать инструмент, но не может выдумать лишние поля склада и не может выкинуть idempotency_key.

function schema (фрагмент)
{
  "type": "function",
  "name": "update_shipment",
  "description": "Вызывать только если пользователь явно просит сменить приоритет доставки.",
  "strict": true,
  "parameters": {
    "type": "object",
    "properties": {
      "order_id": {"type": "string", "description": "Бизнес-номер заказа"},
      "priority": {"type": "string", "enum": ["standard", "expedited"]},
      "idempotency_key": {"type": "string"}
    },
    "required": ["order_id", "priority", "idempotency_key"],
    "additionalProperties": false
  }
}

Порядок: JSON parse → схема → права → таблица идемпотентности → API → {"ok":true,"shipment_id":"..."} или {"ok":false,"error":"not_found"}. Не кладите стек и секреты в tool result.

Tool Calling: от функции к плоскости инструментов

Командам быстро понадобилось больше своих функций: поиск, интерпретатор кода, браузер, computer use, файлы. API ушли от function_call к единой поверхности tools / Tool Calling. Имя сменилось, JSON-контракт нет.

Anthropic называет это Tool use и описывает input_schema как JSON Schema. Модель отдаёт блок tool_use, приложение отвечает tool_result. Открыть документацию Anthropic Tool use

  • Параллельные вызовы: чтение параллельно, блокировка склада и оплата последовательно.
  • Согласование: рискованный инструмент возвращает pending JSON, а не исполняется.
  • Наблюдаемость: в trace имя, краткие аргументы, задержка, код ошибки.

Модель может выбрать верный инструмент и спрятать опасную нагрузку в строковом поле. Схема ловит типы, не семантику. Опасным инструментам нужны allowlist, таймаут и песочница.

MCP: сделать JSON-контракт подключаемым

Function и Tool Calling описывают разговор внутри одного API-запроса. MCP описывает обнаружение, повторное использование многими хостами и исполнение в отдельном процессе. Спецификация использует JSON-RPC 2.0. Открыть спецификацию MCP

  1. Хост стартует как MCP-клиент.
  2. Соединение по stdio, SSE или Streamable HTTP.
  3. initialize согласовывает версию и возможности.
  4. tools/list отдаёт inputSchema — всё ещё JSON Schema.
  5. Модель по-прежнему делает Tool Calling; клиент шлёт tools/call с JSON.
  6. Контент сервера становится tool result.

MCP не заменяет JSON. Он превращает зашитый массив tools в каталог времени выполнения. Один и тот же Git, браузерная автоматизация, API заявок могут обслуживать Cursor, Claude Desktop и вашего агента.

«MCP стоит, инструментов нет» почти всегда баг контракта: initialize, пустой list, схема несовместима со strict, нет required, или проза вместо JSON-RPC error.

Сквозной поток: от фразы до MCP

  1. Пользователь пишет естественный язык.
  2. Рантайм собирает messages, локальные tools и MCP tools/list.
  3. Модель выдаёт JSON-аргументы.
  4. Маршрутизация: локальная функция или JSON-RPC tools/call.
  5. JSON результата возвращается в диалог.
  6. Повторный вызов, вопрос человеку или финальный ответ.

Границу часто не видят: модель не держит ваше соединение с БД. Она выдаёт только JSON. Кто парсит, на какой машине исполняется, есть ли SSH/VNC и исходящая сеть — политика рантайма. Агент на облачном Mac говорит тем же протоколом, но на другой плоскости прав.

СлойРоль JSONГде ставить затвор
Function CallingАргументы одного запросаСхема, strict, бизнес-проверки
Tool CallingЖурнал вызовов на общей плоскостиПараллельность, согласование, trace
MCPОбнаружение между процессамиТранспорт, auth, ошибки list/call

Не цепляйтесь к названиям продуктов. Если инструменты только для одного приложения, хватит Function/Tool Calling. Если несколько хостов должны их делить — оправдан MCP-сервер. Без схемы MCP лишь переносит хаос в другой процесс.

Ломается JSON — ломается вся цепочка агента

  • Невалидный JSON: выключен strict, «сначала объясни», markdown-ограда. Только структурированный канал инструментов.
  • Парсится, схема нет: required, enum, лишние свойства. Ошибку валидации вернуть как tool result, ограничить ретраи.
  • Схема ок, бизнес нет: нет заказа, нет остатка, нет прав. Стабильный error code, не HTML 500.
  • Ретрай пишет дважды: таймаут плюс второй вызов. idempotency_key и дедуп на исполнителе.
  • list и call разъехались: имя или схема после hot reload. Версионировать хеш, заново initialize.
  • Секреты в JSON-логах: полные аргументы в общем trace. Имена полей и хеши, токены и ПДн маскировать.

Соберите таймаут, ошибку схемы и отказ в правах в один приёмочный сценарий. Если агент крутится в цикле или произвольно меняет аргументы, его нельзя пускать к оплате, отгрузке и боевой базе.

Чеклист JSON-контракта перед релизом

  • [ ] У каждого инструмента name, description, JSON Schema, additionalProperties: false.
  • [ ] Рискованные поля — enum / format / max length.
  • [ ] Записи с ключом идемпотентности; timeout и retry в рантайме.
  • [ ] Результат ok / error / data, без сырого стека.
  • [ ] Параллельность по побочным эффектам; оплата, почта, удаление по умолчанию последовательно.
  • [ ] У MCP initialize / list / call есть timeout, auth и коды ошибок.
  • [ ] Хосты заново тянут схему после смены каталога.
  • [ ] Trace восстанавливает цепочку, но не секреты.
  • [ ] Замороженный ввод бьёт в то же имя инструмента и тот же набор обязательных полей.

Только потом — мультиагент и тяжёлые workflow. Нестабильный протокол лишь быстрее копирует сломанный JSON.

FAQ

Почему не отдать естественный язык программе на разбор?

Нет обязательных полей и типов. «Сделай срочно» нельзя стабильно сопоставить enum, лишние поля не отвергнуть. JSON Schema превращает разбор в проверку.

Tool Calling на практике отличается от Function Calling?

Для приложения ядро одно: модель заполняет JSON-форму, ваш код исполняет. Tool Calling — более широкая плоскость: встроенные инструменты хоста, параллельные вызовы, единый канал результата. При миграции сначала выровняйте схемы и роли сообщений.

Когда нужен MCP, а не зашитый массив tools?

Когда те же инструменты нужны нескольким хостам, отдельному процессу или публикации другой командой. Если инструмент живёт и умирает вместе с одним внутренним сервисом, Function/Tool Calling проще.

Иногда битый JSON: ретраить или менять протокол?

Включите строгий structured output и не вытаскивайте аргументы из прозы. Если сбои частые, смотрите глубину схемы, конфликт описаний и число инструментов. Переход на MCP это не лечит: аргументы MCP всё равно JSON.

На общем ноутбуке регрессии схемы разваливаются при дрейфе среды, а процессы MCP дерутся за порты разработки. Бare-metal Mac в облаке Kvmjet держит фиксированный образ macOS, чтобы ту же ошибку Tool Calling или MCP воспроизвести по SSH или VNC. Публично описаны циклы от суток до квартала — достаточно стабилизировать JSON-контракт до долгой аренды.

Возьмите чеклист в справочный центр Kvmjet, проверьте постоянную работу, изоляцию прав и удалённый доступ и решите, где жить MCP-серверу: на ноутбуке, в стойке или на облачном Mac.

Гонять Tool Calling и MCP на стабильном Mac

Схема, идемпотентность и MCP-сервер требуют воспроизводимой машины. Общий ноутбук сразу рассинхронизирует каталоги и порты.

Bare-metal M4 Mac в Kvmjet даёт настоящий macOS, выделенную полосу и SSH/VNC, чтобы повторить тот же упавший tools/call.

Смотреть тарифы →

Специальное предложение