Совместимый API: начало миграции, а не её завершение

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

Документация DeepSeek описывает цикл tool calling: модель запрашивает функцию, приложение выполняет её и возвращает результат в историю диалога сообщением с ролью tool. Такой контракт упрощает адаптацию клиентского кода. Но он не переносит автоматически права сервисной учётной записи, бизнес-правила, сетевые ограничения и среду, где реально выполняется действие.

Полезно разделять три типа утверждений. Первый тип: документированный факт, например поддержка вызовов инструментов. Второй: инженерный план команды по переносу конкретного workflow на другой провайдер или runtime. Третий: ожидание по задержке, стоимости либо доле успешных задач. Последний тип нельзя считать доказанным до испытаний на одинаковом наборе сценариев, с одинаковыми инструментами и правами.

Для чат-бота без внешних действий смена endpoint действительно может оказаться небольшой задачей. Но чем больше у агента интеграций и операций записи, тем меньше его поведение определяется одним API модели. Проверять приходится весь путь от входного события до бизнес-результата.

  • Не считать совместимость API доказательством совместимости всего агентного процесса.
  • Оценивать отдельно API, поведение модели и фактическое исполнение действия.
  • Сравнивать стеки на одинаковых сценариях, а не по единичной демонстрации.
  • Фиксировать критерий успеха как корректную бизнес-операцию и отсутствие лишних операций.

Что переносится: состояние, правила, инструменты, доступы и исполнение

Первый слой миграции: состояние агента. Его точнее понимать как журнал событий, а не как «память модели». В таком журнале остаются системные инструкции, запросы пользователя, ответы модели, tool calls, результаты инструментов, ссылки на документы, статус задачи, число попыток и отметки о ручном подтверждении.

Критичны порядок событий и связь результата с конкретным tool_call_id. Если при переносе сохранить лишь текст переписки, но потерять уже выполненный вызов, агент может повторить операцию записи или продолжить workflow с неверной точки. Для создания заявки, отправки письма или изменения записи в CRM это уже не косметическая ошибка.

Второй слой: правила поведения. Это system prompt, примеры, политика отказов, пределы автономности, схемы аргументов и режим выбора инструмента. Их стоит хранить в репозитории и версионировать. Однако одинаковые инструкции не гарантируют одинакового решения на другой модели и в другом runtime: на результат влияют шаблон чата, parser вызовов и настройки структурированного вывода.

Третий слой: контракт инструмента. Для условного create_ticket недостаточно имени и входной JSON Schema. В переносимом описании нужны версия, ожидаемый результат, требуемая роль, правило повторного вызова, тайм-аут и требование approval. Идемпотентность означает, что повтор с тем же ключом не должен создать второй тикет.

Четвёртый и пятый слои: доступы и execution plane. OAuth-токены, service accounts, scopes, секреты, сетевые ACL и правила согласования не перемещаются вместе со схемой функции. Не переносится автоматически и среда выполнения кода и команд: образ контейнера, версии SDK, файловые mounts, egress-политика, ресурсные лимиты, отмена задач и журналирование.

  • Состояние: event log, артефакты, tool_call_id и статусы workflow.
  • Поведение: prompts, схемы, режимы tool choice и политики отказов.
  • Интеграции: адаптеры, credentials, scopes, сети и approval.
  • Исполнение: sandbox, контейнеры, квоты, retry и cancellation.
  • Наблюдаемость: версии, трассы, ошибки и исходы бизнес-операций.

Контекст не равен кэшу провайдера

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

Без отдельного журнала после сбоя трудно понять, где именно возникла неисправность. Модель могла выбрать неверное действие, parser мог неверно извлечь аргументы, а интеграция могла выполнить некорректный вызов. Если все эти этапы сведены к одному сообщению об ошибке, команда будет отлаживать систему по симптомам.

Отдельная ловушка: server-side context cache. DeepSeek описывает кэширование как механизм полного совпадения префикса контекста и возвращает поля prompt_cache_hit_tokens и prompt_cache_miss_tokens. Это оптимизация обработки токенов на стороне сервиса, а не переносимая память агента.

После смены endpoint или модели кэш разумно считать холодным. Если старый маршрут регулярно использовал cache hit, а новый начинает с пустого кэша, первые замеры смешают разницу стеков с эффектом прогрева. Это не аргумент против перехода, а требование к методике измерений.

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

  • Не путать историю задачи с server-side context cache.
  • Сохранять ссылки на RAG-документы и файлы, а не только их пересказ в сообщениях.
  • Помечать cache hit и cache miss в телеметрии.
  • Сравнивать холодный и прогретый режимы отдельно.
  • Хранить версии промптов и схем рядом с записью конкретного вызова.
Цитата в переводе

«Модель сама решит, вызывать инструменты или нет.»

DeepSeek API Docsдокументация API
Цитата в переводе

«Модель должна вызвать один или несколько инструментов.»

DeepSeek API Docsдокументация API

Где ломается tool calling: от схемы до parser-а

Представим агента, который получает письмо клиента, выделяет тему и дедлайн, а затем вызывает create_ticket. На первый взгляд сценарий переносим: в обоих стеках есть массив tools и JSON Schema. Но дальше возникает вопрос, который меняет поведение системы: модель должна вызвать функцию, может сделать это по своему усмотрению или обязана ответить текстом?

DeepSeek документирует tool_choice со значениями auto, required, none и возможностью принудительно выбрать конкретную функцию. В режиме auto решение остаётся за моделью. В режиме required она должна вызвать один или несколько инструментов. Проверки способности модели вызвать функцию недостаточно: нужно отдельно тестировать каждый используемый режим, включая отказ от вызова, когда данных для операции недостаточно.

В документации vLLM для автоматического вызова инструментов отдельно выделены parser, chat template и настройки структурированного вывода. В другом runtime вызов может иначе извлекаться из свободного текста, а аргументы могут не соответствовать ожидаемой схеме. Перенос описания функции не означает переноса гарантии, что она будет выбрана и корректно заполнена.

DeepSeek также описывает strict mode для tool calls как Beta-возможность, требующую beta endpoint. Сервер валидирует переданную JSON Schema. Для миграции это полезный, но локальный факт: режим следует проверять в конкретной конфигурации и не распространять его семантику на любой OpenAI-совместимый маршрут.

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

  • Прогонять auto, required, none и принудительный named tool отдельно.
  • Проверять enum, массивы, optional-поля, лишние и пустые значения.
  • Фиксировать parser и chat template в конфигурации окружения.
  • Тестировать запрет write-действия при недостатке данных или без approval.
  • Проверять поведение после невалидного результата инструмента и повторного запроса.
Цитата в переводе

«У человека всегда должна быть возможность участвовать в контуре и отклонить вызов инструмента.»

Model Context Protocolспецификация протокола

MCP унифицирует интерфейс интеграции, но не переносит всего агента

Model Context Protocol полезен как стандартизированный слой интеграции. Сервер публикует инструменты, их метаданные и схемы, а клиент может единообразнее обнаруживать доступные возможности. В мультивендорной среде это сокращает число специальных адаптеров между агентной оболочкой и трекером, CRM, хранилищем или внутренним сервисом.

Однако MCP не служит архивом всего процесса. Он не переносит автоматически секреты, роли, сетевую связность, интерфейс согласования, бизнес-логику оркестратора и правила, по которым операция допускается к исполнению. Набор доступных tools способен зависеть от авторизации, поэтому его нельзя считать одинаковым для всех сервисных ролей.

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

Версионность транспорта тоже входит в миграционный контур. В changelog MCP от 28 июля 2026 года отмечены изменения Streamable HTTP, server-minted handles для переноса состояния, требования к metadata и capabilities, а также deprecated-статус HTTP+SSE. Это не означает, что весь стек нужно немедленно заменить. Но команде нужно проверять negotiation версий, capabilities и поведение при неподдерживаемом транспорте.

Практическая граница ответственности проста: MCP-server может быть переносимым интерфейсом интеграции, однако права, approval и наблюдаемость необходимо явно проверять в новом клиенте и окружении.

  • Версионировать MCP-схемы и поддерживаемые версии протокола.
  • Проверять перечень tools отдельно для каждой сервисной роли.
  • Описывать approval как policy-as-code, а не как неявную настройку клиента.
  • Тестировать разрыв соединения и неподдерживаемые capabilities.
  • Хранить правила доступа и жизненный цикл секретов вне описания tool.

Sandbox и выполнение команд: граница между намерением и действием

Вызов инструмента моделью ещё не означает безопасного исполнения. DeepSeek Harness в developer preview различает native function calling и code mode. В code mode модель работает через транспорт run_code; прямой вызов другого инструмента завершается UNKNOWN_TOOL. Один и тот же агентный сценарий может не заработать после переноса не из-за качества модели, а из-за другого способа предоставить ей инструменты.

Документация Harness отдельно указывает, что timeoutMs в определении инструмента сам по себе не создаёт дедлайн исполнения: для реального ограничения требуется отдельная policy-обёртка. Это показательная разница между декларацией в схеме и фактическим поведением runtime. Миграционная проверка должна отвечать не на вопрос «есть ли timeout в JSON», а на вопрос «действительно ли задача прерывается в целевой среде».

Для агента, выполняющего команды, E2E-тест нужно проводить на том же классе окружений, где будет production. В проверку входят контейнерный образ, разрешённые пакеты, рабочая директория, права на файлы, DNS, прокси, egress, ресурсные лимиты, выдача секретов и отмена задач. Иначе успешный тест подтверждает лишь работоспособность на стенде.

Особого контроля требуют shell-команды, удаление объектов, отправка писем, создание заявок и публикации в репозитории. Здесь нужны минимальные привилегии, allowlist, идемпотентные ключи и возможность человека отменить действие. Это дисциплина любой системы, имеющей доступ к внешнему миру, а не свойство отдельной модели.

  • Разделять control plane и execution plane.
  • Не считать поле timeout действующей защитой без runtime-policy.
  • Проверять sandbox и сетевые правила в целевом окружении.
  • Для write-операций требовать идемпотентность и проверяемое подтверждение.
  • Проверять отмену задачи, повтор после сбоя и очистку временных артефактов.

Migration gate: проверки до переключения трафика

Первый артефакт перед миграцией: contract pack для каждого провайдера и runtime. В нём фиксируются поддерживаемые роли сообщений, streaming и non-streaming, tool_choice, strict-схемы, параллельные вызовы, классы ошибок и retry policy. Эти свойства нельзя переносить из рекламного описания или предполагать по сходству API: их следует подтверждать probe-тестами в целевой конфигурации.

Второй артефакт: набор золотых трасс. Это обезличенные реальные или синтетические сценарии с инвариантами. В них должен быть выбран допустимый инструмент, аргументы должны пройти валидацию, должна быть выполнена нужная бизнес-операция и не должно появиться лишнее write-действие. Формулировка финального ответа полезна для оценки, но не может быть единственным критерием качества.

Третий артефакт: матрица «роль × инструмент × операция». Агент с tracker-read и агент с tracker-write являются разными системами, даже если у них один prompt и одна модель. В матрице следует проверить 401, 403, истёкший токен, отсутствие scope и изменение списка MCP-tools для конкретной учётной записи.

Нужны и негативные сценарии: ошибка интеграции, недоступная сеть, пустой результат инструмента, неожиданный тип ответа, частичный streaming, повтор запроса, отмена по тайм-ауту и отказ человека от операции. Эти случаи важнее серии обычных запросов: они показывают, не появятся ли дубликаты и не потеряется ли контекст после сбоя.

До cutover требуется телеметрия. В трассу полезно включать provider, model и версию, версию схемы, tool_call_id, сервисную идентичность, sandbox policy, задержку этапов, cache-поля, класс ошибки и бизнес-исход. Иначе после переключения команда увидит только общий симптом и не отделит проблему модели от parser-а, прав или сети.

  • Запускать shadow traffic или replay trace до боевого переключения.
  • Считать успехом корректное действие и отсутствие лишних действий.
  • Заранее определить критерий отката по критичным операциям.
  • После cutover отдельно наблюдать прогрев кэша и новые классы ошибок.
  • Сохранять результаты probe-тестов вместе с версией адаптера и конфигурации.

Российский контекст: локальные интеграции повышают цену неявных зависимостей

Для российских команд переносимость особенно важна, когда агент связан с корпоративным трекером, базой знаний, почтой, CRM и внутренними API. Yandex Cloud описывает MCP как способ подключать агентов к системам и заявляет для своей платформы функции управления доступом, подтверждения tool calls, логирования и мониторинга. Это сведения поставщика о собственном продукте, а не независимое сравнение платформ или моделей.

Платформенные механизмы могут быть частью рабочего контура. Риск возникает, когда критичные правила существуют только в закрытой конфигурации конкретного вендора. Схемы tools, тестовые трассы, инфраструктурные манифесты, политики и описание прав следует хранить в vendor-neutral репозитории.

Тогда модельный backend, включая DeepSeek, остаётся заменяемым компонентом, а логика процесса не исчезает при смене платформы. Такой подход требует больше дисциплины на старте, явных контрактов и тестов. Зато следующий эксперимент обходится дешевле: команда меняет один слой и сверяет его с прежним на одинаковых трассах, вместо того чтобы заново собирать промпты, секреты и ручные настройки.

  • Хранить секреты в штатном vault, а не в prompt или описании tool.
  • Документировать права и сетевые зависимости рядом с кодом интеграции.
  • Использовать платформенное логирование, но сохранять критичные трассы в общем контуре наблюдаемости.
  • Проверять сценарии с реальными корпоративными ограничениями, а не только с публичными API.

Что это означает на практике

Миграция агента с DeepSeek или на DeepSeek должна восприниматься как перенос управляемого процесса. Совместимый интерфейс сокращает объём клиентской переделки, но не заменяет карту состояния, контрактов и политик. Ключевой вопрос перед переключением звучит не «получили ли мы ответ от модели», а «сохранили ли мы контролируемое и воспроизводимое исполнение задачи».

Если состояние хранится вне вендора, инструменты версионированы как контракты, политика исполнения определена явно, а критические цепочки проходят E2E-проверки, модельный backend становится заменяемым слоем. MCP может уменьшить число интеграционных адаптеров, а DeepSeek способен упростить подключение через совместимый API, но ни один стандарт не отменяет инженерную проверку процесса.

  • Не заменять один base URL без карты состояния, prompts, tools, доступов, sandbox и наблюдаемости.
  • Вести vendor-neutral event log с tool_call_id, версиями схем и статусами workflow.
  • Оформлять tool как контракт с input/output schema, ролью, идемпотентностью, политикой времени и approval.
  • Разделять тест валидного tool call и тест безопасного исполнения в целевой сети и sandbox.
  • Для нового backend отдельно проверять auto, required, named tool и none.
  • До cutover запускать golden traces и негативные тесты: 401/403, ошибки интеграции, timeout, повтор, пустой результат и отказ человека.
  • Сохранять телеметрию шагов: provider, model, версия, schema version, tool_call_id, policy, cache-метрики, задержки и outcome.

Источники

Частые вопросы

Можно ли перенести агента на DeepSeek простой заменой base URL?

Только в простом чат-сценарии без внешних действий это может быть близко к правде. Для агентного workflow нужно отдельно переносить и проверять состояние, режимы tool calling, parser, права, sandbox, сетевые правила и наблюдаемость.

Чем server-side context cache отличается от памяти агента?

Кэш провайдера оптимизирует обработку совпадающего префикса контекста. Память агента должна быть независимым журналом workflow с сообщениями, результатами tools, идентификаторами вызовов, версиями и ссылками на артефакты.

Что нужно тестировать в tool calling при миграции?

Отдельно проверяют режимы auto, required, none и принудительный вызов named tool, соответствие аргументов схеме, обработку невалидного результата, повторы, отсутствие разрешения и запрет операции записи без approval.

Переносит ли MCP доступы и правила согласования?

Нет. MCP помогает унифицировать публикацию и обнаружение инструментов, но секреты, роли, сетевую связность, бизнес-политику, approval и наблюдаемость необходимо переносить и проверять отдельно.

Какие артефакты нужны до переключения боевого трафика?

Минимальный набор включает contract pack для провайдера и runtime, золотые трассы с инвариантами, матрицу «роль × инструмент × операция», негативные сценарии, критерии отката и телеметрию этапов исполнения.

Практический чек-лист

Чек-лист migration gate для агентного workflow

Материал предназначен для отдельного PDF в downloads/checklist-migration-gate-deepseek.pdf. Перед переключением трафика пройдите пункты по состоянию, инструментам, доступам, исполнению и наблюдаемости.

Состояние и воспроизводимость

  • Журнал workflow хранится вне модельного провайдера.
  • Для вызовов сохранены tool_call_id, статусы, версии промптов и схем.
  • Ссылки на документы и внешние артефакты доступны из нового контура.
  • Кэш провайдера не используется как единственное хранилище истории.
  • Холодный и прогретый режимы измеряются отдельно.

Инструменты и политики

  • Для каждого tool описаны входная и ожидаемая выходная схема, версия и роль.
  • Определены идемпотентный ключ, retry policy, тайм-аут и правило approval.
  • Проверены auto, required, none и named tool.
  • Parser и chat template закреплены в конфигурации runtime.
  • Write-операции блокируются при недостатке данных или отсутствии подтверждения.

Доступы и исполнение

  • Для каждой сервисной роли проверен фактический список доступных tools.
  • Пройдены сценарии 401, 403, истёкшего токена и отсутствующего scope.
  • Проверены секреты, DNS, прокси, egress, файловые права и лимиты sandbox.
  • Тайм-аут действительно прерывает задачу через runtime-policy.
  • Проверены отмена задачи, повтор после сбоя и отсутствие дубликатов.

Переключение и наблюдаемость

  • Подготовлен contract pack целевого провайдера и runtime.
  • Золотые трассы содержат допустимое действие и отсутствие лишнего write-действия.
  • Пройдены негативные сценарии с ошибками интеграции, сети и streaming.
  • Определены условия отката по критичным операциям.
  • Трассы содержат provider, model, версию, schema version, tool_call_id, policy, cache-метрики, задержки и outcome.

Вопросы и ответы

Можно ли перенести агента на DeepSeek простой заменой base URL?

Только в простом чат-сценарии без внешних действий это может быть близко к правде. Для агентного workflow нужно отдельно переносить и проверять состояние, режимы tool calling, parser, права, sandbox, сетевые правила и наблюдаемость.

Чем server-side context cache отличается от памяти агента?

Кэш провайдера оптимизирует обработку совпадающего префикса контекста. Память агента должна быть независимым журналом workflow с сообщениями, результатами tools, идентификаторами вызовов, версиями и ссылками на артефакты.

Что нужно тестировать в tool calling при миграции?

Отдельно проверяют режимы auto, required, none и принудительный вызов named tool, соответствие аргументов схеме, обработку невалидного результата, повторы, отсутствие разрешения и запрет операции записи без approval.

Переносит ли MCP доступы и правила согласования?

Нет. MCP помогает унифицировать публикацию и обнаружение инструментов, но секреты, роли, сетевую связность, бизнес-политику, approval и наблюдаемость необходимо переносить и проверять отдельно.

Какие артефакты нужны до переключения боевого трафика?

Минимальный набор включает contract pack для провайдера и runtime, золотые трассы с инвариантами, матрицу «роль × инструмент × операция», негативные сценарии, критерии отката и телеметрию этапов исполнения.