← News and insights

Why Is Everything a Plugin in DeepSeek Harness? An Architecture Walkthrough in 11 Diagrams

A visual walkthrough of plugin lifecycles, the agent loop, session logs and layered configuration—and what they mean for real-world delivery.

Why Is Everything a Plugin in DeepSeek Harness? An Architecture Walkthrough in 11 Diagrams

DeepSeek Harness (DSH) is DeepSeek’s open-source AI agent framework. The developer-preview version discussed here is released under the MIT licence, with source code available in the deepseek-ai/deepseek-harness GitHub repository.

First, what is a harness? DeepSeek puts it this way: Agent = Model + Harness. The model supplies the intelligence; the harness enables it to understand its environment, use tools and keep working in real systems. Think of a car’s chassis, steering wheel and dashboard: they do not produce power, but they determine how that power reaches the road.

DSH’s defining choice is to avoid a fixed core of agent capabilities. The loop, logging, retries, approval, context compaction, model access and interface are replaceable building blocks. Its guiding phrase is “Everything is a plugin”. Here, “no fixed core” does not mean there is no kernel: the Cordis kernel manages loading, unloading and dependencies, while plugins supply the agent’s capabilities.

This article uses 11 diagrams to explain how those blocks fit together, how they cooperate and why the architecture is built this way. No technical background is required. It is written for people evaluating agent frameworks for their teams.

01 / What it is: a framework without a fixed agent core

Start with the whole map. Capabilities commonly described as framework features—approval, retries, context compaction, session logs, sandboxing, model access and the web interface—are plugins in DSH, using the same mechanism as your own extensions. The foundation handles their lifecycle: loading, unloading and dependencies.

Figure 1 / The whole map: every capability is a replaceable block; the foundation manages their lifecycle.
Figure 1 / The whole map: every capability is a replaceable block; the foundation manages their lifecycle. Open full-size diagram ↗

Compare that with a familiar design: a fixed core with a few extension points. The core owns the loop, memory and retries, while the framework author decides which hooks to expose and where to put them.

DSH reverses that arrangement:

Others leave you openings; DSH gives you the whole floor. Even the loop, log and retries are plugins. Official features and third-party extensions use the same underlying mechanism.

Figure 2 / Design philosophy: official features and your plugins stand on equal footing.
Figure 2 / Design philosophy: official features and your plugins stand on equal footing. Open full-size diagram ↗

For example, compatibility with Claude Code hooks is itself an ordinary plugin. It follows the same loading and unloading path as an extension obtained from the community or written by you, rather than relying on a privileged route.

There is a cost. Many blocks jointly determine behaviour, which makes failures harder to trace. In a conventional framework, you might start with the core’s source code. In DSH, you first need to identify which plugins interacted at which stage. Greater freedom brings additional debugging work.

The foundation is built on Cordis, an existing open-source plugin system. Choosing a mature plugin substrate rather than inventing a new one is an engineering decision worth noticing.

02 / How the blocks fit: registration, lifecycle and the loop

A plugin is a new colleague, not a patch

Some plugin systems feel like patches inserted into an existing application. DSH’s model is registration: a plugin declares the capabilities it provides through the host’s interfaces. Think of a colleague registering their responsibilities on their first day, rather than rearranging everyone else’s desk. This describes the intended extension model, not a security guarantee that plugin code cannot alter shared state.

Five common registrations correspond to five kinds of capability:

① Add a tool: give the model another action it can call, such as querying a database.

② Add a prompt: supply instructions, such as requiring sources in an answer.

③ Subscribe to an event: observe or intercept a stage, such as checking a turn before it ends.

④ Provide a service: expose an interface that other plugins can call.

⑤ Mount a UI component: place an interface element in a slot provided by the web application.

Figure 3 / Starting a plugin means registering capabilities. Registration and disposal are paired.
Figure 3 / Starting a plugin means registering capabilities. Registration and disposal are paired. Open full-size diagram ↗

The key rule is that registration comes with automatic disposal. Unloading a plugin removes the tools, prompts, event subscriptions, services and interface elements registered through the managed lifecycle. The purpose is to keep the foundation clean as the number of plugins grows. It does not automatically undo external side effects or unmanaged resources created by plugin code.

Three lifecycle states: wait, work, leave

Each plugin declares the services it depends on. The foundation uses those dependencies to decide when the plugin can start and when it must stop:

Wait: required dependencies are missing, so the plugin does not start.

Work: dependencies are ready, so the plugin starts and registers its capabilities.

Leave: the plugin is disabled or a dependency disappears, so its registrations are disposed of. When the dependency returns, it can start again.

Figure 4 / The foundation resolves lifecycle order from dependencies rather than list position.
Figure 4 / The foundation resolves lifecycle order from dependencies rather than list position. Open full-size diagram ↗

This supports replacing plugins without restarting, giving different conversations different capabilities, and allowing an agent to add capabilities at runtime. Runtime extension is an important architectural possibility, although it still depends on the permissions and plugins available in a particular deployment.

The agent loop: six stages around the dial

The loop itself is deliberately straightforward. The diagram shows six stages:

① Assemble context from prompts, tools and history → ② Run an interceptable pre-flight check → ③ Ask the model, with retry handling supplied by plugins → ④ Append the reply to the log → ⑤ Execute tools, with interception before execution → ⑥ Append tool results to the log. Repeat while the model continues to call tools.

Retry, compaction and approval are supplied by other plugins at the intervention points marked in red. A compliance check before tool execution can attach at stage ⑤ rather than requiring a rewrite of the loop.

Figure 5 / Six stages in the loop. Red markers identify places where a plugin can intervene.
Figure 5 / Six stages in the loop. Red markers identify places where a plugin can intervene. Open full-size diagram ↗

In the loop described by the supplied diagrams, there is no fixed maximum step count. A step limit is another policy to add. When evaluating a deployed configuration, check its actual stop conditions and budget controls rather than assuming the default is suitable for your workload.

03 / One ledger: the underestimated session log

If we had to pick one design to remember, it would be the session log. The rule is simple: append records instead of rewriting past entries. The system prompt belongs in that record alongside user messages and model responses.

Figure 6 / An append-only session log provides a shared record from which other views are derived.
Figure 6 / An append-only session log provides a shared record from which other views are derived. Open full-size diagram ↗

That shared record provides the basis for six useful capabilities:

The model’s conversation: reconstruct context from the log at each step, rather than maintaining a separate, potentially inconsistent history.

Interface state: derive the visible trajectory from the same record used to assemble the model’s context.

Crash recovery: restore recorded session state by replaying the log. External tool side effects still require their own recovery strategy.

Forking: copy a prefix of the record and explore an alternative continuation.

Context compaction: change which earlier material is included in the active context while retaining the original record.

Traceability: inspect what the model was shown and which tools were invoked, using the recorded events.

Our view is that append-only logs are among the most underestimated design choices in agent systems. They attract little attention in a demo, yet become crucial when a team needs to reconstruct what happened. DSH gives traceability a structural foundation. A production audit system still needs appropriate retention, access control, integrity protection and coverage of external systems.

The diagram expresses the central idea as:

“Writing to the log” and “influencing the model” belong to the same information path. What the model sees should be accounted for in the log.

Read this as a practical test: to understand a plugin’s effect, inspect the entries it adds and how context is assembled from them. Documentation describes intent; the recorded trajectory shows what happened in a particular run.

Plugins cooperate through broadcasts and gates

Plugins do not need to know each other directly. The event system offers two broad patterns:

Notification: something has happened. A listener observes the event without changing its result—for example, generating a title after a turn or copying a completed tool event to an audit sink.

Interception: something is about to happen. Handlers can allow, modify or reject it—for example, checking a tool call before execution or deciding whether a failed request should be retried.

Figure 7 / Notification is a broadcast; interception is a gate.
Figure 7 / Notification is a broadcast; interception is a gate. Open full-size diagram ↗

Interception is a powerful extension point. Retry, compaction, approval, sandbox and planning behaviour can be supplied through these events, using the same mechanism available to application-specific plugins.

One warning deserves particular attention: when several plugins intercept the same event, order can affect the result. If both plugin A and plugin B modify a request, reversing them may change the outcome. Test the composition of handlers, not just whether each plugin works on its own.

04 / Assembly: lists layered on lists

The installed plugins are described by a list. The diagrams describe three kinds of edit: insert, replace and disable. Lists are then combined in layers, with later layers overriding earlier ones:

Layer 1 · Vendor bundle: a versioned package of plugins and assembly instructions.

Layer 2 · Client adjustments: switches, thresholds and model routing.

Layer 3 · Personal adjustments: additions and disabled capabilities.

Layer 4 · Launch-time overrides: temporary adjustments applied last, with the highest priority.

Figure 8 / Four configuration layers preserve separate ownership of customisation.
Figure 8 / Four configuration layers preserve separate ownership of customisation. Open full-size diagram ↗

This addresses a familiar software problem: how vendor upgrades coexist with local customisation. The vendor updates the base layer while client and personal changes remain in their own layers. Preserving those files does not guarantee compatibility with every new plugin version; upgrades still need validation.

The separation comes from the assembly model itself. Each party’s changes have a defined place, rather than being mixed into the same vendor-owned configuration.

Plugin, bundle, patch, profile, preset: five positions on one assembly line

Only plugins actually run. The other four terms answer a shared question: which plugins, with what configuration, for whom?

Figure 9 / Five related terms. Open the image for detail; a text explanation follows.
Figure 9 / Five related terms. Open the image for detail; a text explanation follows. Open full-size diagram ↗

① Plugin: one building block—the code that runs.

② Bundle: a versioned box of blocks and assembly instructions. Those instructions are themselves a built-in patch.

③ Patch: edits to the plugin list—insert, replace or disable.

④ Profile: a directory declaring bundles and local patches, combined in layers. Launch-time changes take precedence.

⑤ Process and preset: launching creates a process; each conversation selects a preset that determines the capabilities of that agent.

The process has two scopes. The host scope is shared across the process and configured by the profile: model services, logging, tool registries and the web interface. The agent scope belongs to each conversation and is configured by its preset. Presets use the same plugin-list syntax; removing the bash entry removes that capability from the role’s configuration.

One process can therefore host a research conversation, a compliance conversation and a macro-analysis conversation with different configurations. The result is a shared runtime with individually assembled agent roles.

05 / Context: MCP, Skills, Hooks and delivery

If MCP and Skills already exist, why have a plugin system as well? The diagram compares their typical responsibilities:

Figure 10 / MCP as an external supplier, a Skill as a manual, a Hook as a checkpoint and a DSH plugin as a resident team member.
Figure 10 / MCP as an external supplier, a Skill as a manual, a Hook as a checkpoint and a DSH plugin as a resident team member. Open full-size diagram ↗

MCP: connect external capabilities, commonly including tools and data sources.

Skill: provide instructions and reusable procedures for a task.

Hook: observe or intervene at a defined stage in the host’s workflow.

DSH plugin: participate in the host runtime, provide services to other extensions, add interface components and retain state. Its extension scope can cover the other patterns, although it is not itself a replacement for their protocols or packaging formats.

A useful analogy is a browser extension: it lives inside the host and can change aspects of the host’s behaviour. The comparison is about architectural roles, not a strict equivalence between technologies.

MCP integrations and Skills can be more portable across platforms that support them, although compatibility must still be checked. A useful division is to put reusable data access and methods in portable integrations, and use DSH plugins for behaviour tied to this runtime—interception, context injection or UI extensions.

What this means for forward-deployed engineering

The challenge in forward-deployed engineering (FDE) is not simply building the first agent for the first client. It is whether work from the first nine clients remains reusable for the tenth. Viewed that way, the architecture responds to seven practical delivery needs:

Figure 11 / Seven delivery needs and seven architectural responses. The reported cache-hit figure in the source diagram has not been reproduced in our environment.
Figure 11 / Seven delivery needs and seven architectural responses. The reported cache-hit figure in the source diagram has not been reproduced in our environment. Open full-size diagram ↗

Reuse completed work → Package plugins in versioned bundles, then deliver them to multiple clients.

Accommodate client differences → Express configuration differences through patches and presets rather than forking plugin code.

Keep customisation through upgrades → Separate vendor configuration from client layers, then validate compatibility during upgrades.

Change agent behaviour deeply → Use replaceable capabilities and interception points for policies, traceability and memory-related behaviour.

Make runs traceable → Use the append-only session record as a foundation for investigation, recovery and forking; add the controls required by the deployment.

Support local models and data → Replace the model-access plugin where appropriate. Local execution alone does not keep all data on-premises; review every model endpoint, tool, plugin and outbound connection.

Control long-running costs → Evaluate the architecture’s cache-oriented design against the actual workload and bill.

The supplied diagram reports a cache-hit rate above 95%. We have not reproduced that result in our own environment, so treat it as an unverified reference rather than a performance promise. Cache effectiveness depends on conversation structure and usage; someone else’s measurement cannot replace your own cost model.

The supplied materials also identify three limitations to check against the version you intend to deploy:

Interfaces are still evolving; plugins share a process rather than gaining automatic security isolation; multi-user access, team memory and shared workspaces require additional product work.

These limitations also suggest useful areas to build: isolation within the runtime, the relationship between team memory and the session log, and a multi-user permission model. Delivery teams can turn those gaps into reusable product capabilities.

A practical first step

Run DSH, export the log from one complete task and read it from beginning to end. With Node.js installed, the official quick-start command is:

npx @deepseek-ai/dsh web

Check whether the system prompt and every item of context supplied to the model are represented in the record. Then try reconstructing the task from it. A log that supports that investigation gives you a concrete basis for assessing recovery, forking and traceability.

DSH remains a developer preview, and its core plugins and APIs are expected to evolve. At this stage, understanding the architecture is the useful investment: it gives you a basis for judging future changes, rather than merely keeping up with individual API revisions.

Sources

1. DeepSeek Harness

2. GitHub · deepseek-ai/deepseek-harness

3. This article is adapted from the supplied WeChat article and its 11-page diagram series. English figures use DSH-Core-Mechanisms-EN-v3. The diagrams are explanatory material; implementation details should be checked against the official documentation and the version in use.