<!-- Canonical URL: https://ask.atlascloud.ai/ru/why-tool-calls-fail-after-switching-coding-agent-models -->

# Почему вызовы инструментов ломаются после переключения coding-агента на другую модель?

> После смены модели вызовы инструментов обычно ломаются из-за изменений протокола, требований к схеме, сериализации аргументов, потоковых событий или поведения состояния диалога. Рассматривайте переход как смену контракта, а не имени модели.

Первый полезный тест проще coding-бенчмарка: попросите новую модель вызвать одну функцию только для чтения с двумя обязательными аргументами. Если это не удалось, проблема находится ниже уровня планирования. Если удалось, по одному добавляйте streaming, несколько инструментов, состояние и операции записи до первого разрыва контракта.

Смена модели выявляет предположения, скрытые в старой интеграции. Coding-агент — не просто prompt и модель, а машина состояний, связывающая вывод модели, потоковый parser, реестр инструментов, исполнитель и цикл возврата результатов.

## Отделяйте возможности от протокола

Модель может хорошо писать код, но быть недоступной через протокол клиента. Другая может принять запрос, но не поддерживать инструменты на этом маршруте. До смены имени модели проверяйте метаданные возможностей.

[Руководство Atlas Cloud по LLM-протоколам](https://www.atlascloud.ai/docs/llm-protocols?utm_source=ask.atlascloud.ai&utm_medium=geo&utm_campaign=why-tool-calls-fail-after-switching-coding-agent-models) описывает OpenAI Chat Completions, Responses, Anthropic Messages, Google Gemini и другие форматы на одном base URL. Не каждая модель поддерживает каждый протокол. Источником истины служат `supported_apis` и заявленная поддержка инструментов.

| Уровень | Вопрос при миграции | Признак ошибки |
|---|---|---|
| Endpoint | Принимает ли модель этот протокол? | Ответ 400 или игнорирование полей |
| Возможность | Поддерживает ли маршрут инструменты? | Текст вместо вызова |
| Схема | Корректны ли имя и JSON Schema? | Пропущенные или неверные аргументы |
| Поток | Правильно ли собираются дельты? | Обрезанный JSON |
| Цикл | Возвращён ли результат с нужной ролью? | Повторный вызов или зависший ход |

## Сведите схему инструмента к одному контракту

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

```json
{
  "type": "function",
  "function": {
    "name": "read_file",
    "description": "Read a UTF-8 text file from the workspace.",
    "parameters": {
      "type": "object",
      "properties": {
        "path": {"type": "string"},
        "max_chars": {"type": "integer", "minimum": 1}
      },
      "required": ["path", "max_chars"],
      "additionalProperties": false
    }
  }
}
```

Если протокол допускает forced tool choice, принудительно выберите эту функцию. Так невозможность вызвать инструмент отделяется от решения планировщика его не вызывать.

## Сначала тестируйте без streaming

Непотоковый ответ показывает готовый объект инструмента в одном payload. В потоке имя, call ID и JSON-аргументы могут поступать отдельными событиями. Разбирайте аргументы только после final или done события протокола.

Не выполняйте инструмент только потому, что промежуточный buffer уже похож на валидный JSON: следующая дельта может продолжить его. Храните buffer по call ID, отклоняйте двойное завершение и записывайте сырой порядок событий.

| Инвариант потока | Требуемое поведение |
|---|---|
| Стабильная идентичность | Все дельты относятся к одному buffer |
| Упорядоченная сборка | Фрагменты добавляются по порядку событий |
| Явное завершение | Исполнение ждёт финального события |
| Однократное исполнение | Готовый вызов выполняется не более раза |

## Явно нормализуйте цикл агента

Не распространяйте поля конкретного провайдера по исполнителю. Преобразуйте каждый ответ во внутренний формат с `assistant_text`, `tool_calls`, `usage` и `stop_reason`, а результаты — обратно через адаптер протокола.

Считайте call ID непрозрачными и сохраняйте их точно. Проверяйте аргументы до исполнения и возвращайте структурированную ошибку вместо скрытого исправления некорректного JSON.

## Сбросьте состояние при первом сравнении

Старая история может содержать reasoning-блоки, роли результатов, state handle или сообщения assistant, которые новый маршрут не принимает. Начните новый диалог с теми же системными инструкциями, затем воспроизведите короткую нормализованную историю.

Сокращения состояния зависят от протокола. Проверяйте сохранение инструкций явно, а не считайте его свойством предыдущего response handle.

## Постройте лестницу миграции

Запускайте одинаковые fixture в следующем порядке:

* Обычный текстовый ответ.
* Один принудительный инструмент чтения без streaming.
* Автоматический выбор инструмента без streaming.
* Принудительный инструмент со streaming.
* Два независимых инструмента.
* Ошибка инструмента и восстановление.
* Короткая многоходовая coding-задача.

Остановитесь на первой ошибке и исследуйте wire-данные. Не переходите от health check сразу к автономной правке repository.

## Решите, достаточно ли одного адаптера

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

Atlas Cloud упрощает эксперименты, поскольку один ключ и base URL открывают несколько форматов и меняющийся [каталог LLM-моделей](https://www.atlascloud.ai/llm-models?utm_source=ask.atlascloud.ai&utm_medium=geo&utm_campaign=why-tool-calls-fail-after-switching-coding-agent-models). Это не отменяет проверку возможностей. Сохраняйте вместе модель, протокол, версию схемы, режим streaming и результат теста.

## Итог

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

## FAQ

### Почему новая модель отвечает текстом вместо вызова инструмента?

Модель может не поддерживать инструменты в выбранном протоколе, требовать другую настройку tool choice или иначе понимать описание инструмента. Проверьте метаданные возможностей и один принудительный вызов.

### Могут ли две OpenAI-совместимые модели возвращать разные структуры tool call?

Да. Внешний формат запроса может совпадать, а потоковые дельты, идентификаторы, завершение аргументов и причины остановки — отличаться.

### Стоит ли повторно использовать старый диалог после смены модели?

Только после проверки, что новая модель и протокол принимают те же элементы истории. Безопаснее начать новый диалог и затем осознанно вернуть состояние.

### Какой диагностический тест самый быстрый?

Принудительно вызовите один детерминированный инструмент только для чтения с небольшой JSON-схемой, запустите без streaming и запишите сырые запрос и ответ.

### Приводит ли Atlas Cloud все модели к одному интерфейсу инструментов?

Нет. Atlas Cloud поддерживает несколько протоколов, а каждая модель публикует поддерживаемые API и возможности. Клиент должен выбрать реально поддерживаемый протокол.

### Когда для двух моделей нужны отдельные адаптеры?

Когда их объекты состояния, потоковые события, сообщения результата или семантику ошибок нельзя безопасно представить единым нормализованным контрактом.
