В этом материале
Отсутствие значения, null и пустой контейнер имеют разную семантику. Преобразовывать их можно только по явно описанному контракту.
Тест API часто использует только заполненный user message. Такой вход не показывает, что произойдёт с отсутствующим content, явным null или пустым массивом инструментов. Ошибка нормализации способна изменить смысл запроса ещё до запуска модели. Для провайдера это отдельная область контракта: нужно описать допустимые сочетания роли, содержимого и дополнительных полей, а затем проверить их на реальном интерфейсе.
Не смешивайте четыре представления
Поле может отсутствовать, содержать null, пустую строку или пустой массив. Это разные JSON-значения и разные структуры объекта. Публичная схема OpenRouter показывает конкретные формы сообщений и ответов, но её нельзя превращать в общее разрешение любого сочетания полей у произвольного движка.
В собственном контракте укажите, какие варианты допустимы для каждой роли. Например, сообщение с tool calls проверяется не тем же fixture, что обычная текстовая реплика. Если адаптер заполняет пропуски автоматически, такое действие должно иметь отдельное правило и тест.
Зафиксируйте правила схемы
JSON Schema отличает отсутствие обязательного свойства от свойства со значением null. Перечень properties сам по себе не делает каждое поле обязательным. Поэтому локальный валидатор должен использовать именно ту схему, с которой сравнивается сервер, а не приблизительный объект из примера.
Проверьте дополнительные свойства и вложенные объекты отдельно. Нельзя удалять незнакомое поле, а затем считать исходный запрос полностью поддержанным. Сначала нужно определить выбранную политику, область её действия и то, какое сообщение увидит вызывающая сторона при нарушении.
Постройте компактный набор fixtures
Возьмите один базовый запрос и создайте варианты, меняя одно условие: content удалён, content равен null, content пустой, tools пустой. Для каждого заранее запишите ожидаемую классификацию: принятие, явный отказ либо документированное преобразование.
Файл результата содержит fixture ID, исходное тело и наблюдаемую форму ответа. Пароли, внутренние адреса и реальные пользовательские диалоги для такого набора не нужны. Сохраняйте также версию адаптера: изменение нормализации может проявиться только после обновления зависимости.
Проверяйте до и после адаптации
Если доступна внутренняя тестовая граница, сравните вход клиента с запросом, переданным движку. Это позволяет отделить ошибку схемы от неподдерживаемой роли и от поведения chat template. Без такой границы вывод ограничивается внешним наблюдением, что следует прямо отметить в отчёте.
RFC 8259 определяет синтаксис JSON, но не прикладную корректность сообщения модели. Валидный документ не обязательно является допустимым запросом. Аналогично успешный парсинг на сервере не подтверждает, что пустая реплика сохранила ожидаемый смысл после преобразования.
Сохраните различия в релизном тесте
После изменения валидатора повторите весь небольшой набор, а не только базовый пример. Отказ вместо прежнего преобразования может быть осознанным изменением контракта, но он должен быть виден в release notes и ожидаемых результатах. Непреднамеренное сведение всех пустых состояний к одному значению является поводом для разбора.
Контекст запросов разобран в первом примере Python, а сообщения инструментов — в материале о tool calling. Эти инструкции описывают применение интерфейса; fixtures проверяют его точные границы и не подтверждают одобрение провайдера сторонней платформой.