Function calling у OpenAI, Anthropic и Google: чем отличаются
Три крупных вендора дают моделям вызывать внешние функции по-разному — от формата описания инструментов до параллельных вызовов. Разбираем, что это значит для кода и переносимости.

Function calling перестал быть экспериментальной фичей и стал основой почти любого приложения поверх LLM: поиск по базе, обращение к API, запуск кода, оформление заказа. Модель не выполняет функцию сама — она возвращает структурированный JSON с именем функции и аргументами, а вызывает её уже ваш код. Проблема в том, что у OpenAI, Anthropic и Google этот механизм устроен по-разному: разный формат описания инструментов, разные поля в ответе, разное поведение при параллельных вызовах. Перенести агента с одного вендора на другой без правки кода не получится.
Что вообще происходит при вызове функции
Схема у всех концептуально одна. Вы отправляете модели список доступных инструментов с их JSON-схемами. Модель решает, нужен ли вызов, и если да — возвращает имя функции и аргументы. Ваш код выполняет функцию, отдаёт результат обратно в диалог, и модель формулирует финальный ответ. Различия начинаются в деталях, а именно в них живут баги.
Ключевых точек расхождения три:
- Формат описания инструмента. Где лежит JSON-схема параметров и как называются поля.
- Формат ответа модели. Как именно возвращается вызов — отдельным типом сообщения, полем в ответе или блоком контента.
- Параллельные вызовы. Может ли модель за один ход запросить несколько функций сразу и как вы возвращаете результаты.
OpenAI
У OpenAI инструменты передаются в поле tools, каждый — с типом function и JSON-схемой в parameters. В ответе модель кладёт вызовы в tool_calls, у каждого есть уникальный id. Результат вы возвращаете отдельным сообщением с ролью tool и тем же tool_call_id — именно по нему модель сопоставляет ответ с запросом.
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Погода в городе",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string"}
},
"required": ["city"]
}
}
}
Параллельные вызовы включены по умолчанию: модель может вернуть сразу несколько элементов в tool_calls. Отдельно есть режим Structured Outputs со строгим соблюдением схемы (strict: true), который гарантирует, что аргументы точно совпадут с описанной структурой, а не будут просто «похожи» на неё.
Anthropic (Claude)
Anthropic использует модель контентных блоков. Инструменты описываются в поле tools, но схема параметров лежит в input_schema, а не в parameters. Когда Claude хочет вызвать функцию, он возвращает блок контента типа tool_use с полями id, name и input. Результат вы отправляете блоком tool_result в сообщении с ролью user, ссылаясь на tool_use_id.
Это принципиальное отличие от OpenAI: там результат функции — отдельная роль tool, здесь — часть пользовательского сообщения. Параллельные вызовы поддерживаются: в одном ответе может быть несколько блоков tool_use. Anthropic также продвигает связку function calling с расширенным режимом рассуждения, где модель планирует последовательность вызовов.
Google (Gemini)
У Gemini инструменты передаются через function_declarations, схема параметров описывается в формате, близком к OpenAPI. В ответе приходит functionCall с полями name и args, а результат возвращается частью functionResponse. Идентификаторов вызова в стиле OpenAI здесь исторически нет — сопоставление идёт по имени функции, что усложняет обработку нескольких вызовов одной и той же функции за ход.
Gemini поддерживает разные режимы работы инструментов (авто, обязательный вызов, запрет вызова), что удобно, когда нужно жёстко заставить модель либо всегда вызывать функцию, либо никогда.
Сравнение
| Параметр | OpenAI | Anthropic (Claude) | Google (Gemini) |
|---|---|---|---|
| Поле схемы параметров | parameters | input_schema | parameters (OpenAPI-стиль) |
| Формат вызова в ответе | tool_calls c id | блок tool_use c id | functionCall без id |
| Роль для результата | tool | user (блок tool_result) | function / user |
| Параллельные вызовы | Да, по умолчанию | Да | Да |
| Строгое соблюдение схемы | Structured Outputs (strict) | Частично | Ограниченно |
| Управление режимом вызова | tool_choice | tool_choice | function_calling_config |
Точные наборы полей и доступность отдельных режимов зависят от версии модели и API — сверяйтесь с актуальной документацией вендора, потому что форматы за последний год менялись несколько раз.
Самая частая ошибка при переносе агента между вендорами — не сама логика, а сопоставление результатов с вызовами. У OpenAI и Claude есть id, у Gemini исторически нет. Код, который надёжно работает на одном, молча теряет ответы на другом.
Кому это пригодится и кому нет
Пригодится:
- Разработчикам агентов, которым нужно ходить в несколько внешних API за один запрос — параллельные вызовы экономят раунды диалога.
- Тем, кто строит извлечение структурированных данных: строгая схема (Structured Outputs у OpenAI) избавляет от парсинга «почти-JSON».
- Командам с мультивендорной стратегией — им критично заранее заложить абстракцию над форматами, а не переписывать интеграцию при смене модели.
Скорее не нужно:
- Если у вас один простой запрос без внешних действий — обычной генерации текста хватит, function calling добавит только сложности.
- Если задача — жёсткая детерминированная бизнес-логика без вариативности: там надёжнее обычный код, а не модель, решающая, когда вызвать функцию.
- Если бюджет на токены ограничен: описания инструментов и промежуточные вызовы расходуют контекстное окно*, и цепочка из нескольких вызовов может выйти дороже, чем ожидалось.
Как выбирать
- Определите, нужны ли вам параллельные вызовы — если да, проверьте, как вендор возвращает несколько результатов и есть ли у вызовов идентификаторы.
- Оцените важность строгой схемы: для извлечения данных режим strict у OpenAI заметно снижает число ошибок парсинга.
- Если планируете менять вендора, сразу вынесите формат инструментов в отдельный слой-адаптер, а не размазывайте по коду.
- Считайте стоимость не за один вызов, а за полную цепочку диалога с промежуточными результатами.
Цены на токены и лимиты у всех трёх вендоров меняются регулярно — актуальные значения смотрите на страницах тарифов OpenAI, Anthropic и Google AI, а не в статьях полугодовой давности.
* Контекстное окно — максимальный объём текста (в токенах), который модель удерживает за один запрос: сюда входят и системный промпт, и описания инструментов, и вся история диалога с результатами вызовов.
Prompt-инженер: Идеальные запросы для Midjourney, ChatGPT и других моделей.
Спросить за 15 ₽Источники: OpenAI Platform Docs — Function calling, Anthropic Docs — Tool use with Claude
Частые вопросы
Можно ли написать один код под всех трёх вендоров?
Модель сама выполняет функцию?
Гарантирует ли function calling корректный JSON в аргументах?
Что делать, если модель вызвала функцию, которой нет?
Поддерживают ли все вендоры несколько вызовов за один ход?
Насколько сильно function calling увеличивает расход токенов?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.