跪拜 Guibai
← Back to the summary

DeepSeek Harness Runs on a Plugin Architecture Where Even the Core Is Swappable

On the night of August 12, DeepSeek quietly launched the official version of V4 Pro: 1 million token context, a maximum output of 384,000 tokens, and a generational leap in official self-tested Agent benchmarks compared to the April preview—DeepSWE jumped from 12.8 to 62.7, and Cybergym reached 83.3. On the 13th, the official WeChat account made the formal announcement, with the App, web version, and API going live simultaneously.

Released at the same time was the developer preview of DeepSeek Harness—an open-source agent runtime framework, with a command-line tool called dsh.

DeepSeek Harness Official Website Homepage

I first tried its Web version, and honestly, it felt quite promising. Two reasons: first, it deeply binds its own model—Harness paired with V4 Pro, stacked with the initial pricing (before the August 17 adjustment) of 3 yuan per million input tokens and 6 yuan per million output tokens, makes the cost of this path reassuringly low; second, trust. Trust in the company DeepSeek—or more personally, trust in Liang Wenfeng.

Then, I saw this tagline on its repository homepage:

DeepSeek Harness: Everything is a Plugin.

The README's original text is more complete: "It uses an architecture where everything is a plugin, and is powered by Cordis."

Everything is a plugin. This sentence deserves a careful look.

Starting from VS Code

In July, I wrote an article titled "Learning System Architecture from VS Code", and one point left a deep impression: VS Code's architecture is cleverly done; it leaves the single task of "editor" to the kernel, and almost all other capabilities are accessed through plugins—language services (LSP), Git, themes, debuggers, all are extensions. The kernel without plugins is still a usable editor; plugins are just peripheral additions.

"Everything is a plugin" sounds like the same thing, but Harness goes further: In Harness, even the "core" is a plugin.

VS Code's kernel is a hard-coded editor; Harness has no kernel. Its underlying layer is based on a plugin framework called Cordis (whose design philosophy originates from the paper "A Programming Paradigm for Spatiotemporal Composability"). The entire system has only a shell layer for "wiring and scheduling"; all remaining capabilities—calling models, managing sessions, executing tools, agent loops—are entirely provided by plugins.

In other words:

image.png

Four Mechanisms Supporting "Everything is a Plugin"

The official Cordis Getting Started Guide is written with restraint, and the core points are just these few things:

1. Services are mounted on the context. What each plugin provides is not an isolated class, but a service mounted on the global context, occupying a stable key: ctx.llm, ctx.tools, ctx.sessions, ctx.agents. Other plugins find services by key, rather than importing a specific implementation. If you want to use a model, you find ctx.llm—whether it's V4 Pro or something else behind it, you don't know and don't need to know.

2. Dependency injection determines startup order. Plugins use inject to declare which services they need, and the framework waits for these services to be ready before starting it. The startup order is automatically derived from the dependency graph; there is no hand-written orchestration table, and no problem of "my plugin started first, but the thing it depends on hasn't arrived yet."

3. Events are typed and can "intervene." Cordis events have four dispatch modes:

Mode Waits Dispatch Order Can Return Results
emit No Registration order No
waterfall No Registration order Yes
parallel Yes Parallel No
serial Yes Registration order Yes

The key is waterfall: the listener receives a parameter with a next(), passes it to the downstream for processing, and the downstream's return value comes back to you—so the listener can modify, wrap, or even short-circuit (return directly without calling next, and the subsequent listeners won't receive it). This is completely different from VS Code's pure broadcast events (onDidXxx): broadcast can only listen, waterfall can change.

4. All registrations are reversible. Listeners, prompt fragments, tool schemas, all are installed via ctx.effect() (or ctx.on()). The framework keeps an account of every registration and automatically revokes them on uninstall or hot update. The pitfall in VS Code where forgetting to write deactivate cleanup leaks subscriptions does not exist here.

Get a feel for "what a plugin looks like." Here is a minimal plugin (illustrative code) that automatically adds a date sentence to each request's prompt:

import type { Context } from '@deepseek-ai/cordis'

export const name = 'date-context'
export const inject = []   // Depends on no services

export function apply(ctx: Context) {
  ctx.effect(() => {
    return ctx.on('prompt/build', (prompt) => {
      prompt.prepend('Today is 2026-08-13.')
    })
  })
}

No registration entry point, no manifest, no startup order configuration. Put it in the plugin list, and it lives; remove it from the list, and it automatically cleans up everything it left behind.

What Harness Did with It

In March, I wrote an article called "Harness Engineering", where I defined Harness at a conceptual level: an environmental system that allows Agents to be stably steered—task expression, context organization, tool governance, state management, feedback loops. This time, DeepSeek delivered a code-level implementation, which looks like this:

# dsh's plugin list (illustrative)
plugins:
  - @deepseek-ai/plugin-llm      # ctx.llm —— Model calling
  - @deepseek-ai/plugin-sessions # ctx.sessions —— Sessions
  - @deepseek-ai/plugin-tools    # ctx.tools —— Tool registry
  - @deepseek-ai/plugin-agents   # ctx.agents —— Agent loop

Note that there is no "Harness body" item in this list. The Web version you see is just the official team assembling this set of lists and wrapping a UI on top. Want to change the model? Swap out plugin-llm. Want to change the agent's decision-making method? Swap out plugin-agents.

The relationships between plugins can be drawn as a dependency graph: official plugins each mount their services onto the context, and your plugin only faces the service, not the implementation:

image.png

Your plugin works at the same level as the official plugins—whatever official plugins can do, you can do, including replacing the official plugins themselves.

In Practice: Notify My WeCom When a Task Completes

Let me describe a scenario I actually want to implement: let dsh run a long task, I don't want to watch the terminal, and when the task completes, automatically push a message to a WeCom group.

First, add a group bot in the WeCom group (now officially called "Message Push"), get its webhook address, then write the plugin:

// plugins/wecom-notify.ts —— Illustrative code, event names and details subject to official documentation
export const name = 'wecom-notify'
export const inject = ['llm']

export function apply(ctx, llm) {
  ctx.effect(() => {
    return ctx.on('task/complete', async (result) => {
      const summary = await llm.chat(`Summarize this task result in one sentence: ${result.output}`)
      const res = await fetch(process.env.WECOM_WEBHOOK_URL, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          msgtype: 'markdown',
          markdown: { content: `✅ Task completed\n> ${summary}` },
        }),
      })
      const { errcode } = await res.json()
      if (errcode !== 0) throw new Error(`Notification failed: errcode ${errcode}`)
    })
  })
}

Add it to the list, done:

plugins:
  - @deepseek-ai/plugin-llm
  - @deepseek-ai/plugin-sessions
  - @deepseek-ai/plugin-tools
  - @deepseek-ai/plugin-agents
  - ./plugins/wecom-notify

The entire notification process is like this: the agent loop emits an event when the task ends, your plugin receives it, borrows ctx.llm to make a summary, and then pushes the result to WeCom. Every arrow is not a hard-coded call, but a service and an event:

image.png

About twenty lines. The mechanisms described earlier are all used in this code:

As a comparison, if this were a VS Code plugin, for the same functionality you would have to: register the extension, check for null when getting another extension's API, and then manually clean up the subscription in deactivate. Here, these three things are absorbed by the mechanism itself.

Note: task/complete is an event name I made up for the demonstration. The official primer says new events will be registered with @mode tags and generate a directory; the specific event list awaits documentation completion.

Boundaries of the Preview Period

Finally, a splash of cold water. The README has a capitalized warning: "THERE WILL BE COMPATIBILITY-BREAKING CHANGES"—during the developer preview stage, the API can change at any time, don't rush to depend on it in a production environment. The plugin publishing channel is also not fully open yet (the official team has prepared the dsh-plugin topic tag for plugin authors, the ecosystem is just starting). Currently, the only way to get started is: npx @deepseek-ai/dsh web, running a Web interface locally.

But if you want to get your hands dirty after reading this, the path is already paved: the official documentation site has a quick start guide, and the Cordis tutorial in the repository has seven chapters in total, with the first chapter being the hello world of the first plugin—including where to put the plugin list (loader configuration) and how to write it. The API will change, but these broad frameworks will not.

But the architectural signal is clear: it makes replaceability a first-class citizen of the system. In an era where the agent technology stack is far from settled, the prerequisite for a harness to survive is to allow itself to be repeatedly disassembled and reassembled. DeepSeek chose a foundation suitable for rapid trial and error—this is probably the real meaning of the phrase "everything is a plugin": not a technical show-off, but a survival strategy.

If this is the direction DeepSeek wants to fight for in the coming year, then my expectations for it are a little higher than for a V4 Pro.