needhelp
← Back to blog

DeepSeek Harness: фреймворк агентов с открытым кодом, где буквально всё — плагин

by needhelp
DeepSeek
AI Agents
Open Source
Cordis
Plugin Architecture

Полный агентский стек, выложенный на GitHub

13 августа 2026 года DeepSeek выпустил developer preview DeepSeek Harness (dsh). Репозиторий находится по адресу deepseek-ai/deepseek-harness. К концу дня у него было 1.6k звёзд, 12 293 коммита и 19 контрибьюторов — цифры, по которым понятно, что это не хакатон за выходные. Кодовая база на 97.1% написана на TypeScript, 1.6% — CSS, 0.7% — Python. Версия пакета на момент публикации: 0.1.0-rc.5.

Лендинг — deepseek.com/harness, документация для разработчиков — deepseek-harness.github.io/deepseek-harness.

Лицензия — MIT.

Однострочное позиционирование

Из README: «Агент = Модель + Harness».

Модель — это душа. Harness позволяет агенту понимать окружение, использовать инструменты и продолжать работать в реальных условиях. По замыслу DeepSeek, каждая возможность — модели, инструменты, навыки, сессии, песочницы, хранилище, циклы, планирование и UI — это заменяемый плагин.

Это не лозунг. Это закреплено архитектурой.

Cordis: ядро под всем стеком

DeepSeek Harness построен на основе Cordis — встроенного фреймворка плагинов. Дизайн Cordis описан в статье A Programming Paradigm for Spatiotemporal Composability.

Весь фреймворк сводится к пяти идеям:

  1. Плагин — это объект, реализующий Service. Это может быть функция с inject и apply(ctx) или подкласс Service.
  2. Контекст — это реестр сервисов. Плагин занимает стабильный ключ вроде ctx.tools, ctx.llm или ctx.sessions. Другие плагины находят сервисы по ключу, а не через импортирование конкретных реализаций.
  3. Зависимости сервисов объявляются через inject. Плагин, перечисливший нужные сервисы, ожидает их появления. Ручная последовательность загрузки не нужна.
  4. Типизированные события для коммуникации. Четыре режима диспетчеризации: emit (отправил и забыл), waterfall (middleware-стиль с next()), parallel (все слушатели запускаются одновременно) и serial (слушатели выполняются по порядку с возвратом значений).
  5. Регистрации — это обратимые эффекты. Секции промптов, схемы инструментов, адаптеры, слушатели — всё устанавливается через ctx.effect(), поэтому перезагрузка и очистка отрабатывают предсказуемо.

Модель waterfall в Cordis работает по принципу around-middleware. Слушатель получает (...args, next). Вызов next() передаёт управление следующему сервису; возврат без next() обрывает цепочку. Для событий с единственным решением обрыв цепочки — это и есть задумка: слушатель политики может единолично принять решение.

Всё — плагин (серьёзно)

Список плагинов на deepseek.com/harness раскрывает весь набор возможностей:

  • Models — бэкенды LLM (DeepSeek, OpenAI, Anthropic, Bedrock, Vertex, Azure, Codex и любой OpenAI-совместимый endpoint)
  • Tools — то, что может вызывать модель
  • Skills — переиспользуемые связки промптов и инструментов
  • Sessions — управление состоянием диалога
  • Sandboxes — среда выполнения кода (PTY bash, локальный бэкенд danger-full-access, нативная песочница на основе landlock)
  • Storage — персистентность сессий
  • Loops — логика ходов агента
  • Scheduling — диспетчеризация саб-агентов и задач
  • UI — Web UI, по умолчанию на порту 3080

Разработчик может выбирать, заменять или расширять любую из этих частей через конфигурацию — без изменений в исходном коде DeepSeek Harness. Plugin Config Catalog генерируется автоматически из исходников (scripts/gen-config-catalog.ts) и заново проверяется в CI, поэтому каждое поле в блоке config: в cordis.yml точно соответствует объявленному типу конфигурации плагина.

Четыре режима исполнения

В документации четыре пресета. Каждый под свою задачу.

Standard Mode — полноценный coding-агент: редактирование файлов, shell, поиск по файлам и вебу, навыки, планирование, цели, саб-агенты и workflows. Это режим Web UI по умолчанию.

Code Mode — всё из Standard, но инструменты доступны через Code Mode SDK, так что модель может объединять многошаговые операции в одной TypeScript-программе. Одна программа, сгенерированная моделью, заменяет несколько раундов вызовов инструментов.

Minimal Mode — всего два инструмента: постоянный bash shell и str_replace_editor. Для бенчмаркинга моделей в урезанном окружении. Без навыков, планирования и саб-агентов — чистая способность модели против реальной кодовой базы.

Creator Mode — создан для написания собственных пресетов агентов. Включает все возможности Standard Mode плюс инспекцию рантайма, эксперименты с плагинами Cordis в памяти и руководства по авторству пресетов. Именно так вы собираете пятый, шестой, седьмой режимы.

Каждый запуск трассируется

Это то, чем Harness отличается от большинства агентских инструментов. Всё, что видит модель, записывается в журнал сессий с режимом «только добавление»:

  • Системные промпты
  • Вывод reasoning
  • Вызовы инструментов и их результаты
  • Решения планировщика саб-агентов
  • Каждое внедрение контекста

В Web UI есть Trajectory view, где можно просматривать эти записи с фильтрацией по источнику. Возобновление, ветвление, поиск и воспроизведение — все четыре операции работают с одним и тем же потоком событий. Никакой отдельной базы трассировок, никакого экспорта. JSONL сессии и есть источник истины.

Для Python SDK каталог сессий хранит несжатый JSONL с собранными запросами к модели и вызовами инструментов. Пример в examples/jsonrpc-agent/minimal.py демонстрирует это от начала до конца.

Конфигурация моделей: DeepSeek + всё остальное

Страница конфигурации моделей (Configure models) имеет три слоя.

DeepSeek Official. Открываем Settings → Models, вставляем API-ключ DeepSeek, сохраняем. Ключ доступен только для записи. После сохранения UI получает замаскированный дескриптор, никогда — открытый текст. Ключи хранятся в \$DSH_HOME/.credentials.yaml; на странице настроек остаётся только ссылка на учётные данные.

Catalog providers. Нажимаем «Add provider», выбираем Anthropic или OpenAI, вставляем ключ. Провайдеры с нативной аутентификацией (Bedrock через AWS creds + region, Vertex через ADC project, Azure через api-version, Codex через OAuth) не работают с одним полем API key — каждому нужен свой путь авторизации.

Custom providers. Для корпоративных gateway, self-hosted серверов или любого провайдера, которого нет в каталоге. Задаём Provider ID в нижнем регистре (постоянный — запросы, сохранённые сессии, дефолты моделей и ссылки на учётные данные используют именно его), base URL, протокол API, учётные данные и хотя бы одну модель.

Для визуальных моделей нужен ещё один шаг. Так как custom endpoint не может сообщить о поддерживаемых модальностях, форма не определит поддержку vision автоматически. Добавляем input: [text, image] к модели в \$DSH_HOME/settings.yaml. Если все ваши custom модели принимают изображения, задайте defaultInput: [text, image] один раз на уровне провайдера, а не для каждой модели. Поле input — это утверждение, а не проверка: если вы заявляете, что модель поддерживает vision, а endpoint на самом деле нет, провайдер отвергнет запрос раньше, чем Harness.

В документации расписано и устранение неполадок:

  • MISSING_CREDENTIAL → сохраните ключ провайдера через страницу Models или экспортируйте указанную env-переменную
  • UNKNOWN_MODEL → выберите сконфигурированную модель или добавьте недостающую модель к custom provider
  • «Get available models returns 401» → проверьте ключ. Discovery моделей вызывает OpenAI-совместимый endpoint GET /models. Если ваш сервис не предоставляет его, введите модели вручную.
  • «Image rejected before send» → модель не объявила модальность image. Добавьте input: [text, image].
  • «Provider rejects a request with an image» → модель заявила поддержку vision, которой на самом деле нет у endpoint. Удалите image из списка и начните новую сессию (старое изображение остаётся в журнале сессии и будет повторять тот же запрос).

Начало работы: три пути

Путь 1: npx @deepseek-ai/dsh web

Устанавливаем Node.js, выполняем одну команду. Web UI запускается на http://127.0.0.1:3080. И всё. Без clone, build, pnpm.

Terminal window
npx @deepseek-ai/dsh web

Далее: Settings → Models → вставляем API-ключ DeepSeek. Выбираем workspace (подойдёт директория, из которой был вызван dsh). Начинаем сессию:

Суммируйте этот репозиторий и определите его основные пакеты.

Агент читает и редактирует файлы workspace, выполняет команды, делегирует работу и поддерживает план. Любая операция, требующая одобрения согласно активной политике разрешений, вызывает диалог в Web UI перед исполнением.

Путь 2: Клонируем и собираем из исходников

Terminal window
git clone https://github.com/deepseek-ai/deepseek-harness.git
cd deepseek-harness
pnpm install
pnpm run build
pnpm dsh web

Путь 3: Python SDK

Требования: Python 3.10+, Linux x64 / Linux arm64 / macOS 14+ на arm64, DeepSeek-совместимый endpoint.

Terminal window
git clone https://github.com/deepseek-ai/deepseek-harness.git
cd deepseek-harness
python -m venv .venv
. .venv/bin/activate
python -m pip install deepseek-harness-sdk

Настраиваем учётные данные:

8000/v1
export DEEPSEEK_API_KEY=sk-your-key-here
# Optional:
# export DSH_MODEL=deepseek-v4-flash
# export DSH_SYSTEM_PROMPT='You are a helpful software engineer assistant.'

Запускаем задачу в изолированном workspace:

Terminal window
python examples/jsonrpc-agent/minimal.py \
--workspace /absolute/path/to/workspace \
--session-root /absolute/path/to/sessions \
--session-id example-001 \
"Inspect the repository and fix the failing tests."

В своём коде точка входа SDK — DeepSeekHarness как контекст-менеджер:

from pathlib import Path
from deepseek_harness import DeepSeekHarness
config = Path("examples/jsonrpc-agent/minimal.cordis.yml").resolve()
workspace = Path("/absolute/path/to/workspace").resolve()
sessions = Path("/absolute/path/to/sessions").resolve()
with DeepSeekHarness(
provider="deepseek-official",
model="deepseek-v4-flash",
max_tokens=49_152,
cwd=str(workspace),
session_root=str(sessions),
cordis=str(config),
) as harness:
result = harness.run(
"Inspect the repository and fix the failing tests.",
session_id="example-001",
)
print(result.final_response)

DeepSeekHarness лениво запускает встроенный рантайм и переиспользует его до выхода из блока with. Используйте тот же session ID, чтобы сохранить Bash-процесс (рабочую директорию, env-переменные, shell-функции). Для независимой задачи — новый session ID.

Минимальная композиция jsonrpc-agent намеренно скудная: только постоянный bash и str_replace_editor как инструменты, доступные модели. Таймаут Bash — 300 секунд. Лимит вывода редактора — 16 000 символов. Уплотнение контекста отключено. Файловая система использует чистый локальный бэкенд — пути редактора могут обращаться ко всему, что видит процесс рантайма. В документации прямо указано: «Запускайте это только внутри одноразового checkout или контейнера». Постоянный PTY-бэкенд также требует POSIX-терминал — для этой композиции поддержки Windows нет.

Пишем первый плагин

Учебник: Your first plugin. Плагин — это TypeScript-модуль, экспортирующий функцию apply:

import type { Context } from '@deepseek-ai/cordis'
export const name = 'hello-plugin'
export function apply(ctx: Context) {
console.log('[hello-plugin] plugin loaded!')
}

Регистрируем в патче cordis.yml:

- insert:
- id: hello
name: '/absolute/path/to/deepseek-harness/scratch-plugin/src/my-plugin.ts'

Запускаем с оверлеем:

Terminal window
pnpm dsh web --patch ./scratch-plugin/cordis.yml

Убийственная фича — автоматическая очистка. Всё, что зарегистрировано через ctx — слушатели событий, инструменты, таймеры — очищается при выгрузке плагина. Никаких ручных removeListener или clearInterval. Для явной очистки (сетевые соединения) возвращайте диспоузер из ctx.effect().

Зависимости объявляются через inject:

export const name = 'my-tool-plugin'
export const inject = ['tools']
export function apply(ctx: Context) {
// ctx.tools is ready here
}

Cordis дожидается всех обязательных сервисов перед загрузкой плагина.

Существует три формы плагина: функция (выше), объект с apply и класс, наследующий Service. Используйте класс, когда сам плагин предоставляет сервис для потребления другими плагинами.

Пишем первый инструмент

Учебник: Build a tool. Используем defineTool из @deepseek-ai/dsh-tools:

import type { Context } from '@deepseek-ai/cordis'
import { defineTool } from '@deepseek-ai/dsh-tools'
export const name = 'greet-tool'
export const inject = ['tools']
export function apply(ctx: Context) {
ctx.tools.register(defineTool({
name: 'greet',
description: 'Greet someone by name.',
parameters: {
name: {
type: 'string',
required: true,
description: 'The name to greet',
},
},
output: {
schema: { type: 'string' },
render: (_args, value) => [{ type: 'text', text: value }],
},
async execute(args) {
return `Hello, ${args.name}!`
},
}))
}

defineTool выводит и валидирует args из parameters. execute возвращает каноническое значение, объявленное в output.schema. output.render преобразует это каноническое значение в контент для модели. После перезапуска с патчем спросите в Web UI: «Use the greet tool to greet Ada». Модель вызовет greet и получит Hello, Ada!.

Следующие шаги учебника: plugin configuration, справочник по авторству инструментов (вложенные схемы, канонические значения, фоновая работа, policy-хуки, Code Mode, UI cards) и capability layering (разделение на Service Definition → Service Provider → Consumer package).

Режимы входа CLI

Команда @deepseek-ai/dsh — это лаунчер продукта. Четыре точки входа:

Command Purpose
dsh --profile <name> Запускает указанный профиль из \$DSH_HOME/profiles/<name>
dsh --profile headless "job" Запускает одну свежую персистентную сессию, печатает финальный ответ, завершает работу
dsh web Алиас для --profile web
dsh plugin --profile <name> <pnpm args> Управляет плагинами профиля, пробрасывая вызовы в pnpm

Директория, из которой вызвана команда, становится корнем workspace по умолчанию. Профили web и headless автоматически инициализируются из поставляемых шаблонов при первом использовании. Любой другой профиль нужно создать через dsh plugin.

Флаги лаунчера идут первыми. Первый токен, который лаунчер не распознаёт, становится аргументами приложения. Пример: dsh --profile web --port 8080 передаёт --port 8080 web-приложению, а не лаунчеру.

Директория профиля хранит package.json (вне-дерревные зависимости плагинов плюс манифест профиля dsh.profile с упорядоченным списком bundles) и cordis.patch.yml (собственный патч-слой пользователя). Порядок композиции поверх пустого корня: патч каждого бандла в порядке dsh.profile.bundlescordis.patch.yml профиля → домашний \$DSH_HOME/cordis.patch.yml → оверлеи --patch. Используйте --dump-default-config и --dump-config, чтобы просмотреть скомпонованное дерево без запуска.

Плагины сообщества и экосистема

Помечайте ваш репозиторий плагина тегом dsh-plugin на GitHub для поиска. Официальный сайт ссылается прямо на эту страницу темы. Есть также Discord-сообщество DeepSeek Harness для обсуждений.

Проект использует GitHub Discussions для обратной связи и отчётов о багах. В документации есть ссылки на CONTRIBUTING.md для процесса разработки, architecture.md для дизайна системы и AGENTS.md для агентспецифичных конвенций кода.

Developer preview — да, всё будет ломаться

В README это написано ЗАГЛАВНЫМИ: «THERE WILL BE COMPATIBILITY-BREAKING CHANGES.»

Основные плагины и API ещё эволюционируют. На лендинге это сказано прямо: «DeepSeek Harness остаётся в developer preview и продолжает тестироваться разработчиками, создающими агентские harness».

Если вы строите на его основе — закрепляйте хэш коммита, делайте плагины тонкими относительно каталога конфигураций и готовьтесь перетестироваться при каждом повышении версии rc. Автоочистка плагинов и внедрение зависимостей делают перетестирование менее болезненным, чем в монолитных фреймворках, но «developer preview» значит ровно то, что написано.

В чём отличие

Большинство современных агентских фреймворков начинают с цикла ходов и прикручивают расширяемость как запоздалую мысль. Harness переворачивает это: расширяемость и есть фреймворк, а цикл ходов — просто ещё один плагин. Измеряемый результат — три вещи, которые обычно не встретишь в одном пакете:

  • Заменяй что угодно без форка. Не нравится встроенная система инструментов? Замените её. Хотите другой слой маршрутизации LLM? Поменяйте провайдер. Всё разрешается через ключи сервисов Cordis.
  • Трассируемость по умолчанию. Журнал на основе добавления — это не аддон наблюдения. Это и есть то, как работают сессии. Возобновление, ветвление, поиск и воспроизведение используют один и тот же поток.
  • Компонуемые пресеты, а не feature flags. Четыре режима (Standard / Code / Minimal / Creator) — это просто упорядоченные слои патчей из бандлов плагинов. Свои пресеты можно наслаивать сверху через YAML, а не код.

Победит ли этот подход монолитные SDK, зависит от того, появится ли в экосистеме плагинов достаточно сторонних инструментов и провайдеров, чтобы история замены и перекомпоновки стала реальностью. При 1.6k звёзд и 12k коммитов в первый день импульс явно есть.

Ссылки

Share this page