DeepSeek Harness (Architecture): Why Even the Agent Loop Is Replaceable
Most plugin systems start with a fixed core, then let plugins add themes, commands, or tools around it.
DeepSeek Harness does it differently.
The Agent Loop is the core of any agent: it organizes model decisions, tool executions, and result feedback, and decides whether to continue or stop. In conventional plugin architectures, this lives in the software core—plugins can only extend around it.
But the official architecture docs explicitly treat the Agent Loop as a plugin, alongside the model adapter, tool registry, and session logger.
That's the biggest difference: even the core execution loop can be replaced.
The "capability boundary" here works like a socket: it defines how requests come in, how results and errors come out, but doesn't mandate which concrete implementation sits behind it. The socket stays the same, so the model adapter, filesystem, or Agent Loop can all be swapped out independently.
1. The Plugin Isn't an Add-on—It Is the Product
A typical plugin system looks like this:
Fixed Agent Loop + peripheral plugins
The main program drives workflow; plugins can only add features at reserved spots, and rarely touch model adapters or the execution loop.DeepSeek Harness follows a different structure:
Stable interfaces + composable plugins including the Agent Loop
Model calls, tool execution, session logging, filesystem, sandbox, and the Agent Loop itself are plugins that compose the default product. There's no official-only Agent core."Everything is a Plugin" doesn't mean the system has no rules. Plugins still must honor interfaces, dependencies, and runtime contracts. What's removed is the assumption that some default implementation is inherently irreplaceable.

2. The Plugin Tree Is an Agent Assembly Map, Not a Feature List
DeepSeek describes a running dsh instance as a plugin tree—a record of which components were loaded on this startup and who provided them.
In the .dsh/profiles/ directory, you can see two separate Profile sets: web and headless.

The Web config shows these distinct entries:
- id: llm
name: '@deepseek-ai/dsh-llm'
- id: session
name: '@deepseek-ai/dsh-session'
- id: tools
name: '@deepseek-ai/dsh-tools'
- id: agent-loop
name: '@deepseek-ai/dsh-agent-loop'
- id: web-runtime
name: '@deepseek-ai/dsh-web-app'The Headless config still keeps llm, session, tools, and agent-loop, but drops the web interface and ends with its own startup and runner:
- id: headless-startup
name: '@deepseek-ai/dsh-headless/startup'
- id: headless-runner
name: '@deepseek-ai/dsh-headless'Here "Headless" means a command-line entry that doesn't spin up a web server or browser. It accepts a task, waits for the Agent to finish, prints the final reply, and exits.
It's great for one-shot scripts, but it's not what the official docs call the SDK approach.
The Python SDK is a separate programmatic entry. Callers can start a full Harness runtime, reuse processes, manage sessions, submit tasks continuously, and subscribe to events.
The SDK communicates with the runtime over stdio using JSON-RPC—it doesn't use the Headless runner's one-shot model.
Three entry points, distinguished:
| Entry | Use Case |
|---|---|
| Web | Browser-based interaction |
| Headless | Command line, one task, output, exit |
| SDK | Another program drives the Harness runtime continuously |
What they share: none of them are hard-wired to a specific model, tool, session, or Agent Loop. The Web vs. Headless config comparison shows the same underlying plugins can connect to different entry points. The SDK goes further, letting an external program drive an entirely different plugin composition.
3. Replaceability Requires Separating Capability, Implementation, and Consumer
Breaking code into many packages doesn't automatically make implementations swappable. If the upper layer directly binds to a concrete implementation, changing that implementation still requires changing the consumer.
DeepSeek Harness divides each replaceable capability into three roles:
- Capability interface: defines the socket—inputs, outputs, and error shapes;
- Provider: the concrete implementation doing the actual work;
- Consumer: calls the capability through the interface to accomplish higher-level tasks.
The relationship in one line:
Consumer → Stable Capability Interface ← Current Provider
Take file operations as an example.
Upper-layer tools only care about reading, writing, and searching files. Both a local filesystem and a remote sandbox can be providers—as long as they honor the same contract, the upper layer doesn't need a separate implementation for each environment.
The same applies to command execution: the real runner can be local PowerShell, a restricted sandbox, or a remote environment.
Replaceability isn't arbitrary swapping. A new provider still must correctly handle permissions, paths, error reporting, and lifecycle.
4. Model, Tool, and Session: Three Independent Boundaries
Once the capability interface concept is clear, the model, tool, and session boundaries become concrete rather than abstract.
Model boundary: handles connecting to different model providers. The Agent Loop issues a unified model request; the adapter translates it into whatever protocol the specific provider understands. Swapping model implementations doesn't require the Loop to know every vendor's interface details.
Tool boundary: registers which tools the current Agent can see, and manages pre/post-processing around actual tool execution. Files, commands, and other capabilities can be added separately—no need to stuff all tool code into the Agent Loop.
Session boundary: records user messages, model replies, tool calls, and tool results. Resume, fork, replay, and other capabilities can all be derived from this record rather than relying on whatever's temporarily visible in the web UI.
A single task flows through all three boundaries roughly like this:
Agent Loop requests model
→ Model selects a tool
→ Tool executes and returns result
→ Result is written to session
→ Agent Loop decides whether to continueAll three boundaries cooperate but remain unbound to each other. Swapping one doesn't require rewriting the others.
5. Why Even the Agent Loop Is Replaceable
In conventional plugin systems, the Agent Loop belongs to the software core—plugins can only extend around it.
DeepSeek Harness separates "how an external caller uses an Agent" from "how an Agent internally advances a task."
Web, Headless, or SDK only need to know how to create an Agent, submit a task, and read its status. How the task is advanced internally is determined by the Agent Loop plugin. The agent package in the source provides the public contract; @deepseek-ai/dsh-agent-loop is the official default implementation.
Swapping the Agent Loop doesn't require rewriting the UI, SDK, session, or tool system. Any alternative scheduler just needs to honor the same contract to keep using those capabilities.
"Replaceable" doesn't mean deleting the Loop—it means allowing different implementations. A replacement still must handle capability dependencies, state consistency, errors, and execution ordering. Plugin architecture provides choice; it doesn't guarantee the new Loop works better.
Conclusion
What stays open is the capability boundary, not the number of plugins.
Now the opening question can be answered: if the Agent Loop is a plugin too, does DeepSeek Harness have a core at all?
Yes.
What stays stable is the capability interface and the collaboration contract. What's variable is the concrete implementation currently loaded.
When you see another Agent framework claim "plugin support," ask three questions first:
- What can actually be replaced—peripheral features, or critical capabilities like model, tools, state, and the execution loop?
- Do upper modules depend on stable interfaces, or are they directly bound to a default implementation?
- When replacing one provider, must other modules be copied or rewritten to match?
Most plugin systems extend the Agent Loop. DeepSeek Harness makes the Agent Loop itself replaceable. That's the real difference behind "Everything is a Plugin."
The next article in this series traces a real request deeper—looking at how turns, steps, model calls, tool executions, and result passing link together into one complete task.