Getting Started · 01
What Is DeepSeek Harness? From Agent Runtime to ‘Everything Is a Plugin’
Separate the harness from the model and API, inspect its shipped compositions, and run a bounded evaluation before considering production use.
- Reading time
- 14 minutes
- Sources verified
Start by identifying the layer you are evaluating
DeepSeek Harness is an agent runtime, not a new language model and not a synonym for the DeepSeek API. A model turns messages into generated output. A provider endpoint accepts authenticated requests for that model. The harness owns the longer-lived engineering problem around those calls: it constructs model-visible history, records durable session events, exposes tools, applies approval and sandbox policy, persists state, and presents the result through Web, headless, SDK, or editor-facing surfaces. Keeping those responsibilities separate prevents two common evaluation errors: attributing model quality to the runtime, or assuming that API compatibility proves the surrounding agent system is safe and operationally complete.
The official architecture makes this boundary concrete. The model adapter, tool registry, session log, persistence backend, approval policy, sandbox provider, and Agent Loop are independently mounted plugins. Replacing a provider does not replace the session model; changing a permission preset does not change model weights; switching from Web to headless does not create a different reasoning engine. It changes the composition that hosts the same capability contracts. Evaluate each layer with evidence that belongs to it.
- Judge the model with task quality, latency, token behavior, and provider errors.
- Judge the harness with replayability, tool policy, composition, lifecycle, and operational failure handling.
- Judge a profile with the exact plugins and configuration rows it resolves at boot.
- Judge an integration with its workspace, credential, persistence, and deployment boundaries.
Translate ‘everything is a plugin’ into runtime consequences
Cordis provides the shared Context in which plugins contribute typed services, events, and reversible effects. A plugin can expose a Service that another plugin consumes, listen to an Event without hard-coding the producer, and register an Effect whose cleanup runs when the owning plugin unloads. This is more than packaging style. It defines how resources are owned, how hot configuration can unwind behavior, and how alternate implementations occupy the same capability seam.
There is deliberately no privileged core that extension authors patch around. The Agent Loop itself is mounted beside the model adapter and session service. A filesystem implementation is a provider for a filesystem contract. A session persistence backend provides the same event vocabulary whether the deployment chooses JSONL or SQLite. This makes composition inspectable, but it also means a feature is present only when the appropriate Definition, Provider, and Consumer are all mounted with satisfied dependencies.
Definition: ctx.sessionPersistence contract
Provider: session-persistence-jsonl or session-persistence-sqlite
Consumers: agent-loop, session-query, tool-bash, hooks
Selection: the active profile and its resolved plugin rowsTreat profiles as the product shapes you actually run
The launcher boots a named profile from the Harness home. Each profile lists an ordered stack of Bundles, keeps out-of-tree plugin dependencies, and owns a cordis.patch.yml. A Bundle distributes Cordis configuration rows and their mounting code. The base Bundle supplies shared model adapters, tools, persistence, sandbox and approval policy, settings, credentials, and telemetry. The Web application Bundle adds browser-facing host and client behavior. The headless Bundle adds a one-shot runner and intentionally has no server.
Layers apply to an empty row list in a defined order: profile Bundles first, then the profile patch, then the home patch, then any command-line --patch overlay. A patch targets a row by id and replaces its entire config or inserts a row. It is not an object deep merge. That rule matters during evaluation because a small-looking patch can accidentally remove an expression or sibling field that the shipped row relied on.
dsh --profile web --dump-default-config > web-default.yml
dsh --profile web --dump-config > web-resolved.yml
diff -u web-default.yml web-resolved.ymlA successful command prints configuration without booting the application. The diff is your first trustworthy answer to ‘what am I running?’ Review changed rows before you provide credentials or point the profile at a valuable workspace.
Compare Web and headless before choosing an entry point
Web and headless are not merely two skins. The Web runner serves a browser application, uses the invoking directory as the default filesystem location, and requires the user to add and select a workspace before the session composer becomes available. The installed production runner serves http://127.0.0.1:3080 by default. The CLI does not currently accept --host 0.0.0.0; that value is rejected as a usage error. Named authorities can be added with --trusted-host for the browser trust fence.
Headless accepts one job, creates a fresh persisted session, prints the final answer, and exits. It has no browser server and no opportunity to open an unexpected approval dialog. That makes it attractive for automation, but it also makes deterministic permissions, exit handling, and idempotent external effects more important. Both modes use the invoking directory as the default workspace root and load applicable repository instructions within the documented render budget.
dsh --profile web --dump-config > /tmp/web.yml
dsh --profile headless --dump-config > /tmp/headless.yml
diff -u /tmp/web.yml /tmp/headless.yml- Choose Web when a person needs to select models, workspaces, permissions, and inspect conversation state.
- Choose headless when one bounded job must produce output and a meaningful exit status.
- Choose the Python SDK when a program must own runtime lifecycle and consume a structured RunResult.
- Choose none of them for a production path until its permission, persistence, credential, and shutdown behavior has been exercised.
Run a bounded Web evaluation with observable success criteria
Start in a disposable checkout that contains no customer data, production credentials, or unrelated repositories. Launch from that directory so its path becomes the default filesystem location. The command prints the URL; for the shipped installed Web runner the default is the loopback address on port 3080. Open Settings → Models, enter a provider credential, and save it. Keys are write-only in the UI: the browser receives a redacted descriptor, while the local credential provider stores the value in $DSH_HOME/.credentials.yaml and settings retain only a reference.
mkdir -p /tmp/dsh-evaluation
cd /tmp/dsh-evaluation
printf '# Evaluation workspace\n' > README.md
npx @deepseek-ai/dsh webAdd and select /tmp/dsh-evaluation as the workspace. Begin with a read-only prompt whose claims can be checked directly. Success is not merely a fluent answer: the response must name the real README.md, the tool trajectory must show reads rather than writes, and the session must remain available after a browser refresh.
Inspect this workspace without modifying it.
Report the top-level files, quote the first Markdown heading,
and state which evidence supports each claim.Use the session log as evidence, not the final message alone
The append-only SessionEvent log is the source of the context the model sees. Durable facts such as user messages, assistant chunks, turns, steps, and tool events survive reload and are broadcast through session/event. Live agent events coordinate queueing, request construction, steering, and status, but they are not a replacement for replayable transcript facts. The architecture summarizes the invariant as ‘model-visible means logged’: anything entering a model request must be reconstructable from the session stream.
For an evaluation, examine at least three things. First, confirm that the user request and model response appear after reload. Second, inspect tool calls and results to ensure the runtime did not perform an action the prose answer concealed. Third, stop and resume a representative session before trusting persistence. Do not edit JSONL rows to make a failed session appear healthy; copy the log for diagnostics and preserve event order.
cp /path/to/session.jsonl /tmp/session.inspect.jsonl
wc -l /tmp/session.inspect.jsonl
head -n 5 /tmp/session.inspect.jsonlSuccess means replay reconstructs the same visible conversation, tool evidence remains ordered, and no secret literal appears in the copied diagnostic artifact. A preview upgrade should be tested against backed-up representative sessions because event shape compatibility across arbitrary revisions is not promised.
Separate permission choice from filesystem confinement
The shipped permission presets bundle two knobs: sandbox mode and approval policy. workspace-write combines workspace-write confinement with ask. danger-full-access combines unrestricted file modification with never asking. New sessions default to workspace-write. A Settings change affects later Web sessions; an already-open session retains the permission facts pinned into its log. That session-local behavior prevents an administrator's new default from silently changing an ongoing conversation.
The sandbox policy resolves one mode and one canonical workspace root per call. For an ordinary agent session, the immutable SessionHeader.cwd supplies that root. workspace-write permits modifications under the session workspace and platform temporary roots, while reads, network access, and process visibility are not universally confined by that label. Approval answers whether an action may proceed; sandboxing constrains what the executing backend can modify. Neither substitutes for limiting credentials or tools.
Evaluation case A
Preset: workspace-write
Request: create ./notes.txt
Expected: write can remain inside the selected workspace
Evaluation case B
Preset: workspace-write
Request: overwrite a file outside the workspace
Expected: denial or approval path; no outside mutationDiagnose common failure branches in the correct order
When the Web composer is disabled, verify that a workspace is selected and a configured model is available. MISSING_CREDENTIAL means the provider route exists but cannot resolve the referenced secret. UNKNOWN_MODEL means the selected model is not available in the configured route. A 401 during custom-provider model discovery points to credential rejection. A browser trust error belongs to host or trusted-authority configuration, not the model.
When profile boot fails, inspect configuration before changing prompts. Invalid launcher flags, configuration errors, and boot failures exit nonzero. From a source checkout, production Web operation needs built package and frontend artifacts; stale existing bundles can run older browser code because the launcher does not check freshness. Rebuild after checkout changes. If a patch caused the failure, compare default and resolved dumps and inspect the last overlay targeting the broken row.
dsh --help
dsh --profile web --dump-config > resolved.yml
grep -E "llm|credentials|workspace|permission|sandbox" resolved.yml- Network or provider failure: preserve the provider error code and request id, but redact credentials.
- Workspace failure: confirm the selected canonical directory and session cwd.
- Permission failure: inspect the session's pinned preset rather than only the current global default.
- Composition failure: identify the missing or replaced provider row and restore the full config shape.
Define a production-readiness gate rather than a demo milestone
A successful demo proves that one profile started and one task completed. Production readiness requires a stronger matrix. Pin the package or commit you evaluated; preserve resolved configuration; document credential rotation; test representative session recovery; verify graceful shutdown; and record which tools, network paths, subprocesses, writable roots, and telemetry modes are active. The CLI gives the plugin tree up to five seconds to dispose. SIGTERM is the normal supervisor stop and exits zero; SIGINT reports 130; a second signal forces immediate exit. Exercise those paths under the supervisor you intend to deploy.
Telemetry is local by default. Explicit FULL mode can export every projected session event, while FEEDBACK_ONLY uploads a suffix after feedback. The shipped base has no telemetry redaction rule, so enabled exports can contain message text, tool arguments, results, and workspace paths. Treat telemetry configuration as a data-governance decision, not a harmless observability switch.
Release gate
1. Pin runtime and profile dependencies.
2. Archive default and resolved config dumps.
3. Test read, write, denial, cancellation, resume, and provider failure.
4. Send SIGTERM during an active task and verify bounded disposal.
5. Review session and telemetry artifacts for sensitive content.
6. Roll back by restoring the prior profile and package version.DeepSeek Harness remains a developer preview with expected compatibility-breaking changes. A responsible adoption decision therefore includes ownership for upgrades and rollback. If the organization cannot assign that owner, keep the harness in an evaluation environment even when its architecture is compelling.
Official sources
- Architecture ↗Supports: Cordis plugin model, Profiles and Bundle precedence, SessionEvent durability, Model-visible logging invariant
- Web UI guide ↗Supports: Model setup, Workspace selection, First-task workflow
- CLI behavior reference ↗Supports: 127.0.0.1:3080 default, host restrictions, workspace cwd, credential precedence, shutdown and telemetry behavior
- Model provider guide ↗Supports: Write-only credentials, session model stickiness, provider failure branches
- Permission presets ↗Supports: workspace-write and danger-full-access bundles, per-session pinned selection
- Sandbox policy ↗Supports: Per-call mode and workspace root, workspace-write boundaries

