AGENTCONN

Field report · · AgentConn Team

Inside DeepSeek Harness: A Kernel, Not a Rival

We cloned the repo at 0.1.1-rc.2: 229 packages, 246K lines, and plugins that run Claude Code and Codex as subagents. The architecture read nobody filed.

AI AgentsAgent HarnessDeepSeekPlugin ArchitectureCordisClaude CodeOpen Source2026
A modular backplane chassis with a dozen removable circuit cards, one pulled halfway out and glowing at its connector edge

Inside DeepSeek Harness: A Kernel, Not a Rival

DeepSeek Harness landed on August 13, 2026 and collected 187,837 stars in ten days. Nearly every writeup filed it under the same headline: DeepSeek built a Claude Code competitor. TechNode framed it as “against Claude Cowork.” The New Stack led with the plugin architecture. SCMP called it a strategic pivot to agentic AI. All true, all surface.

So we cloned it — commit b150a55, tag release/dsh-0.1.1-rc.2 — and read the tree. The competitor framing collapses about twenty minutes in. dsh is not a coding agent that competes with Claude Code. It is a plugin kernel with no privileged core, and the most strategically loaded packages in the repository are the ones that mount Anthropic’s and OpenAI’s agents inside it. dsh-hooks-claude-code executes your existing .claude/hooks.json. dsh-subagent-claude-code invokes the official Claude Agent SDK as a delegated child process. dsh-subagent-codex does the same for Codex. The generic model adapter is backed by a library published by a competitor.

If the harness is the moat, DeepSeek is not attacking the moat. It is trying to own the layer that mounts harnesses — and demote every rival to a config row. That is a much more interesting bet than “we cloned Claude Code,” and it is also a much riskier one. Here is what the source actually shows.

What is actually in the tree

Numbers first, because the marketing page does not give you any.

The deepseek-ai/deepseek-harness GitHub repository page showing the MIT license and star count

At 0.1.1-rc.2 the workspace holds 229 packages, 1,397 TypeScript source files, 246,244 lines of src/, and 696 test files. There are 2,506 markdown documents, of which 744 are English-language design notes under .agents/notes — 561 implemented, 26 proposed, 144 archived, and 11 explicitly rejected. The repo ships four numbered postmortems. The default dsh-base bundle is a single YAML patch that inserts 78 plugin rows.

That last file matters more than it sounds. The base bundle is not a config file in the usual sense — it is the composition itself, a list of plugin identities and their configuration, applied as one insert over an empty profile root. Mode bundles patch rows by id, then your profile patches on top, then command-line overlays. There is no main() that wires subsystems together. Boot is layered composition, top to bottom.

Read this if you read nothing else in the repo: packages/bundle/base/cordis.patch.yml. Seventy-eight rows tell you exactly what DeepSeek considers the minimum viable agent, and every row is something you can delete.

Cordis: the part that is not marketing

“Everything is a plugin” is a slogan until you ask what happens when a plugin unloads. That is what Cordis, the framework underneath, actually contributes. Plugins register services, typed events, and reversible effects on a shared context, and registrations unwind when the plugin’s fiber disposes. Add and remove capabilities in a live process without leaking listeners, sockets, or half-registered tools.

The HN thread — which hit 745 points and 311 comments the day of release — did the most useful triage on this. One commenter who read the underlying paper landed on a fair verdict: it adds hot-reload and dynamic dispose to a plugin system, the framework requires each plugin to declare how it initializes and how it destructs “like C++‘s RAII, Rust’s Drop trait,” and if you already know OSGi or useEffect, a skim is enough. Another supplied the missing context: Cordis is not new. It has been running in production for roughly four years in a chat framework called Koishi; dsh is the first thing to ship on v4.

Hacker News thread on the DeepSeek Harness developer preview with 745 points and 311 comments

Read the full thread on Hacker News →

One of the harness authors showed up in the thread and set expectations honestly, which is more than most launches manage:

DeepSeek Harness author tianyicui replying on Hacker News that it is an early developer preview with rough edges

View the author’s reply →

The agent loop really is a plugin — and here is the proof

This is the claim most likely to be marketing, so we checked it against the dependency graph rather than the README.

@deepseek-ai/dsh-agent owns the Agent interface, the registry, and the event vocabulary. @deepseek-ai/dsh-agent-loop is a concrete driver — 1,662 lines across six source files, exporting a class literally named ReactLoopAgent. If the loop were the core, packages would import it.

They do not. Across the workspace, 88 packages depend on dsh-agent. Exactly one package takes dsh-agent-loop as a runtime dependency: dsh-base, the bundle that composes a default profile. The other 28 packages that mention it list it as a devDependency — they need a real loop to run their tests, not to do their jobs. Tool packages, hook bridges, subagent providers, compaction policies, plan mode: all of them talk to events and services, none of them talk to the loop.

That inversion is the whole trick. You can replace ReactLoopAgent with a different driver and the 88 packages that make the harness useful do not notice.

Diagram showing the three-package capability seam pattern for shell execution and a table of what ships behind each service seam in DeepSeek Harness

The pattern generalizing this is what the docs call a capability seam, and the discipline is stricter than typical dependency injection: a seam is three roles that normally live in three packages — a Service Definition that owns ctx.<key> and the vocabulary types (an abstract class, never a TypeScript interface, so it survives to runtime), one or more Providers, and Consumers that inject the service. packages/shell is the canonical example: dsh-shell defines, dsh-bash-local and dsh-bash-sandbox provide, dsh-tool-bash consumes.

The payoff is a property most harnesses cannot offer. Filesystem and subprocess providers share an execution world, so pointing both at a remote sandbox moves bash, PTY, and LSP with them — “with no provider forks,” as the architecture doc puts it. Remote execution is a configuration change, not a fork of every tool.

The session log is the source of truth, and everything else is derived

The single best idea in the codebase is one sentence from docs/architecture.md:

Model-visible means logged — anything that reaches a model request must be reconstructible from the log.

Everything the model sees is a durable event appended to an append-only session log: system prompts, reasoning, tool calls, tool results, subagent scheduling, and every context injection. The message array handed to the model is not stored — it is computed by deriveMessages() from that stream.

Follow the consequence. Forking a session, resuming after a crash, replaying a run, searching a trajectory, exporting a transcript, and emitting telemetry are not six features. They are six projections over one event stream, and the log is the only thing persistence has to get right. Want SQLite instead of JSONL? Swap the ctx.sessionPersistence provider; nothing above it changes.

Adding a new model-visible input requires extending SessionEventMap and rendering it from the log. You cannot slip context into a prompt without leaving a record — the invariant is enforced by where the message array comes from, not by a code review convention.

Turing Post article: DeepSeek Opens the Agent Layer — While Agents Get Harder to See Inside

Read the full analysis on Turing Post →

Turing Post put the timing well: agent systems are getting more capable and less inspectable at the same time, with encrypted reasoning blocks passing between calls that logs never show. An HN commenter made the sharper version of the point — traceability at this level “is a killer feature, IMHO, and one that US models won’t allow you to do, as their traces are encrypted, obfuscated.” Whatever you think of the rest of dsh, the trajectory view is the honest artifact here, and it is the reason to run it even as a research harness.

One tool call, three waterfalls

If the session log is the best idea, the tool execution pipeline is the best engineering. It is also the piece most worth stealing, because it answers a question every agent team eventually hits: where does policy go?

Flow diagram of a single tool call through DeepSeek Harness: tool/call logged, pre-execute waterfall, monotonic guards, approval, execute waterfall, tool body, post-execute waterfall, finalizeContent, tool/result

Three details make this better than the usual middleware chain.

The call is logged before it executes. tool/call is appended to the session log ahead of the pre-execute waterfall. The record precedes the effect, so a crash mid-execution still leaves an auditable intent.

Guards are monotonic and denials still flow. Waterfall listeners delegate by calling next(), but registered guards can only deny or abstain — they can never widen permission, and their identity is protected so ordering cannot be rewritten by a later plugin. When a guard or an unanswerable approval prompt kills a call, the tool body is skipped but the call still re-enters tools/post-execute. The model receives exactly one tool/result either way. There is no path where a denial silently produces nothing.

Code Mode does not get a bypass. The run_code transport lets the model write a TypeScript program that orchestrates several tools at once. Every sub-call that program dispatches re-enters the complete guarded pipeline, carries the parent token, and logs a tool/code-dispatch pair. Policy applies to generated code exactly as it applies to a direct call.

The pattern to copy: one pipeline, four attachment points, zero policy inside tools. Timeouts wrap tools/execute. Oversized output is a tools/post-execute transformer that spills the full text to a session-scoped file and hands the model a head/tail preview plus a path it can grep. Hook bridges, sandbox mode, and permission presets all attach at tools/pre-execute. None of the 25+ shipped tool packages contain a line of policy logic.

Sandboxing that admits what it cannot do

Most agent frameworks describe sandboxing as a boolean. dsh treats enforcement as a reported fact.

SandboxMode is read-only, workspace-write, or danger-full-access, and it governs filesystem effects only — network and process visibility are explicitly outside the vocabulary rather than quietly implied. Backends are dsh-sandbox-local with bwrap/Landlock on Linux, Seatbelt on macOS, and a restricted-token ACL runner on Windows. Each reports enforcement as full or partial, where partial means an older kernel ABI or an active backend governs only a subset of promised effects. Consumers that require an absolute boundary must reject a partial rather than treat it as full.

Approval and sandboxing are deliberately independent knobs — approval decides whether a human is asked, sandboxing decides what is reachable — bundled into named presets like workspace-write + ask and danger-full-access + never. The docs state the reason plainly: an approval dialog is not a filesystem boundary, and a sandbox is not a substitute for user intent. Composing the preset service over a bash executor that cannot confine throws at plugin load rather than pretending.

The honesty is not accidental. Postmortem 0004 in the repo is titled landlock-partial-notice-misclassified-child-failures — they shipped the write-up of the time this exact distinction went wrong. If you are building a guardrail stack for agents or sandboxing untrusted agent code, the full/partial reporting contract is worth adopting before anything else in this repo.

The move nobody covered: rivals as plugins

Now the part that reframes the launch.

@deepseek-ai/dsh-hooks-claude-code is a plugin that reads your existing Claude Code hook configuration — a hooks.json or a settings file’s hooks key — and runs the supported command-hook subset on the harness’s own interception points. It handles Claude Code’s env substitution, including ${CLAUDE_PLUGIN_ROOT} and ${CLAUDE_PROJECT_DIR}, and maps each hook to a typed decision: PreToolUsetools/pre-execute, PostToolUsetools/post-execute, SessionStartagent/session-start, Stopagent/turn-stopping. dsh-hooks-codex does the same for Codex’s dialect, implementing five of its ten hook points.

The package’s own README is unusually candid about why it exists: a native Cordis plugin could do everything the bridge does, “more powerfully, with typed returns and no serialization boundary.” The bridge exists only as a compatibility path. That is not an engineering statement. That is a migration ramp.

@deepseek-ai/dsh-subagent-claude-code goes further. It registers a subagent provider whose default name is claude-code; each accepted run invokes the official Claude Agent SDK in the delegating session’s workspace, lets the pinned SDK select its installed platform CLI, and returns the final answer through the shared subagent result contract. It exposes Anthropic’s own permission modes — dontAsk, acceptEdits, auto, plan, bypassPermissions — as configuration on a DeepSeek plugin. dsh-subagent-codex mirrors it.

And the generic model adapter, dsh-llm-pi-ai, is built on @earendil-works/pi-ai — the model library from Earendil, makers of the competing Pi agent. DeepSeek hand-rolled its own DeepSeek adapter and outsourced everyone else’s providers to a competitor’s package.

Armin Ronacher, Earendil’s co-founder, was one of the more generous voices in the reaction:

Armin Ronacher on X: I don't think the DeepSeek Harness is perfect but this is for sure the first time I have been looking at something new in the space and felt quite inspired

View the original post on X →

Put the three packages together and the strategy resolves. Every competing harness accumulates lock-in through configuration — your hooks, your skills, your permission settings, your muscle memory. DeepSeek’s answer is not to build a better version of that lock-in. It is to absorb it: bring your Claude Code hooks, keep calling Claude Code for the work it is good at, and let dsh own the loop, the log, the policy pipeline, and the sandbox underneath. The moat does not get crossed. It gets mounted.

Contrarian Corner: no privileged core is not the same as no core

The architecture's central promise contains its central problem. "There is no privileged core to patch" does not delete the core — it relocates it into the composition file. cordis.patch.yml is now the thing that determines whether your agent works, and it is the least documented surface in the entire repository.

The independent hands-on reviews are damning in a specific way. One controlled three-run benchmark ran the same task under three configurations: all three runs printed confident “Done” summaries with verification checklists, and exactly one produced a page with zero console errors. The reviewer’s line is the right one to remember: “Every run reported success. Only one produced a page with zero console errors. Read the output, not the summary.” The decisive variables — compat.thinkingFormat and maxTokens — were documented only in package READMEs, not the official guide. Two missing YAML lines turned a 152-second, 15-step run into a 422-second, 36-step one.

A second in-depth review measured roughly 10× the token consumption of Pi and 3× other frameworks, partly from a duplicate-instruction-injection bug that doubled the system prompt, and found all five attempted third-party plugin integrations failed outright despite a 2,000-plugin ecosystem forming within days. That is what an ecosystem looks like on day four: a lot of packages, very little compatibility.

The HN skeptics got to the structural version first. “I have developed over the years a plugin fatigue,” one wrote. “Every product relying on community plugins for their features implies it works fine the six first months, then it’s a nightmare of incompatible, deprecated plugins, with no consistency and no governance.” Another simply asked, “But like, what is it?” — a fair question about a #1 HN post whose README was installation instructions and a link to a paper on spatiotemporal composability.

r/LocalLLaMA thread titled DeepSeek Harness is Insanely Good with 172 upvotes and 140 comments

Read the r/LocalLLaMA thread →

There is a real counterweight, and it is where the local-model community landed: the seam design pays off immediately if your model is not a hosted frontier API. One HN user reported connecting dsh to a 9B speculative-decoding Qwen variant running in llama.cpp and getting good results on small Python projects, faster than other harnesses they had tried. That is ctx.llm doing its job. The broader r/LocalLLaMA harness discussions show the same shape — people shopping for a runtime, not a model.

r/LocalLLaMA thread asking for the best harness for long autonomous tasks

Read the discussion on r/LocalLLaMA →

The honest summary: 229 packages and a private vocabulary — seams, waterfalls, monotonic guards, fiber states, scope carriers, Ralph rounds — mean the marginal cost of your first plugin is learning an ontology. DeepSeek bet that composability is worth an ontology tax. 187,837 stars say developers want the idea. The hands-on reviews say the product is not there yet. Both are true, and neither is the interesting question.

What to steal even if you never run dsh

You do not need to adopt Cordis to benefit from having read this repository. Five patterns transfer directly to whatever harness you already run:

  1. Make model-visible imply logged. Derive your message array from an append-only event stream instead of storing it. Fork, resume, replay, and audit stop being features and become projections.
  2. Give policy exactly one attachment point. A pre/around/post pipeline around tool dispatch, with denials flowing through post-execute, removes permission logic from every tool you will ever write.
  3. Split seams into three packages. Definition, provider, consumer. The test is whether swapping a provider requires touching a consumer. If it does, you have dependency injection, not a seam.
  4. Report enforcement, do not assume it. full versus partial is two extra characters in a return type and the difference between a sandbox and a story about one.
  5. Ship your rejected designs. Eleven rejected notes and four postmortems in a public repo tell a contributor more about the system’s boundaries than any architecture diagram. Most teams delete this material; it is the highest-signal documentation they produce.

The bottom line

Do not run DeepSeek Harness as your production coding agent this quarter. The authors say so themselves — developer preview, compatibility-breaking changes, rough edges — and the benchmarks confirm it. Confident false-success summaries are the single most expensive failure mode an agent can have, and dsh has that bug today.

Do run it as a research harness. There is no better instrument available right now for seeing what your model actually receives, because the trajectory view exposes the full trace that hosted agents encrypt. If you are evaluating models — especially local or open-weight models — the combination of a swappable ctx.llm and a complete session log is a genuinely differentiated evaluation rig. That is the use case the model-versus-harness debate has been waiting for, and it is worth an afternoon regardless of what you ship on.

Here is our prediction. The plugin ecosystem will not be what determines whether this succeeds — plugin fatigue is real and the day-four compatibility numbers are bad. What will determine it is whether dsh-subagent-claude-code and dsh-hooks-claude-code keep working as Anthropic and OpenAI iterate. Those two packages encode a strategy of absorbing your competitors’ configuration surface, and that strategy has exactly one failure mode: the competitors changing their surface faster than a bridge can track it. Watch those bridges. They are the real product roadmap, and the first quarter one of them is quietly deprecated is the quarter this bet is settled.

The AgentConn Weekly

Weekly digest of new AI agent releases, framework comparisons, and deployment guides. Built for builders.

Weekly. Unsubscribe anytime.

Explore AI Agents

Discover the best AI agents for your workflow in our directory.

Browse Directory