DeepSeek's agent harness makes everything a plugin, even the approval policy
· the plori team
TL;DR. DeepSeek's open-source agent harness, dsh, treats every part of the product as a replaceable plugin. Two of its ideas are worth copying: a session log that is the only source of model-visible context, enforced by a runtime invariant, and a tool pipeline whose policy guards can only deny, never widen. The cost is real too. You have to learn a bespoke plugin framework before you can read the code, and the same patch system that swaps a model adapter can swap out the sandbox and approval policy. This is an early read of a developer preview, based on the project's documentation as of August 13, 2026.
A disclosure before anything else: we build a competing agent harness, the runtime behind plori. We read dsh the way you read a rival's blueprints, looking for ideas to take and mistakes to avoid. Three of its ideas went straight onto our backlog. That should tell you how seriously to take the praise below, and the criticism.
What is the DeepSeek harness?
dsh is an MIT-licensed agent framework from DeepSeek. You run it yourself: as a local web app with a browser UI on 127.0.0.1, or as a one-shot headless runner. As of August 13, 2026 the repository shows about 10,300 stars and more than 12,000 commits, and the README labels it a developer preview with breaking changes expected.
The architecture sits on Cordis, a plugin framework in which, per the project's own docs, "plugins contribute services, typed events, and reversible effects to a shared context." Model adapters, the tool registry, the session log, and the agent loop itself are all plugins. The docs state the consequence plainly: "There is no privileged core to patch."
A running dsh is assembled at boot from ordered layers. Bundles like dsh-base (model
adapters, tools, persistence, sandbox and approval policy) stack under dsh-web-app or
dsh-headless, then user patches apply on top, each targeting a config row by id and
replacing it whole. dsh --profile web --dump-config prints the tree your machine
actually boots, and the docs note that any row it prints can be replaced by a patch of
your own.
What does dsh get right?
The session log is the only source of model context
The strongest sentence in the architecture doc is four words: "Model-visible means logged." Anything that reaches a model request must be reconstructible from the append-only session log, and a runtime invariant asserts it. Model history is a projection of the log. Fork, resume, transcripts, telemetry, and persistence all derive from the same stream, which is why forking a live session is a single call in dsh.
Most harnesses, ours included, treat the transcript as a record they write with best effort while the real context lives in process memory. dsh inverts that: the log is the context. Replay fidelity and auditability stop being features you build and become properties you inherit.
Tool calls pass through guards that can only deny
dsh runs every tool call through a fixed pipeline: a pre-execute stage for hooks, permissions, and sandbox checks, then registered guards, then execution with timeout and retry handling, then a post-execute stage that can accept, block, or replace the result. The guards are the interesting part. The docs describe them as monotonic: they "deny or abstain," with their identity protected, so no plugin loaded later can widen a decision or impersonate the policy layer. Approvals fail closed. Per the tool-pipeline doc, a one-shot approval prompt that is absent or unanswerable means deny.
A policy layer that can only tighten is a structural guarantee, not a convention. A tool author who forgets about policy cannot bypass it, because policy is not the tool author's job.
Every new behavior has a documented home
The architecture doc ends with a table mapping each kind of change to its attachment point: a new model provider, a new tool, background work, filesystem policy, a sandbox backend. Capabilities are grouped into seams with a declared interface, so swapping one provider moves a whole family of behavior. The docs give the concrete example: filesystem and subprocess providers share one execution world, so pointing them at a remote sandbox "moves Bash, PTY, and LSP with them, with no provider forks." Sub-agents get the same treatment, "from a fresh child agent to a delegated turn in another product," behind one interface.
Documentation that says where code goes is rarer than it should be. It is the difference between a framework and a pile of extension points.
Where does the design cost you?
You have to learn Cordis before you can read anything
The architecture doc opens with a warning: "It assumes you know Cordis; if you do not, start with the primer or the tutorial." Two sentences later it adds, "We recommend using an agent to explore the codebase and understand its architecture." Both sentences are honest, and both are the bill for making everything a plugin.
Cordis brings five concepts (plugins, service contexts, injected dependencies, typed
events, reversible effects), and the event system has four dispatch modes. The primer
is explicit that "the dispatch mode is part of the event's public contract."
Waterfall listeners must call next() to delegate, so tracing one turn means walking
a chain of interceptors across plugins, and one listener that does not delegate ends
the chain. None of this is bad engineering. It is indirection purchased for
replaceability, and you pay it on every read.
The guardrails live in a swappable layer
The sandbox and approval policy ship inside dsh-base, as ordinary config rows in the
same patch system as everything else. A patch "targets a row by id and replaces its
whole config." For a single-user tool on your own machine, that is freedom, and dsh is
exactly that tool today.
But it means there is no static answer to "which guards run on this install." The
answer is always: whatever the four patch layers left in place, which you check with
--dump-config. The monotonic guard design protects you from plugins loaded beside
the policy. It cannot protect you from configuration that replaces the policy row
itself. Anyone building a multi-tenant or hosted product on dsh inherits that
property on day one.
It is a preview, and it moves
The README says developer preview and promises breaking changes. The commit count backs it up: over 12,000 commits, with several documentation corrections landing the same week we read it. In a framework where plugin interfaces and event dispatch modes are public contracts, that churn lands on every third-party plugin. Treat any specific claim in this post, and in the dsh docs themselves, as dated the day it was written.
How does dsh compare with the plori agent harness?
They answer different questions. dsh is a framework you assemble and host yourself: you pick the adapters, own the machine it runs on, and can replace any layer. plori is a cloud AI agent where each agent gets its own computer: a persistent account disk, real CLI tools, and a bill that stops when the agent sleeps. Our harness is a compiled Go loop, not a plugin tree, and that is deliberate. A hosted product wants byte-stable prompts for provider prompt caches, a fixed stop policy for agents that loop without progress, and approval gates that park a run until a human answers. Those properties are easier to guarantee when the loop is code you compiled than when it is a composition you configured.
The comparison cuts both ways. dsh has structural moves we lack: its log invariant is stronger than our append-only transcript, its guard pipeline is a better shape than our single pre-execution check, and it forks sessions in one call. We opened an internal epic to adopt all three. In the other direction, the problems a hosted harness sweats daily, prompt-cache economics, tenant isolation, per-run budgets, metered billing, do not appear in dsh's architecture docs at all. Neither project is ahead. They are optimizing different constraints.
When should you use dsh, and when plori?
Use dsh when the harness itself is your project. You want to swap model adapters, write your own sandbox backend, or study a cleanly factored agent loop. You are comfortable in TypeScript, and preview-grade churn is acceptable because you read diffs anyway. It is a good codebase to learn from, and its docs deserve specific praise for stating their own costs.
Use plori when the agent is the product and the harness is our problem. You want to hand work to an agent that keeps its files between sessions, runs while your laptop is closed, and asks before doing something risky, without learning a plugin framework or operating a host. That is the product we run, so weigh our bias accordingly.
The honest middle: if you are evaluating what to build on, read dsh's architecture doc even if you never run it. If you are choosing what to use, the framework-versus-product split answers the question faster than any feature table.
Limitations
This is an early, documentation-first analysis. We read the dsh architecture docs, the
Cordis primer, the tool-pipeline doc, and the README at master commit 1540e76
(August 13, 2026); we have not benchmarked dsh on agent workloads or audited the
implementation behind the docs. dsh is a developer preview and its docs were being
corrected the same week we read them, so verify quotes against the current tree before
relying on them. And we build a competing harness, which is a bias no disclosure fully
removes.