Сигнал есть, подтверждённого дефекта DeepSeek нет

Утверждение, что DeepSeek теряет ввод после принудительного завершения процесса, было бы чрезмерным. В каталоге есть публикация с таким заголовком и датой 13 августа 2026 года, но ссылка ведёт через RSS-агрегатор. По ней нельзя установить версию рантайма, устройство очереди, настройки хранилища, точную последовательность событий и позицию разработчиков.

Название deepseek-harness также не делает проект официальным компонентом DeepSeek. Один из доступных репозиториев с таким именем принадлежит стороннему автору Henry Zhang, а не организации deepseek-ai. Его материалы могут помочь при изучении или воспроизведении сценариев, но переносить свойства этого проекта на инфраструктуру DeepSeek нельзя.

Поэтому предмет разбора иной: как интегратору восстановить агентский контур, если хост аварийно завершился во время обработки сообщения. Репозиторий DeepSeek-V3 относится к модельному слою; журнал событий, диспетчер задач, политика подтверждений и протокол восстановления остаются ответственностью команды, которая разрабатывает продукт.

  • Сигнал из RSS-агрегатора не является официальным признанием дефекта DeepSeek.
  • Сторонний harness нельзя называть официальным рантаймом DeepSeek.
  • Crash-recovery нужно проверять в собственном контуре: gateway, очереди и хранилище.
Цитата в переводе

«После принудительного завершения DSH host и перезапуска пользовательский ввод появляется поздно или вовсе не появляется: write-behind batching теряет незафиксированный хвост.»

Неустановленный авторзаголовок стороннего bug report; перевод редакции

Что означает «потерянный хвост» при write-behind

В типовой агентской схеме host принимает сообщение, присваивает ему идентификатор, показывает пользователю статус приёма, помещает работу в очередь и передаёт её worker’у. Чтобы ускорить обработку, часть изменений может накапливаться в памяти и записываться в хранилище пакетно. Такой подход называют write-behind batching: между приёмом данных процессом и их долговременной фиксацией остаётся временное окно.

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

Исчезновение сообщения из интерфейса не всегда означает безвозвратную потерю. Оно может появиться позднее, если успело попасть во внешний брокер, но ожидает нового назначения. Запись может остаться в состоянии running, если она закреплена за уже умершим worker’ом. Внешний инструмент, в свою очередь, способен сработать дважды, если вызов состоялся, а подтверждение результата не успело попасть в журнал.

Поэтому нельзя объявлять write-behind причиной конкретного сигнала без логов. Нужны время клиентского подтверждения, идентификатор события, границы commit, содержимое очереди и состояние задачи до и после рестарта. Сторонний репозиторий может описывать тестовые сценарии, но его результаты нельзя автоматически считать характеристикой DeepSeek или другого агентского стека.

  • Позднее появление события и его безвозвратная потеря — разные сценарии.
  • Подтверждение до durable commit создаёт риск расхождения между обещанием интерфейса и состоянием системы.
  • Зависший running и повтор внешнего действия требуют отдельных механизмов recovery.

Deadlocked agents: почему restart ещё не означает recovery

В эксплуатации словом deadlock часто называют любую зависшую сессию. При расследовании полезно различать настоящий взаимный блок ресурсов и orphaned work: работу, которая числится занятой, хотя process или worker, владевший ею, уже завершился. После kill особенно важен второй сценарий: в базе остаётся запись о владельце, но самого владельца уже нет.

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

Практический ответ: ограниченное по времени владение задачей, то есть lease, heartbeat и поколение владельца либо fencing token. После истечения срока работу получает новый worker. Если прежний процесс позднее пытается записать результат, хранилище должно отличить устаревшего владельца от нового. Это нужно и для снятия зависания, и для предотвращения параллельных действий двух агентов в одной сессии.

Правило «после рестарта повторить всё» небезопасно. Повтор поиска или чтения данных может быть приемлем, но повтор создания заявки, изменения записи или отправки сообщения способен создать второй бизнес-эффект. В issue Kimi Code описан близкий по классу случай: после падения терминала сохранённый transcript не удалось безопасно продолжить с DeepSeek; обходным действием стал откат последнего шага, а не безусловное автоматическое возобновление.

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

  • Lease без срока может навсегда удерживать задачу после смерти worker’а.
  • При записи результатов новый владелец должен быть отличим от прежнего.
  • Автоповтор допустим только при идемпотентности действия или надёжной сверке эффекта.

Почему неполный tool-loop особенно опасен

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

DeepSeek-V3 предоставляет модельный код и примеры инференса, но историю сериализует, сохраняет и передаёт в следующий запрос именно интегратор. При работе с reasoning-состоянием и инструментальными шагами сохранённый контекст должен соответствовать фактически завершённым стадиям. Если сообщения переставлены, tool result не связан с исходным вызовом или шаг ассистента записан лишь частично, следующий запрос может оказаться непригодным для продолжения.

Особенно уязвимы промежуточные состояния: reasoning уже получен, но итоговый content ещё пуст; tool call сформирован, но не зафиксирован; инструмент выполнился, но его результат не привязан к вызову. Сохранять такую запись как завершённое сообщение ассистента значит создавать формально похожую, но логически неполную историю.

Механика риска видна в стороннем issue Kimi Code. После crash/restart локально сохранённый незавершённый assistant-step был преобразован в запрос, который DeepSeek отверг с HTTP 400: у assistant message не были заданы ни content, ни tool calls. Это не доказательство потери пользовательского ввода и не разбор первопричины DeepSeek, а пример того, что адаптер обязан валидировать transcript перед resume.

Отдельный симптом описан в issue #1453: пользователь сообщил о пустых ответах после tool results при HTTP 200, без content, без reasoning_content и с нулевым числом completion tokens. В репорте нет подтверждённого разбора первопричины, поэтому он не доказывает дефект модели. Однако этот случай показывает, почему оркестратор не должен считать любой HTTP 200 полноценным завершением агентского шага.

  • Незавершённый assistant-step следует хранить как partial, а не как финальную реплику.
  • Для resume необходимы порядок сообщений, связи tool call и tool result, а также версия сериализатора.
  • HTTP 200 сам по себе не гарантирует результат, пригодный для продолжения.
Цитата в переводе

«Некорректное сообщение assistant: должны быть заданы content или tool_calls.»

Автор issue #1404 в MoonshotAI/kimi-codeсторонний интегратор; имя и должность в каталоге не раскрыты; перевод редакции

Не склеивайте разные причины в один «сбой модели»

Потеря подтверждённого пользовательского ввода обычно относится к ingress, очереди, persistence layer или политике подтверждений: модель могла вовсе не увидеть сообщение. Невалидный диалог после рестарта связан с сериализацией transcript и восстановлением tool-loop. Пустой ответ модели — отдельный симптом. У этих случаев могут различаться владельцы, журналы и способы исправления.

Issue Kimi Code относится прежде всего ко второму классу: в нём описана проблема на границе сохранённой истории и корректной последовательности сообщений при возобновлении. Это полезный пример интеграционного последствия crash/restart, но не подтверждение того, что DeepSeek теряет пользовательский ввод.

Issue #1453 нельзя связывать с write-behind, force-kill или deadlock. Автор приводит собственные наблюдения: 22 пустых и 24 обычных ответа в заявленном сценарии. Это данные одного репортёра, а не независимая статистика надёжности сервиса.

Такая дисциплина особенно нужна при обсуждении production-систем. Громкий диагноз может направить команду к исправлению не того слоя: например, к смене модели вместо пересмотра подтверждений и commit-точек или к настройке базы вместо валидации сообщений. Проверяемая формулировка должна описывать симптом, границу компонента и условия воспроизведения.

  • Потерянный подтверждённый ввод: вопрос durable ingress.
  • Ошибка следующего запроса после рестарта: вопрос адаптера и протокола tool-loop.
  • Пустой ответ модели требует отдельных метрик и воспроизведения.
  • Ни один из этих симптомов не подтверждает write-behind bug у DeepSeek.

Минимальная архитектура восстановления

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

Второе правило: не использовать единственный перезаписываемый JSON диалога как источник истины. Снимок удобен для чтения, но журнал событий позволяет установить, было ли принято сообщение, когда задачу назначили, какой worker ею владел, начался ли tool call и зафиксирован ли результат. После аварии от этого зависит, что можно продолжить, а какое состояние следует признать неопределённым.

Третье правило: разделять намерение выполнить внешнее действие и подтверждение его эффекта. До вызова инструмента сохраняется tool_call_intent с идемпотентным ключом, после вызова: результат или receipt. Если процесс погиб между этими этапами, recovery worker сперва сверяет эффект с внешней системой, а не повторяет действие вслепую.

Четвёртое правило: для генерации и tool-loop нужна явная политика работы с незавершённостью. Частичный ответ нельзя безусловно добавлять в следующую историю как законченное сообщение. Ему нужны статус partial, причина остановки и решение recovery: отбросить шаг, сгенерировать новый или продолжить лишь в условиях, которые допускает конкретный протокол. Случай Kimi Code показывает, что сохранённый фрагмент transcript ещё не гарантирует безопасного resume.

  • Подтверждайте приём после durable ingress, а не после локальной RAM-очереди.
  • Event log хранит факты; snapshot ускоряет чтение, но не заменяет журнал.
  • Для внешних эффектов нужны intent, идемпотентный ключ и receipt.
  • Неполные модельные и инструментальные шаги должны иметь отдельный статус.

Crash-test для production RAG и агентов

Проверка восстановления должна входить в release-процесс. Сериям входящих сообщений присваивают уникальные event_id, фиксируют момент клиентского подтверждения и durable commit, затем хост принудительно останавливают в заданных точках. После рестарта журнал сверяют с тем, что было обещано пользователю, и с действиями, которые могли быть отправлены во внешние системы.

Полезная матрица включает остановку после HTTP ACK, но до append; после append, но до commit; после commit, но до назначения worker’у; во время tool call; после внешнего действия, но до записи receipt; во время фиксации assistant-step и tool-state. Такой тест не доказывает свойства чужого SaaS или стороннего harness, зато даёт воспроизводимый ответ о собственной очереди, базе, gateway и оркестраторе.

Результат следует выражать в наблюдаемых показателях: сколько подтверждённых event_id удалось восстановить, сколько времени заняло возвращение к приёму задач, сколько runs осталось в running, были ли повторные внешние эффекты, удалось ли продолжить tool-loop без ошибки схемы. Для DeepSeek-интеграции отдельно проверяют полноту контекста: порядок сообщений, наличие обязательных полей и связи tool calls с результатами.

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

  • После каждого kill сверяйте все подтверждённые event_id с durable log.
  • Проверяйте порядок, истёкшие lease, повторы внешних эффектов и валидность resume.
  • В сценарии должны быть частичные assistant-step и незавершённые tool calls.
  • Фиксируйте версии модели, SDK, сериализатора, хранилища и настройки TTL.

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

Надёжность агентского контура после аварии определяется не тем, насколько убедительно выглядит восстановленное окно чата. Важнее, может ли команда объяснить судьбу каждого принятого события, владельца задачи, стадию tool-loop и эффект внешнего вызова.

  • Подтверждайте пользователю приём сообщения только после durable-фиксации входящего события с идентификатором и ключом идемпотентности.
  • Ведите append-only журнал событий. Snapshot диалога используйте для ускорения чтения, но не как единственный источник истины.
  • Ограничивайте lease по времени, добавляйте heartbeat и различайте поколения владельцев задачи.
  • Разделяйте tool_call_intent, исполнение и effect_receipt: после сбоя сначала сверяйте эффект, затем решайте вопрос о повторе.
  • Храните tool-loop как структурированное состояние с порядком сообщений, связями вызовов и результатов, а также флагом partial.
  • Проводите управляемые crash-тесты и измеряйте потерю подтверждённых событий, зависшие runs, дубли эффектов и валидность resume.
  • Не приписывайте DeepSeek дефект на основании одного стороннего issue: отделяйте API-симптом, ошибку адаптера и сбой persistence layer.

Вывод

Сигнал вокруг deepseek-harness не даёт оснований утверждать, что DeepSeek теряет пользовательские сообщения из-за write-behind batching. Для такого вывода нужны проверяемый первоисточник, версии компонентов, логи и воспроизводимый сценарий.

Сам класс отказов игнорировать нельзя. После crash/restart production-агент должен восстановить не только окно чата, но и объяснимое состояние: принятый ввод, владельца задачи, стадию tool-loop и статус каждого внешнего эффекта. Для DeepSeek-интеграций это критично там, где неполный transcript делает следующий запрос невалидным.

Для команды правильный вопрос звучит так: какие события и действия система сможет доказуемо объяснить и безопасно продолжить после рестарта? Ответ дают crash-тест, журнал событий и строгие commit-точки, а не предположение о поведении модели.

Источники

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

Подтверждает ли сигнал вокруг deepseek-harness потерю сообщений DeepSeek?

Нет. Доступный материал ведёт через RSS-агрегатор, а в каталоге нет проверяемого подтверждения из официального пространства deepseek-ai. Сторонний harness нельзя переносить на инфраструктуру DeepSeek.

Почему перезапуск хоста не всегда восстанавливает агента?

После аварии задача может остаться в состоянии running за уже умершим worker’ом. Для восстановления нужны ограниченный по времени lease, heartbeat и различение поколений владельцев.

Чем опасен неполный tool-loop после рестарта?

Частично сохранённый assistant-step, несвязанный tool result или неверный порядок сообщений могут сделать следующий запрос невалидным. Неполное состояние следует помечать отдельно, а не выдавать за финальную реплику.

Когда можно повторять внешний tool call после сбоя?

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

Что проверять в crash-тесте DeepSeek-интеграции?

Нужно сопоставить все подтверждённые event_id с durable log, проверить порядок сообщений, истёкшие lease, повторные внешние эффекты, частичные шаги и валидность resume.

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

Чек-лист crash-теста DeepSeek-агента

Материал полезно сохранить как отдельную памятку для release-процесса. Для локальной сборки подготовить файл downloads/deepseek-agent-crash-test-checklist.pdf и добавить его в лист Downloads с кнопкой «Скачать PDF».

До теста

  • Присвойте каждому входящему сообщению уникальный event_id.
  • Зафиксируйте момент клиентского подтверждения и момент durable commit.
  • Определите идемпотентные ключи для внешних действий.
  • Зафиксируйте версии модели, SDK, сериализатора, хранилища и настройки TTL.

Точки аварийной остановки

  • Остановите хост после HTTP ACK, но до append.
  • Остановите хост после append, но до commit.
  • Остановите хост после commit, но до назначения worker’у.
  • Остановите хост во время tool call.
  • Остановите хост после внешнего действия, но до записи receipt.
  • Остановите хост во время фиксации assistant-step и tool-state.

Проверка после рестарта

  • Сверьте все подтверждённые event_id с durable log.
  • Проверьте порядок сообщений и связи tool call с tool result.
  • Выявите runs, оставшиеся в состоянии running, и истёкшие lease.
  • Проверьте, не появились ли повторные внешние эффекты.
  • Проверьте, что частичные assistant-step не подставлены как финальные сообщения.
  • Проверьте валидность resume и следующего запроса к модели.

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

Подтверждает ли сигнал вокруг deepseek-harness потерю сообщений DeepSeek?

Нет. Доступный материал ведёт через RSS-агрегатор, а в каталоге нет проверяемого подтверждения из официального пространства deepseek-ai. Сторонний harness нельзя переносить на инфраструктуру DeepSeek.

Почему перезапуск хоста не всегда восстанавливает агента?

После аварии задача может остаться в состоянии running за уже умершим worker’ом. Для восстановления нужны ограниченный по времени lease, heartbeat и различение поколений владельцев.

Чем опасен неполный tool-loop после рестарта?

Частично сохранённый assistant-step, несвязанный tool result или неверный порядок сообщений могут сделать следующий запрос невалидным. Неполное состояние следует помечать отдельно, а не выдавать за финальную реплику.

Когда можно повторять внешний tool call после сбоя?

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

Что проверять в crash-тесте DeepSeek-интеграции?

Нужно сопоставить все подтверждённые event_id с durable log, проверить порядок сообщений, истёкшие lease, повторные внешние эффекты, частичные шаги и валидность resume.