DeepSeek Harness: plugins, core and capability seams

DeepSeek opened the Harness repository on 13 August, a TypeScript agent runtime under the MIT licence, built on Cordis. The documentation publishes a table declaring the role of each of its 56 service rows, 26 of which are extension points. The agent loop is a row in a configuration file, and the actions allowed on an existing row are six, named in the interface.

AIOpen SourceAIAI AgentsOpen SourceDeepSeekArchitecturePluginsTypeScriptMCP
Four figures on the architecture of the DeepSeek Harness agent runtime
The architecture as it reads in the repository on 16 August. Sources at the end.

The repository deepseek-ai/deepseek-harness was created on 13 August 2026 at 11:56 UTC, in TypeScript, under the MIT licence. Read on 16 August at 12:48 CEST, the GitHub API reports 124,089 stars and 12,288 forks.

Harness sits between a model and the tools, files and environment an agent works on, which is the place we wrote about in harness engineering and in the shapes to give a cycle. The interesting part is how it is built.

The table that declares each service’s role

The document docs/capability-seams.md lists 56 service rows and declares a role for each: 26 are marked seam, meaning intended extension points, 29 are marked core, and one, ctx.agentLoop, is marked bundle.

An extensible runtime that publishes the list of its own extension points, row by row with the role beside it, tells anyone evaluating it where they can intervene without having to find out by reading the code. It is the document to open first.

Among the core rows are ctx.sessions, the append-only session log, ctx.agents, the agent registry and factory, and ctx.tools, the tool registry and execution pipeline. Among the seam rows, ctx.llm already has several implementations in tree, among them llm-deepseek and llm-pi-ai.

The project is built on Cordis, a service and plugin framework that predates Harness and sits in the repository as a vendored subtree. docs/architecture.md describes the model at line 13: “you extend dsh by mounting a plugin beside the others, and registrations are effects that unwind when their plugin unloads”.

That second half is what matters in operation: a plugin’s registrations are effects that unwind when the plugin unloads. A runtime that loads and unloads components hot without leaving orphan registrations solves a problem usually discovered late.

The agent loop is a configuration row

The base bundle carries a cordis.patch.yml of 451 lines with a single - insert: block, and at lines 436-439 declares the entry - id: agent-loop with the package implementing it.

Replacing an agent’s cycle therefore means changing one row in a configuration file, without touching the rest of the runtime. For anyone who has tried to change an agent’s strategy inside a framework that keeps the cycle in its own core, that is a substantial difference in work.

The patch mechanism has two branches, insertion and override by id. On an existing row the actions are six, named in the PatchOptions interface: config, disabled, inject, intercept, isolate and group. Having them named, rather than leaving substitution to a convention, makes what happens to a component readable from the configuration file.

Interoperability in both directions

On MCP, Harness acts as a client, so it consumes existing servers.

In the opposite direction the repository carries packages/acp, a server exposing Harness agents to programmatic clients over the Agent Client Protocol. The documentation qualifies it as “an interoperability transport, not a presentation layer”, with two permitted transports, stdio and streamable-http. Server names are constrained to [A-Za-z0-9_-]{1,32} and public ones are normalised to 64 characters, with a deterministic 12-hex hash on collision.

A runtime that is a client of one protocol and a server of another fits into an existing toolchain from both sides.

The Landlock launcher

Under native/landlock-run the project ships a native launcher based on Landlock, the Linux kernel security module that lets a process restrict its own filesystem and network access without root privileges. It carries a BSD 3-Clause licence, separate from the MIT of the rest.

For a runtime that executes tools and plugins, having the piece that confines a process in house is useful material: confinement remains something to configure, but the building block is there and does not have to be sourced elsewhere.

Next to the ones that already exist

OpenHands is MIT, with 84,167 stars on the main repository and a separate SDK in Python, whose base class AgentBase states in its docstring: “Agents are stateless and should be fully defined by their configuration”.

Aider is Apache-2.0, with 48,260 stars, and picks the implementation by iterating coders.__all__ inside Coder.create. In the aider/ package the string mcp appears zero times.

What sets Harness apart is where the replaceability lives: in rows of a configuration file with named actions, over a set of seams declared in a document, rather than in a class hierarchy to extend.

What it takes to try it

The baseURL is configurable, both on llm-deepseek, which points by default at https://api.deepseek.com, and per route on llm-pi-ai, and model discovery goes through an OpenAI-compatible GET /models. A compatible endpoint can therefore be pointed at.

The repository carries no local execution path: a search across every tracked file for ollama, vllm, sglang, llama.cpp and gguf returns zero occurrences.

DeepSeek API prices read on 16 August, per million tokens: flash at $0.0028 on a cache hit, $0.14 on a cache miss and $0.28 on output; pro at $0.003625, $0.435 and $0.87.

What we will see

This is a three-day-old developer preview, and some things will be judged later.

As of 16 August the repository has no tags and no releases, and the 0.1.0-rc.6 published on npm has no matching commit in the public history, which stops at rc.5. For a trial on a development machine that changes nothing, and we will see which versioning scheme the project brings to a stable release.

Plugins are installed from a GitHub reference resolved by pnpm, as the Plugin management section of the CLI reference documents, noting that “pnpm must be on PATH”. A registry, signing or an allowlist are not documented at present, and that will be one of the more informative choices of the coming months. Until then a plugin is treated like any other dependency, with review, pinning and a confined environment.

It remains to be seen how many of the 29 core rows will become seam, and which will stay where they are. The answer will say how much the project’s formula holds as a principle and how much as a description of this version.

Sources

Need support?Under attack?Service Status
Need support?Under attack?Service Status