Симптом: локальный скрипт работает, но после переноса на облачный Mac теряются каталоги, сессии или процесс не возвращается после сбоя. Самое быстрое решение: сначала выполните одну безопасную задачу в отдельной рабочей области, затем зафиксируйте версии SDK и runtime, вынесите session_root из репозитория и только после этого подключайте постоянный запуск.

Этот материал подходит автоматизаторам, которые управляют задачами DeepSeek Harness из Python. Он также нужен платформенным инженерам, готовящим облачный Mac для длительных Agent-сессий, и руководителям, которым требуется проверить, действительно ли переданная среда восстанавливается после остановки или перезапуска.

**Последнее обновление: 18 августа 2026 года.** Данные сверены с [официальным репозиторием DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness), [руководством по Python SDK](https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/user/guide/python-sdk.md), [описанием пакета runtime](https://github.com/deepseek-ai/deepseek-harness/blob/master/python/sdk-runtime/README.md), [карточкой пакета в PyPI](https://pypi.org/project/deepseek-harness-sdk/) и [документацией Python по виртуальным окружениям](https://docs.python.org/3/library/venv.html). Команды и требования ниже относятся к состоянию документации на эту дату.

Этап 1. Фиксация границ запуска

До установки определите, что именно вы разворачиваете:

  • одноразовый Python-скрипт, который завершается после ответа;
  • периодическую задачу, запускаемую расписанием;
  • долгоживущий Agent-процесс, который принимает несколько заданий;
  • проверочную среду для передачи другому разработчику или заказчику.
Это не формальность. Для одноразового запуска можно создать временную рабочую область и удалить её после проверки. Для непрерывного Agent-процесса понадобятся отдельные каталоги, резервные копии, политика остановки и понятный владелец восстановления.

Официальное руководство указывает предварительные условия для текущей линии Python SDK: Python 3.10 или новее, Git, macOS 14 или новее на arm64, совместимый API endpoint и изолированная рабочая область, которую Agent может изменять. Проверяйте эти требования по актуальному руководству SDK, потому что developer preview может меняться без обратной совместимости.

Для облачного Mac сначала нужно проверить не название модели, а фактическую архитектуру и версию системы:

uname -m
sw_vers -productVersion
python3 --version
git --version

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

Проверьте также три скрытых ограничения:

  1. Права доступа. Python-процесс должен читать конфигурацию и изменять только назначенную рабочую область.
  2. Диск. В рабочем каталоге появляются исходники и результаты, а в session_root — журналы и состояние сессий. Нельзя считать эти два пространства одним и тем же.
  3. Ответственность за процесс. SDK запускает runtime как дочерний процесс, но это не означает, что он сам становится системным daemon, настраивает автоматический перезапуск или гарантирует восстановление после сбоя.
Для выбора подходящей среды полезно заранее свериться с [руководством по окружению Mac для Agent-задач](https://macgpu.com/ru/m4-rukovodstvo.html). Там важнее не максимальная конфигурация, а доступность SSH, постоянного диска и понятного способа повторного подключения.

Этап 2. Изолированная установка SDK

Python SDK и runtime нужно устанавливать в отдельное виртуальное окружение. Не используйте системный Python, не ставьте пакет в каталог общего проекта и не копируйте на сервер весь локальный venv: такой перенос часто связывает окружение с локальными путями и архитектурой. Механизм venv предназначен именно для создания изолированного набора Python-пакетов, что подтверждается официальной документацией Python.

Создайте базовую структуру:

mkdir -p "$HOME/dsh-deploy"/{app,workspace,sessions,logs,backup}
cd "$HOME/dsh-deploy/app"

python3 -m venv .venv
. .venv/bin/activate

python -m pip install --upgrade pip
python -m pip install deepseek-harness-sdk

Пакет deepseek-harness-sdk импортируется в Python как deepseek_harness. Установка также подтягивает совместимый пакет предварительно собранного runtime той же версии; конкретный состав зависимостей проверяйте по карточке пакета в PyPI и официальному README runtime.

По официальной документации, для обычного использования предварительно собранного runtime отдельная установка системного Node.js не нужна. Node.js остаётся требованием для сборки runtime или wheel из исходного кода. Это принципиальная граница: не устанавливайте исходное монорепо только потому, что в документации для разработчиков упоминаются Node.js и pnpm.

Зафиксируйте фактическое состояние:

python -m pip show deepseek-harness-sdk
python -m pip freeze > "$HOME/dsh-deploy/app/requirements.lock.txt"
python -c "import deepseek_harness; print(deepseek_harness.__file__)"

В файл передачи среды добавьте:

  • дату установки;
  • результат sw_vers -productVersion;
  • результат uname -m;
  • версию Python;
  • вывод pip show;
  • источник установки;
  • путь к рабочему каталогу;
  • путь к session_root.
На первом запуске не подключайте настоящий репозиторий и не используйте старую сессию. Создайте выбрасываемую рабочую область:
mkdir -p "$HOME/dsh-deploy/workspace-smoke"
printf '# Smoke test\n' > "$HOME/dsh-deploy/workspace-smoke/README.md"

Успешный сигнал этого этапа — импорт модуля и запуск runtime без ошибок. Если процесс не стартует, откат выполняется удалением .venv и повторной установкой зафиксированного пакета, а не переносом случайных файлов из локальной машины.

Этап 3. Минимальная задача и проверяемый результат

Теперь нужно проверить не только ответ модели, но и весь путь: модель, рабочую область, редактор и Bash. Официальный пример запускает задачу с абсолютными путями workspace, session-root и session-id; сверяйте синтаксис с текущей версией руководства SDK:

cd "$HOME/dsh-deploy/app"
. .venv/bin/activate

export DEEPSEEK_API_KEY='ваш-ключ'
# export DEEPSEEK_BASE_URL='https://совместимый-endpoint/v1'
# export DSH_MODEL='deepseek-v4-flash'

python examples/jsonrpc-agent/minimal.py \
  --workspace "$HOME/dsh-deploy/workspace-smoke" \
  --session-root "$HOME/dsh-deploy/sessions" \
  --session-id smoke-001 \
  "Прочитайте README.md, создайте файл result.txt с одной строкой OK и покажите итоговый путь."

Если в вашем checkout отсутствует каталог с примером, не подменяйте его произвольным API-вызовом: возьмите актуальный пример из ветки репозитория, которую вы зафиксировали в журнале установки. Это особенно важно для developer preview, где интерфейсы и имена файлов могут меняться без обратной совместимости.

Результат принимайте только при наличии четырёх независимых доказательств:

  1. входной текст задания сохранён в журнале запуска;
  2. рабочая область указана абсолютным путём;
  3. в ответе присутствует итоговый путь к result.txt;
  4. файл действительно существует и содержит ожидаемое содержимое.
Проверка на уровне оболочки:
test -f "$HOME/dsh-deploy/workspace-smoke/result.txt"
cat "$HOME/dsh-deploy/workspace-smoke/result.txt"
find "$HOME/dsh-deploy/sessions" -type f -maxdepth 3 -print

SDK работает поверх построчного JSON-RPC через stdio, а журнал сессии сохраняется в формате JSONL. Эти детали относятся к реализации и схеме взаимодействия, поэтому перед приёмкой сверяйте их с техническим описанием проекта, а не только с примером команды.

Ошибка может находиться не в модели, а в несовпадении конфигурации, пути runtime, праве записи или параметрах запуска дочернего процесса.

Если задача завершилась ошибкой, откатите её до трёх отдельных тестов:

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

Этап 4. Рабочий каталог, сессия и состояние Bash

У Python SDK есть три разных понятия, которые нельзя смешивать:

  • cwd — рабочая область, доступная Agent;
  • session_root — каталог журналов и состояния;
  • session_id — идентификатор конкретной продолжительной сессии.
Пример явной конфигурации:
from pathlib import Path
from deepseek_harness import DeepSeekHarness

workspace = Path.home() / "dsh-deploy" / "workspace"
sessions = Path.home() / "dsh-deploy" / "sessions"

with DeepSeekHarness(
    provider="deepseek-official",
    model="deepseek-v4-flash",
    cwd=str(workspace),
    session_root=str(sessions),
) as harness:
    result = harness.run(
        "Проверьте состояние рабочей области и опишите только обнаруженные файлы.",
        session_id="project-a-001",
    )

print(result.final_response)
session_root лучше размещать вне репозитория, но на том же постоянном диске, если вы хотите быстро продолжать задачу после перезапуска. Не храните его в /tmp: временный каталог удобен для smoke-теста, но непригоден как источник восстановления.

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

Используйте такие правила:

  • новая задача — новый session_id;
  • следующий шаг той же задачи — прежний session_id;
  • другой репозиторий — отдельные cwd и session_root;
  • другой владелец или окружение — новый префикс идентификатора;
  • после смены версии SDK сначала тестовая сессия, затем продолжение рабочей.

**Важно:** одинаковый session_id не превращает два независимых процесса в безопасный кластер. Он лишь указывает на состояние, которое процессы пытаются продолжить. Параллельные записи, разные конфигурации и одновременный запуск могут привести к конфликтам, поэтому такую схему нужно отдельно тестировать.

Этап 5. Ключи и процессная ответственность

Ключ API передавайте через переменную окружения или защищённый файл, права на который ограничены владельцем:

mkdir -p "$HOME/dsh-deploy/secrets"
printf '%s\n' 'ваш-ключ' > "$HOME/dsh-deploy/secrets/deepseek.env"
chmod 600 "$HOME/dsh-deploy/secrets/deepseek.env"

set -a
. "$HOME/dsh-deploy/secrets/deepseek.env"
set +a

Не добавляйте ключ в:

  • requirements.lock;
  • Git-репозиторий;
  • session_root;
  • JSONL-журналы;
  • launch-скрипт, который передаётся третьей стороне;
  • команды, попадающие в историю оболочки.
Если используется прокси, отдельно задайте DEEPSEEK_BASE_URL. Сначала проверьте endpoint простым запросом, затем запускайте Agent-задачу. Не меняйте одновременно ключ, модель, endpoint и конфигурацию runtime: иначе при сбое вы не поймёте, какой компонент оказался причиной.

Для постоянной работы опишите владельца каждого действия:

  • кто запускает процесс;
  • кто останавливает его по таймауту;
  • где лежат логи;
  • кто удаляет старые журналы;
  • кто проверяет место на диске;
  • кто восстанавливает сессию после reboot;
  • кто утверждает обновление SDK.
SDK не следует описывать как встроенную систему управления процессами. Если вам нужен автоматический запуск, используйте внешний механизм macOS или собственный оркестратор, но сначала испытайте ручной сценарий запуска и остановки. Для диагностики оставляйте stdout и stderr в отдельном каталоге:
mkdir -p "$HOME/dsh-deploy/logs"

python run_agent.py \
  >> "$HOME/dsh-deploy/logs/agent.log" \
  2>> "$HOME/dsh-deploy/logs/agent.error.log"

FAQ: установка и продолжение сессий

Проверка после перезапуска

Восстановление нужно проверять как процедуру, а не как обещание. Сначала остановите Python-процесс во время безопасной задачи. Затем снова активируйте то же виртуальное окружение, загрузите те же переменные, укажите прежние абсолютные пути и запустите продолжение с тем же session_id.

Перед продолжением выполните безопасную проверку:

test -d "$HOME/dsh-deploy/workspace"
test -d "$HOME/dsh-deploy/sessions"
python --version
python -m pip show deepseek-harness-sdk

После этого попросите Agent только описать последнюю зафиксированную точку и содержимое рабочего каталога. Нельзя сразу отправлять команду «продолжите исправление»: если предыдущий шаг успел изменить файл, повторная команда может выполнить изменение ещё раз.

Проверяйте три сценария:

  1. процесс завершён вручную;
  2. SSH-соединение разорвано, но хост продолжил работу;
  3. Mac перезапущен и процесс нужно поднять заново.
Успешное восстановление означает, что cwd не изменился, session_root читается, история доступна, а повторный запуск не создаёт новую задачу вместо продолжения старой.

Этап 6. Приёмка и решение о расширении

Перед передачей среды отметьте каждый пункт:

  • [ ] Архитектура Mac проверена как arm64.
  • [ ] Версия macOS соответствует текущему руководству SDK.
  • [ ] Python находится в отдельном виртуальном окружении.
  • [ ] Установлены SDK и runtime совместимых версий.
  • [ ] Пакеты и источник установки записаны в журнал.
  • [ ] Рабочая область не совпадает с каталогом сессий.
  • [ ] session_root находится на постоянном диске.
  • [ ] API-ключ не попадает в репозиторий и журналы.
  • [ ] Выполнена задача чтения файла.
  • [ ] Выполнена задача изменения файла.
  • [ ] Выполнена проверка Bash.
  • [ ] Для новой задачи создан новый session_id.
  • [ ] Продолжение старой задачи проверено отдельно.
  • [ ] Процесс остановлен вручную и запущен снова.
  • [ ] Проверен сценарий разрыва удалённого подключения.
  • [ ] Смоделирован перезапуск Mac.
  • [ ] Зафиксирован безопасный способ отмены или отката.
  • [ ] Определены резервируемые каталоги.
  • [ ] Записана процедура возврата на прежнюю версию SDK.
Не расширяйте параллельность и не увеличивайте срок аренды только потому, что одна smoke-задача завершилась успешно. Сначала получите повторяемое восстановление на одной рабочей области. Затем добавляйте вторую задачу с отдельными cwd, session_root и session_id.

Сравнение вариантов развёртывания

<
ВариантЧто проверяетсяОсновной рискОценка для длительного Agent
Локальный Mac разработчикаБыстрый прототип и ручная отладкаСон, смена сети, личные права и незаписанные зависимости3/5
Облачный Mac с ручным запускомПовторяемая среда и удалённый доступПосле перезапуска нужен оператор4/5
Облачный Mac с внешним менеджером процессаЗапуск, остановка и журналированиеОшибка менеджера может повторно отправить задачу4/5
Копия локального проекта «как есть»Минимум подготовительных действийСломанные пути, утечки ключей и смешение состояния1/5
Для короткого теста достаточно изолированного виртуального окружения и ручной команды. Для непрерывной работы облачный Mac обычно удобнее личного ноутбука: его проще оставить доступным, передать другому инженеру и проверить по одной инструкции. Но это не отменяет резервного копирования и не превращает SDK в готовый production-оркестратор.

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

Текущий подход — запускать всё на личном Mac или просто копировать локальную папку в облачную среду — имеет четыре слабых места: состояние часто лежит в непредсказуемом месте, ключи оказываются в shell-истории, процесс не имеет заранее назначенного владельца, а восстановление после reboot проверяется только после реальной аварии. Поэтому для временной проверки разумнее арендовать через MACGPU отдельный облачный Mac, получить чистую среду, провести описанную приёмку и завершить аренду после подтверждения результата. Для постоянной тяжёлой эксплуатации, физического доступа к периферии или строгой корпоративной интеграции сначала оцените собственный Mac и внутреннюю инфраструктуру — аренда нужна не всегда.

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