Skip to specification

DeepSeek Harness — the harness with no core

A model lab shipped its own harness and made one claim about it: everything is a plugin. Not the tools — everything. The model adapter, the tool registry, the session log, the sandbox, and the agent loop itself are all rows in a config tree, and every row can be replaced from a file. The three sheets before this one describe harnesses with a centre. This one argues there does not have to be a centre at all.

Identification

Steward
DeepSeek AI
Opened
13 August 2026 · developer preview
Licence
MIT
Runtime
TypeScript on Node · pnpm workspace
Composition
219 packages across 49 families
Surfaces
web UI at 127.0.0.1:3080 · headless runner

LineageThe interesting ancestry is not DeepSeek's. The plugin framework underneath, Cordis, is a third-party project by the cordiverse group — described as a meta-framework of spatiotemporal composability, with its own paper and its own unstable API — and it is vendored into this repository rather than depended on. So the architectural argument on this sheet was not invented for an agent harness; an agent harness was fitted to it. That is why the vocabulary reads oddly for the field: contexts, services, effects and waterfalls, not sessions and callbacks.

Read it as

A ship of Theseus, built that way on purpose

Every plank is replaceable, including the keel, and the vessel is still the vessel. What stays constant is not any part — it is the sockets the parts plug into, and the order in which they are fitted.

The drawing, in one paragraph

One sentence in the architecture document generates the rest of this sheet: there is no privileged core to patch. A running dsh is a plugin tree composed at boot from ordered layers — a base bundle, then whatever bundles the profile stacks, then the profile's patch file, then the machine's, then anything passed for this run alone — applied to an empty entry list. Each layer targets a row by id and replaces its whole config, or inserts a new one. Plugins claim a stable key on a shared context (ctx.tools, ctx.llm, ctx.sessions), declare what they need by key rather than by import, and install everything they do — prompt sections, tool schemas, adapters, listeners — as reversible effects that unwind when the plugin unloads. The consequence is that the eleven slots below are not answered by features. They are answered by seams: a service definition declaring an interface, a provider implementing it, a consumer using it, and no consumer ever naming a provider.

composed on the left · the context in the middle · what it exposes on the right

FIG. 4 — the harness with no core. On the left, the three ways the tree gets composed: two of them at boot by a person, one of them mid-run by the agent. In the middle, the context those layers compose. On the right, what it exposes — and every box there is a row that could have been something else, including the model adapter and the loop itself.
PROVIDERSERVICE DEFINITIONCONSUMERfs-localthe host diskfs-sandboxfenced by sandbox modefs-e2ba remote Linux boxregistersctx.fsthe interface, andnothing but the interfacefound by keytool-fsread · write · editimports no implementationONE SWAP, ONE WORLDfs-localfs-e2bsubprocess-localsubprocess-e2bcarriesBashtool-bashPTYtool-terminalLSPtool-lspTwo rows change in a config file. The shell, the terminal and thelanguage servers move with them — no consumer is forked.
FIG. 5 — the anatomy of a seam, and why one swap moves a whole world. A definition declares the interface, providers implement it, consumers use it, and no consumer ever names a provider. Because the filesystem and subprocess seams share one execution world, repointing both at a remote sandbox carries the shell, the terminal and the language servers along with them.
APPLIED IN ORDER — LAST LAYER WINS01dsh-basebundle · models, tools, persistence, sandbox, policy02dsh-web-appbundle · the browser application03profile cordis.patch.ymlthe named composition's own overrides04home cordis.patch.ymlthis machine, every profile05--patch overlaythis run onlyan empty entry list — there is no core underneathbootsTHE TREE THAT BOOTSllm-deepseek01 basesandbox-local01 baseweb-app02 webfs-local04 hometool-cordis05 --patch$ dsh --profile web --dump-configevery row it prints can be replaced by a patch of your ownA patch targets a row by id and replaces its whole config, or inserts a new one.The model adapter, the tool registry, the session log and the agent loop are all rows.
FIG. 6 — composition as sediment. Layers are applied in order to an empty entry list, and each one may replace a row below it by id or insert a new one. The tree on the right is what actually boots, with every row attributed to the layer that won it — which is why the harness ships a command to print it.

The examination — eleven slots, one harness

Built in
Ships in the core; works with no configuration.
Via config or extension
The slot is real but you fill it — config, extension, or convention.
Deliberately omitted
Left out on purpose, with a stated argument for the gap.
  1. There is no prompt file at the centre. ctx.systemPrompt is a registry: plugins contribute prompt sections and tool schemas, and the assembly runs fresh at every step, so what the model is told is a function of which plugins are mounted. A preset can compose a different capability set — and therefore a different prompt — for one session without touching the deployment.

    Built in

    ctx.systemPrompt · sections per plugin · presets

  2. Filesystem, web and language-server access each arrive through their own seam, so search can be Exa, Perplexity or DeepSeek's own behind one unchanged tool. The unusual channel is lateral: a resolver projects a bounded snapshot of another session into this one as durable, explicitly untrusted context. Injected material does not interrupt — it waits in the inbox until a real message wakes the loop.

    Built in

    ctx.fs · ctx.web · ctx.lsp · agent.inject()

  3. Pressure is measured, not guessed: a token meter keeps isolated per-session replay folds and publishes immutable revisioned measurements that compaction consumes after each step. Two mechanisms run before summarisation — a pruner that rewrites oversized current tool results as replayable surface replacements, and a spill store that moves oversized tool text out and hands the model a locator plus a retrieval hint. Notably, there is no compact tool the model can call; the harness decides.

    Built in

    token meter · pruner · spill · no compact tool

  4. Every call runs a fixed pipeline — a pre-execute waterfall, monotonic guards, around-dispatch, a post-execute waterfall, then final content invariants — and registering on ctx.tools is what puts a schema into prompt assembly. Code Mode is the variant worth noting: rather than one call per step, the model writes a program that the code runtime executes against host bindings, and its sub-calls are logged individually so the transcript stays honest.

    Built in

    guarded pipeline · Code Mode · MCP client

  5. Consumers hand the sandbox the exact argv they are about to spawn; the backend wraps it under a per-call policy and reports what it enforced. One detail carries the design: the default mode and workspace root live in a single policy service that both the shell executor and the filesystem provider read, deliberately, so bash and fs cannot end up confined to different roots. Approval is a waterfall that fails closed when nobody is listening.

    Built in

    argv handover · one policy home · fails closed

  6. The session log is an append-only event stream, and model history is projected from it rather than stored beside it. The rule is enforced rather than documented: anything that reaches a model request must be reconstructable from the log, and a runtime invariant asserts it — which is why adding a new model-visible input means adding a new session event. Backends are swappable (JSONL or SQLite), and a cache of folded projections means listing sessions never replays full logs.

    Built in

    append-only log · model-visible means logged

  7. A step is one model request plus its tool calls; a turn opens when input is claimed and closes when nothing is owed. The extension points are typed events with declared dispatch modes, and the one that matters is agent/pre-step — a waterfall that can rewrite what the model is about to see or reject it outright. A rejected first claim still closes a durable turn that spent no step, so the log records the attempt rather than hiding it.

    Built in

    turn / step · agent/pre-step waterfall · one inbox

  8. Delegation is a seam with six providers behind it, and three of them leave the process entirely — ACP, Codex, and Claude Code. A dsh run can hand a turn to a competing harness and treat the result as an ordinary subagent return. The service also owns continuation, so a delegation can be followed up rather than only awaited.

    Built in

    6 providers · incl. Codex and Claude Code

  9. Skills are a seam too: providers publish catalogues, the service merges them, and the model-facing tool renders a short catalogue into the session prefix and loads a full body only when asked. The same accommodating instinct shows up beside it — dedicated packages read Claude Code's and Codex's hook formats, so know-how already written for another harness runs here without translation.

    Built in

    ctx.skills · catalogue then body · rival hook formats

  10. Telemetry is a seam ending in OpenTelemetry, and the log itself is the trace. Two choices stand out. The language-server seam offers exactly four normalised operations and no protocol escape hatch, which forces backends to translate rather than leak. And invariants are a first-class service: packages register their own runtime checks, and a failure is attributed to the package that owns it — the harness reports which part broke its own contract.

    Built in

    OTel · 4-operation LSP · attributed invariants

  11. The machinery for self-modification is further along than anywhere else on this register: because registrations are reversible effects, plugins mount and unmount live, and a model-facing tool lets the agent define a new Cordis package — syntax-checked, shown to the user as a card with a start control — then run it in a sandbox inside the running process. But those packages live only in process memory and disappear on restart. The harness can rewrite itself for an afternoon; making the change last is still a human writing a patch row.

    Via config or extension

    cordis_define / cordis_run · in-memory only

Where this design runs out of road

If every plank is replaceable, the name stops picking out an object. Two dsh installations can share no row and both be DeepSeek Harness, which makes every question a reader might ask — what is in the prompt, where does bash run, what happens after a tool call — unanswerable without inspecting that machine's tree. The project knows it: --dump-config exists precisely because you cannot otherwise know what you are running. And the composition is not small, at 219 packages across 49 families, so the plugin surface is itself the learning curve. The sharpest version of the trade appears in DeepSeek's own evaluation note. The published agent scores were produced with a minimal mode of this harness marked to be released — so at the moment the numbers were set, the configuration that produced them was not one you could check out. A harness that can be composed any way is a harness whose results travel only with their config.

06Side by sideThe comparison table — one row per primitive, one column per harness

Read from — every finding traces to one of these

UnitT04
Fills10 built in · 1 adapted · 0 omitted
Read againstThe Harness — eleven primitives