Function Calling (вызов инструментов) в 2026 — протокол по умолчанию для агентов: модели больше не изображают вызов API прозой. Они отдают JSON по согласованной схеме, а ваш код реально запрашивает погоду, БД, правит файлы или гоняет тесты. Разница не в том, кто лучше болтает, а в том, проверяется ли схема, аудитится ли исполнение и изолированы ли побочные эффекты.
Обновлено 18 августа 2026. Имена полей в SDK плывут; цикл нет: запрос → исполнение → возврат. Инструмент, который меняет диск, идёт в паре с песочницей файловой системы агента. Предпочтения между сессиями — в слое Memory, не в следующем arguments.
Почему свободный текст недостаточен (Why)
Раньше писали «вызови get_weather(city=Beijing)» и вырезали regex. Демо проходит; прод ломается в трёх местах:
- Нестабильный разбор — вежливость, переставленные аргументы, кавычки;
JSON.parseпадает. - Нет типов — enum становится свободным текстом; обязательные поля пропадают; параллельные вызовы не сопоставить.
- Побочные эффекты в чате — модель утверждает удаление, которого не было, или вы выполнили, а результат не вернули.
Function Calling оставляет выбор модели, а исполнение — runtime. HTTP, SQL и shell не происходят в процессе модели. Как в CI: один job — один workspace; граница раньше «умности».
Три слоя (What)
«Подключили OpenAI tools» — не архитектура. Минимум три слоя:
| Слой | Задача | Носитель | Владелец |
|---|---|---|---|
| L1 Schema | Имена, JSON Schema, описания, required | OpenAI tools[].function, Gemini functionDeclarations, Claude input_schema | Продукт |
| L2 Runtime | Валидация, секреты, timeout, retry, аудит | Свой цикл, LangGraph, Claude Code | Бэкенд / локальный агент |
| L3 Transport | Обнаружение и соединение процессов инструментов | HTTP, MCP stdio/SSE, внутренний RPC | Инфраструктура |
Асимметричный вывод: API вендоров стандартизируют JSON-конверт L1. Авторизацию L2 и изоляцию процессов L3 делаете вы. MCP — discovery и сессия, не автоматическая безопасность.
Цикл: модель не хранит ваши ключи; секреты только в runtime.
┌──────────────┐ JSON tool request ┌──────────────────┐
│ LLM API │ ────────────────────────► │ Your runtime │
│ (OpenAI / │ name + arguments │ (Agent loop) │
│ Gemini / │ │ │
│ Claude) │ ◄──────────────────────── │ execute tool │
└──────────────┘ tool result JSON │ • HTTP APIs │
│ • DB / search │
│ • shell / MCP │
└────────┬─────────┘
│
▼
┌──────────────────┐
│ Policy + secrets │
│ allowlist, audit │
│ Cloud Mac / VPC │
└──────────────────┘Сравнение: OpenAI vs Gemini vs Claude
| Поверхность | Вход | Исполнение | Контекст | Кому |
|---|---|---|---|---|
| OpenAI tools | Chat Completions / Responses | Выполняете вы; arguments часто JSON-строка | Параллельные tool_calls[]; optional strict | Уже есть OpenAI SDK или совместимый шлюз |
| Gemini functionDeclarations | Gemini API / Vertex | Выполняете вы; toolConfig.mode заставляет или запрещает | Типы часто OBJECT/STRING в верхнем регистре | GCP; продукты с переключателем mode |
| Claude tool_use | Messages API / Claude Code | Выполняете вы; input уже объект | Блоки: tool_use / tool_result | Anthropic, IDE-агенты, MCP |
| MCP-инструменты | Клиент ↔ MCP-сервер | В процессе сервера; модель только JSON | Каталог обнаруживается в runtime | Горячая замена каталогов |
В 2026 водораздел не «поддерживается ли» (все трое поддерживают), а строка vs объект, выравнивание параллели и запись ошибок назад. Шлюзы нормализуют в ToolCall{name, id, args} и один L2 runtime.
Как выглядит JSON (How)
Тот же get_weather. В проде в description пишите границы («только публичная погода, не личная геолокация»).
OpenAI: tools + tool_calls
Инструменты в запросе. При вызове в сообщении ассистента — tool_calls. arguments — строковый JSON: parse, затем validate.
{
"model": "gpt-4.1",
"messages": [{"role": "user", "content": "What's the weather in Beijing?"}],
"tools": [{
"type": "function",
"function": {
"name": "get_weather",
"description": "Current weather for a city",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string", "description": "City name"},
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
},
"required": ["city"]
}
}
}]
}{
"role": "assistant",
"tool_calls": [{
"id": "call_abc123",
"type": "function",
"function": {
"name": "get_weather",
"arguments": "{\"city\":\"Beijing\",\"unit\":\"celsius\"}"
}
}]
}После исполнения — role: tool (или эквивалент Responses) с тем же tool_call_id и строковым content.
Gemini: functionDeclarations + toolConfig
Объявления в tools[].functionDeclarations. mode: AUTO, ANY, NONE — продуктовый переключатель, не песочница.
{
"contents": [{"role": "user", "parts": [{"text": "What's the weather in Beijing?"}]}],
"tools": [{
"functionDeclarations": [{
"name": "get_weather",
"description": "Current weather for a city",
"parameters": {
"type": "OBJECT",
"properties": {
"city": {"type": "STRING"},
"unit": {"type": "STRING", "enum": ["celsius", "fahrenheit"]}
},
"required": ["city"]
}
}]
}],
"toolConfig": {"functionCallingConfig": {"mode": "AUTO"}}
}Модель отдаёт part functionCall; вы — functionResponse. Не считайте имена полей как у OpenAI.
Claude: tools + tool_use / tool_result
input_schema. Ответ — массив content-блоков. input уже объект; валидация всё равно нужна.
{
"model": "claude-sonnet-4-6",
"max_tokens": 1024,
"tools": [{
"name": "get_weather",
"description": "Current weather for a city",
"input_schema": {
"type": "object",
"properties": {
"city": {"type": "string"},
"unit": {"type": "string", "enum": ["celsius", "fahrenheit"]}
},
"required": ["city"]
}
}],
"messages": [{"role": "user", "content": "What's the weather in Beijing?"}]
}{
"role": "assistant",
"content": [{
"type": "tool_use",
"id": "toolu_01XYZ",
"name": "get_weather",
"input": {"city": "Beijing", "unit": "celsius"}
}]
}{
"role": "user",
"content": [{
"type": "tool_result",
"tool_use_id": "toolu_01XYZ",
"content": "{\"temp_c\": 28, \"condition\": \"clear\"}"
}]
}Claude Code и Cursor добавляют MCP. Модель по-прежнему видит каталог JSON Schema. Транспорт меняется, цикл нет.
Матрица выбора
| Если вы… | Берите | Почему |
|---|---|---|
| уже на шлюзе, совместимом с OpenAI | диалект OpenAI tools | самая большая экосистема; адаптеры один раз |
| в основном GCP / Vertex | Gemini + mode | меньше перевода; «этот ход обязан искать» |
| сначала Claude Code | Claude tools + MCP | совпадает с каталогом IDE |
| маршрутизируете три модели | внутренний ToolCall + адаптеры | не размазывать vendor if-else по бизнесу |
| правите файлы или команды | удалённый Mac + allowlist путей | красивый JSON не остановит ошибочный rm |
| только read-only SaaS API | serverless + секрет-менеджер | не нужна вся машина; параметры всё равно в allowlist |
Рекомендуемые стеки
A — соло, полдня: одна модель, 1–3 read-only инструмента, JSON Schema без additionalProperties, секреты в env, в логах только хеши.
B — небольшая команда: внутренний ToolCall, таймауты и лимиты на инструмент, записи на сессиях Cloud Mac, Memory отдельно. Та же дисциплина уничтожения, что у автоматизации удалённого Mac.
C — enterprise: ревью каталога, схема через PR, MCP в VPC, никакого безграничного bash. Добавьте глобальный выключатель деструктивных инструментов (аналог Gemini NONE) без редеплоя модели и храните audit JSONL вне volume рабочего пространства, чтобы destroy сессии не стирал след.
Ошибки
- Думать, что модель аутентифицирует — ключи в runtime.
- Считать OpenAI
argumentsобъектом — сначала parse. - Описания «сделай всё» — лишние вызовы.
- Игнорировать параллельные tool_calls — записи сериализовать.
- Глотать ошибки — возвращать структурированный error.
- MCP = безопасность — root в домашнем каталоге это весь диск.
Внедрение: 7 шагов
- Инвентарь (класс эффекта, timeout, резидентность).
- JSON Schema (required, enum, без additionalProperties).
- Минимальный цикл, один инструмент.
- Валидация, изоляция секретов, аудит.
- Второй vendor-адаптер как доказательство внутренней модели.
- Песочница для пишущих инструментов.
- 7 дней наблюдений, сузить схемы с частыми промахами.
FAQ
Чем отличается от JSON mode?
JSON mode задаёт форму финального ответа. Function Calling задаёт промежуточные запросы инструментов и обычно идёт несколько ходов после исполнения.
Может ли модель ходить в БД напрямую?
Нет, если runtime не выставил произвольный SQL без авторизации. По умолчанию модель только предлагает параметры по схеме.
Одна схема на трёх вендоров?
Ядро JSON Schema общее, конверты разные. Регрессионно проверяйте enum и required; strict ведёт себя не одинаково.
Инструменты Claude Code — это Function Calling?
Тот же цикл; каталог динамически даёт IDE/MCP, а не рукописный массив tools в каждом HTTP-запросе.
Класть результаты инструментов в долгую память?
Сырые payload большие и эфемерные. Суммируйте в Memory. См. справку.
Итог
Function Calling в 2026 — это RPC с JSON Schema. Три диалекта, одна грамматика. Безопасность — в L2 и изолированных хостах. Если не можете сказать, на какую машину и в какой каталог сейчас уйдёт write_file, не подключайте пишущие инструменты. Read-only API можно сегодня; правки кода и тесты — на уничтожаемом Cloud Mac; сначала цены.