DeepSeek Harness: Ein Open-Source-Agent-Framework, wo buchstäblich alles ein Plugin ist
Ein vollständiger Agent-Stack, auf GitHub veröffentlicht
DeepSeek hat am 13. August 2026 eine Entwickler-Vorschau von DeepSeek Harness (dsh) veröffentlicht. Das Repository liegt unter deepseek-ai/deepseek-harness. Zum Tagesende hatte es 1,6k Stars, 12.293 Commits und 19 Mitwirkende — Zahlen, die zeigen: Das ist kein Wochenendprojekt. Die Codebasis besteht zu 97,1 % aus TypeScript, mit 1,6 % CSS und 0,7 % Python. Paketversion zum Veröffentlichungszeitpunkt: 0.1.0-rc.5.
Die Landing-Page findet sich auf deepseek.com/harness und die Entwicklerdokumentation auf deepseek-harness.github.io/deepseek-harness.
Lizenziert unter MIT.
Der Ein-Satz-Pitch
Aus dem README: “Agent = Model + Harness.”
Das Modell ist die Seele. Ein Harness lässt einen Agenten seine Umgebung verstehen, Tools verwenden und in realen Settings weiterarbeiten. DeepSeeks Ansatz: Jede Fähigkeit — Modelle, Tools, Skills, Sitzungen, Sandboxes, Storage, Loops, Scheduling und die UI — ist ein austauschbares Plugin.
Das ist kein Slogan. Die Architektur erzwingt es.
Cordis: Der Kernel unter allem
DeepSeek Harness baut auf Cordis auf, einem mitgelieferten Plugin-Framework. Das Design von Cordis wird in einem Paper mit dem Titel A Programming Paradigm for Spatiotemporal Composability beschrieben.
Das gesamte Framework reduziert sich auf fünf Ideen:
- Ein Plugin ist ein Objekt, das Service implementiert. Es kann eine Funktion mit
injectundapply(ctx)sein, oder eine Unterklasse vonService. - Ein Kontext ist ein Repository von Services. Ein Plugin beansprucht einen stabilen Key wie
ctx.tools,ctx.llmoderctx.sessions. Andere Plugins finden Services per Key, statt konkrete Implementierungen zu importieren. - Service-Abhängigkeit per
injectdeklarieren. Ein Plugin, das erforderliche Services benennt, wartet, bis diese Services existieren. Keine manuelle Boot-Reihenfolge. - Getypte Events für Kommunikation. Vier Dispatch-Modi:
emit(abschicken und vergessen),waterfall(Middleware-artig mitnext()),parallel(alle Listener laufen gleichzeitig) undserial(Listener laufen nacheinander mit Rückgabewerten). - Registrierungen sind reversible Effekte. Prompt-Abschnitte, Tool-Schemas, Adapter, Listener — alles wird über
ctx.effect()installiert, sodass Reload und Teardown es vorhersagbar rückgängig machen.
Das Cordis-Waterfall-Modell ist ein umschließendes Middleware. Ein Listener erhält (...args, next). next() aufrufen, um an den nächsten Service zu delegieren; ohne next() zurückkehren, um kurzzuschließen. Bei Single-Decision-Events ist der Kurzschluss Teil des Designs — ein Policy-Listener kann eine Entscheidung vollständig besitzen.
Alles ist ein Plugin (im Ernst)
Die Plugin-Liste auf deepseek.com/harness buchstabiert die gesamte Fähigkeitsoberfläche heraus:
- Models — Die LLM-Backends (DeepSeek, OpenAI, Anthropic, Bedrock, Vertex, Azure, Codex, plus jeder OpenAI-kompatible Endpunkt)
- Tools — Was das Modell aufrufen kann
- Skills — Wiederverwendbare Prompt- und Tool-Pakete
- Sessions — Konversationszustandsverwaltung
- Sandboxes — Wo Code läuft (PTY bash,
danger-full-accesslokales Backend, landlock-basierte native Sandbox) - Storage — Sitzungspersistenz
- Loops — Die Agent-Turn-Logik
- Scheduling — Subagent- und Task-Verteiler
- UI — Die Web-UI, standardmäßig auf Port 3080 erreichbar
Entwickler können jedes dieser Elemente per Konfiguration auswählen, austauschen oder erweitern — ohne Quelländerungen an DeepSeek Harness selbst. Der Plugin Config Catalog wird automatisch aus dem Quellcode (scripts/gen-config-catalog.ts) generiert und von CI frisch verifiziert, sodass jedes Feld in einem cordis.yml-config:-Block exakt zum deklarierten Config-Typ eines Plugins passt.
Vier Laufzeitmodi
Die Docs enthalten vier Presets. Jedes zielt auf einen anderen Anwendungsfall ab.
Standard Mode — Vollständiger Coding-Agent: Dateibearbeitung, Shell, Datei- und Websuche, Skills, Planung, Ziele, Subagents und Workflows. Das ist die standardmäßige Web-UI-Erfahrung.
Code Mode — Alles aus Standard, aber Tools werden über ein Code-Mode-SDK freigegeben, sodass das Modell mehrschrittige Operationen in einem einzigen TypeScript-Programm kombinieren kann. Ein einziges modellgeneriertes Programm ersetzt mehrere Tool-Call-Runden.
Minimal Mode — Nur zwei Tools: Eine persistente bash-Shell und str_replace_editor. Das dient zum Benchmarken von Modellen in einer abgespeckten Umgebung. Keine Skills, keine Planung, keine Subagents — rohe Modellfähigkeit gegen eine echte Codebase.
Creator Mode — Gebaut zum Schreiben eigener Agent-Presets. Enthält alle Standard-Mode-Fähigkeiten plus Runtime-Inspektion, In-Memory-Cordis-Plugin-Experimente und Preset-Autorierungs-Hilfen. So baut man den fünften, sechsten, siebten Modus.
Jeder Lauf ist nachverfolgbar
Hier unterscheidet sich Harness vom meisten Agent-Tooling. Alles, was das Modell sieht, wird in einem nur-erweiternden Sitzungsprotokoll aufgezeichnet:
- System-Prompts
- Reasoning-Output
- Tool-Calls und deren Ergebnisse
- Subagent-Scheduling-Entscheidungen
- Jede Kontextinjektion
Die Web-UI hat eine Trajectory-Ansicht, wo man diese Einträge gefiltert nach Quelle inspiziert. Fortsetzen, abzweigen, suchen und wiedergeben — alle vier Operationen arbeiten gegen denselben Event-Stream. Keine separate Trace-Datenbank, kein Export-Schritt. Das Sitzungs-JSONL ist die Quelle der Wahrheit.
Beim Python-SDK speichert das Sitzungsverzeichnis unkomprimiertes JSONL mit den zusammengesetzten Modellanfragen und Tool-Calls. Das Beispiel in examples/jsonrpc-agent/minimal.py zeigt das von Anfang bis Ende.
Modellkonfiguration: DeepSeek + alles Mögliche
Die Modellkonfigurationsseite (Modelle konfigurieren) hat drei Ebenen.
DeepSeek Official. Settings → Models öffnen, DeepSeek-API-Key einfügen, speichern. Der Key ist schreibgeschützt. Nach dem Speichern erhält die UI einen geschwärzten Deskriptor, nie den Klartext. Keys liegen in \$DSH_HOME/.credentials.yaml; die Settings-Seite behält nur einen Credential-Referenz.
Catalog-Provider. Auf “Add provider” klicken, Anthropic oder OpenAI auswählen, Key einfügen. Provider mit nativer Authentifizierung (Bedrock über AWS-Creds + Region, Vertex über ADC-Projekt, Azure über api-version, Codex über OAuth) funktionieren nicht mit nur einem API-Key-Feld — jeder braucht seinen eigenen Auth-Pfad.
Custom Provider. Für ein Unternehmens-Gateway, selbst gehosteten Server oder jeden nicht im Katalog enthaltenen Provider. Eine kleingeschriebene Provider-ID festlegen (permanent — Anfragen, gespeicherte Sitzungen, Modelldefaults und Credential-Refs nutzen sie alle), Basis-URL, API-Protokoll, Credentials und mindestens ein Modell.
Visuelle Modelle brauchen einen extra Schritt. Da ein Custom-Endpunkt keine Möglichkeit hat, seine unterstützten Modalitäten bekanntzugeben, kann das Formular Vision-Unterstützung nicht automatisch erkennen. Man fügt input: [text, image] zum Modell in \$DSH_HOME/settings.yaml hinzu. Wenn alle Custom-Modelle Bilder akzeptieren, setzt man defaultInput: [text, image] einmal auf Provider-Ebene statt pro Modell. Das input-Feld ist eine Behauptung, keine Prüfung — wenn man behauptet, ein Modell könne Vision, der Endpunkt es aber nicht kann, lehnt der Provider die Anfrage ab, nicht Harness.
Fehlerbehebung steht direkt in den Docs:
MISSING_CREDENTIAL→ Provider-Key über die Models-Seite speichern oder die referenzierte Umgebungsvariable exportierenUNKNOWN_MODEL→ Ein konfiguriertes Modell wählen oder das fehlende Modell zum Custom-Provider hinzufügen- “Get available models returns 401” → Key prüfen. Modell-Discovery ruft den OpenAI-kompatiblen
GET /models-Endpunkt auf. Wenn Ihr Dienst das nicht exponiert, Modelle manuell eingeben. - “Image rejected before send” → Das Modell hat die Modalität
imagenicht deklariert.input: [text, image]hinzufügen. - “Provider rejects a request with an image” → Das Modell behauptete Vision-Fähigkeit, die sein Endpunkt nicht hat.
imageaus der Liste entfernen und eine frische Sitzung starten (das alte Bild bleibt im Sitzungsprotokoll und wiederholt dieselbe Anfrage immer wieder).
Erste Schritte: Drei Pfade
Pfad 1: npx @deepseek-ai/dsh web
Node.js installieren, einen Befehl ausführen. Die Web-UI startet auf http://127.0.0.1:3080. Das war’s. Kein Clone, kein Build, kein pnpm.
npx @deepseek-ai/dsh webDann: Settings → Models → DeepSeek-API-Key einfügen. Workspace wählen (das Verzeichnis, wo dsh aufgerufen wurde, reicht). Sitzung starten:
Dieses Repository zusammenfassen und seine Hauptpakete identifizieren.
Der Agent liest und bearbeitet Workspace-Dateien, führt Befehle aus, delegiert Arbeit und unterhält einen Plan. Jede Operation, die unter der aktiven Berechtigungsrichtlinie Genehmigung braucht, öffnet vor der Ausführung einen Dialog in der Web-UI.
Pfad 2: Klonen und aus Quelle bauen
git clone https://github.com/deepseek-ai/deepseek-harness.gitcd deepseek-harnesspnpm installpnpm run buildpnpm dsh webPfad 3: Python-SDK
Voraussetzungen: Python 3.10+, Linux x64 / Linux arm64 / macOS 14+ auf arm64, ein DeepSeek-kompatibler Endpunkt.
git clone https://github.com/deepseek-ai/deepseek-harness.gitcd deepseek-harnesspython -m venv .venv. .venv/bin/activatepython -m pip install deepseek-harness-sdkCredentials setzen:
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.'Eine Aufgabe gegen einen isolierten Workspace ausführen:
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."Für eigenen Code ist der SDK-Einstiegspunkt DeepSeekHarness als Context-Manager:
from pathlib import Pathfrom 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 startet das mitgelieferte Runtime lazy und nutzt es wieder, bis der with-Block endet. Dieselbe Session-ID wiederverwenden, um den Bash-Prozess (Arbeitsverzeichnis, Umgebungsvariablen, Shell-Funktionen) zu erhalten. Eine frische Session-ID für eine unabhängige Aufgabe verwenden.
Die minimale jsonrpc-agent-Komposition ist bewusst knapp: nur persistentes bash und str_replace_editor als modellseitige Tools. Bash-Timeout 300 Sekunden. Editor-Output-Limit 16.000 Zeichen. Kontextkompaktion deaktiviert. Das Dateisystem nutzt das blanke lokale Backend — Editor-Pfade können alles adressieren, was der Runtime-Prozess sehen kann. Die Docs warnen explizit: “Nur innerhalb eines wegwerfbaren Checkouts oder Containers ausführen.” Das persistente PTY-Backend erfordert zudem ein POSIX-Terminal-Substrat — keine Windows-Unterstützung für diese Komposition.
Das erste Plugin schreiben
Tutorial: Das erste Plugin. Ein Plugin ist ein TypeScript-Modul, das eine apply-Funktion exportiert:
import type { Context } from '@deepseek-ai/cordis'
export const name = 'hello-plugin'
export function apply(ctx: Context) { console.log('[hello-plugin] plugin loaded!')}In einem cordis.yml-Patch registrieren:
- insert: - id: hello name: '/absolute/path/to/deepseek-harness/scratch-plugin/src/my-plugin.ts'Mit dem Overlay booten:
pnpm dsh web --patch ./scratch-plugin/cordis.ymlAutomatisches Cleanup ist die Killer-Funktion. Alles, was über ctx registriert wird — Event-Listener, Tools, Timer — wird beim Entladen des Plugins aufgeräumt. Kein manuelles removeListener oder clearInterval. Für explizites Cleanup (Netzwerkverbindungen) einen Disposer aus ctx.effect() zurückgeben.
Abhängigkeiten werden mit inject deklariert:
export const name = 'my-tool-plugin'export const inject = ['tools']
export function apply(ctx: Context) { // ctx.tools ist hier bereit}Cordis wartet auf jeden erforderlichen Service, bevor das Plugin geladen wird.
Es gibt drei Plugin-Formen: Funktion (oben), Objekt mit apply und Klasse, die Service erweitert. Die Klassenform nutzen, wenn das Plugin selbst einen Service bereitstellt, den andere Plugins konsumieren.
Das erste Tool schreiben
Tutorial: Ein Tool bauen. defineTool aus @deepseek-ai/dsh-tools nutzen:
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 leitet args aus parameters ab und validiert sie. execute gibt den kanonischen Wert zurück, der von output.schema deklariert wird. output.render wandelt diesen kanonischen Wert in modellseitigen Inhalt um. Nach einem Neustart mit dem Patch in der Web-UI fragen: “Use the greet tool to greet Ada.” Das Modell ruft greet auf und erhält Hello, Ada!.
Die nächsten Schritte aus dem Tutorial sind Plugin-Konfiguration, die Tool-Autorierungs-Referenz (verschachtelte Schemas, kanonische Werte, Hintergrundarbeit, Policy-Hooks, Code Mode, UI-Karten) und Capability-Layering (Service-Definition → Service-Provider → Consumer-Paket-Aufteilung).
CLI-Eintrittsmodi
Der Befehl @deepseek-ai/dsh ist der Produkt-Launcher. Vier Einstiegspunkte:
| Befehl | Zweck |
|---|---|
dsh --profile <name> |
Das benannte Profil unter \$DSH_HOME/profiles/<name> booten |
dsh --profile headless "job" |
Eine frische persistente Sitzung ausführen, die finale Antwort ausgeben, beenden |
dsh web |
Alias von --profile web |
dsh plugin --profile <name> <pnpm args> |
Plugins eines Profils verwalten, indem an pnpm weitergereicht wird |
Das Aufrufverzeichnis ist die standardmäßige Workspace-Root. Die Profile web und headless initialisieren sich bei erster Nutzung automatisch aus mitgelieferten Templates. Jedes andere Profil muss über dsh plugin erstellt werden.
Launcher-Flags kommen zuerst. Das erste Token, das der Launcher nicht erkennt, wird zu den App-Argumenten. Beispiel: dsh --profile web --port 8080 reicht --port 8080 an die Web-App weiter, nicht an den Launcher.
Ein Profilverzeichnis enthält eine package.json (außerhalb des Baums liegende Plugin-Abhängigkeiten plus das Profil-Manifest dsh.profile mit seiner geordneten bundles-Liste) und ein cordis.patch.yml (die eigene Patch-Ebene des Benutzers). Kompositionsreihenfolge über eine leere Root ist: Jeder Bundle-Patch in dsh.profile.bundles-Reihenfolge → das cordis.patch.yml des Profils → das \$DSH_HOME/cordis.patch.yml auf Home-Ebene → --patch-Overlays. Mit --dump-default-config und --dump-config den zusammengesetzten Baum inspizieren, ohne ihn zu booten.
Community-Plugins und Ökosystem
Das Plugin-Repository auf GitHub mit dsh-plugin taggen, damit es auffindbar ist. Die offizielle Seite verlinkt direkt auf diese Topic-Seite. Es gibt zudem eine DeepSeek Harness Discord-Community zur Diskussion.
Das Projekt nutzt GitHub Discussions für Feedback und Bugmeldungen. Die Docs verlinken auf CONTRIBUTING.md für den Entwicklungsworkflow, architecture.md für Systemdesign und AGENTS.md für agentspezifische Codierkonventionen.
Entwickler-Vorschau — Ja, es wird brechen
Das README setzt das in GROSSBUCHSTABEN: “ES WIRD KOMPATIBILITÄTSBRECHENDE ÄNDERUNGEN GEBEN.”
Core-Plugins und APIs entwickeln sich noch. Die Landing-Page sagt es direkt: “DeepSeek Harness bleibt in der Entwickler-Vorschau und wird weiterhin von Entwicklern getestet, die Agent-Harnesses bauen.”
Wenn du darauf aufbaust: Einen Commit-Hash pinnen, deine Plugins gegenüber dem Config-Katalog schlank halten und damit rechnen, bei jedem rc-Bump erneut zu testen. Plugin-Auto-Cleanup und Dependency-Injection machen erneutes Testen weniger schmerzlich als bei monolithischen Frameworks, aber “Entwickler-Vorschau” bedeutet genau das, was es sagt.
Was das anders macht
Die meisten Agent-Frameworks heute fangen mit einer Turn-Loop an und bauen Extensibility als Nachgedachtes dazu. Harness dreht das um: Die Extensibility ist das Framework, und die Turn-Loop ist nur ein weiteres Plugin. Das beobachtbare Ergebnis sind drei Dinge, die man normalerweise nicht in einem Paket bekommt:
- Alles ohne Fork tauschen. Das eingebaute Tool-System gefällt nicht? Ersetzen. Eine andere LLM-Routing-Schicht gewünscht? Provider tauschen. Alles löst sich über Cordis-Service-Keys auf.
- Nachverfolgbarkeit standardmäßig. Das nur-erweiternde Protokoll ist kein Observability-Add-On. Es ist die Funktionsweise von Sitzungen. Fortsetzen, abzweigen, suchen und wiedergeben nutzen alle denselben Stream.
- Komponierbare Presets, keine Feature-Flags. Die vier Modi (Standard / Code / Minimal / Creator) sind nur geordnete Plugin-Bundle-Patch-Ebenen. Du kannst deine eigenen Presets mit YAML statt Code darüberlegen.
Ob dieser Ansatz gegen monolithische SDKs gewinnt, hängt davon ab, ob das Plugin-Ökosystem genug Drittanbieter-Tools und -Provider produziert, um die Tauschen/Rekomponieren-Geschichte zur Realität werden zu lassen. Mit 1,6k Stars und 12k Commits am ersten Tag ist die Dynamik eindeutig da.
Referenzen
- DeepSeek Harness Landing-Page
- deepseek-ai/deepseek-harness auf GitHub
- Entwicklerdocs Quickstart
- Modellkonfigurationsanleitung
- Python-SDK-Anleitung
- Tutorial Das erste Plugin
- Tutorial Ein Tool bauen
- Cordis Primer
- Plugin Config Catalog
- CLI-README
- Cordis auf GitHub
- Cordis-Paper: A Programming Paradigm for Spatiotemporal Composability
- Community dsh-plugin Topic auf GitHub
- DeepSeek Harness Discord