DSH Composite Model Explained: Plugin Layering in a Coreless Architecture

DSH uses an empty-root + layered Patch model instead of a config language — changing capabilities means changing plugin composition.
DeepSeek Harness (DSH) is a coreless Agent platform that abandons standalone configuration languages in favor of a three-layer composition model: Profile sets the foundation, Bundle packages plugin rows, and Patch is the user override layer. Key design principles include an empty root (Coreless.iml) to prevent user changes from being polluted during upgrades, row-level atomic replacement (not field-level merging) for unambiguous semantics, service-dependency-driven activation (not file order), and mandatory Isolate domains for service-publishing rows. DSH also supports in-process dynamic plugin mounting via a Plugin/Package/PluginUnit three-level model, enabling runtime capability extension without touching any files.
An Architecture Without a Configuration Language
When adding a new capability to DeepSeek Harness (DSH), your instinct might be to open a config file, find a toggle, and change a parameter. But that's not how it works — DSH has no standalone configuration language at all.
What an Agent can do depends on exactly one thing: which plugin rows you've composed for it. Break it down, and DSH is fundamentally a Coreless (kernel-free) application. All capabilities are built on the same "empty root," layered together through three levels of composition:
- Profile sets the foundation
- Bundle packages a set of plugin rows
- Patch is your override layer
This big picture is the key to understanding DSH's composition model. Let's unpack the layering logic level by level.
The Empty Root Design: Why Coreless.iml Is Empty
Open DSH's Profile directory and you'll find a file called Coreless.iml containing exactly one line — a pair of square brackets, an empty array.
Most people's first reaction is: did someone wipe the config? No. This empty root is intentional. The plugin tree in DSH isn't written into this file — it's built up layer by layer through Patches.
Coreless.iml exists to prove one thing: there's nothing here, and everything starts from zero. That's why the official comments in the file say: if you want to change capabilities, edit Coreless.patch.iml, not this file.
Why? If you write your own rows directly into the empty root, your changes become entangled with the Bundle's Patch layer. The next time you upgrade or switch Profiles, those changes become orphaned — unclaimed by anyone. The correct approach is: keep the root empty, and write what you want into your own layer. This is the first principle of the composition model — the root stays unchanged; layers do the stacking.
This "empty root + layered overrides" approach maps to a well-known concept in software engineering: Layered Configuration, similar to Docker's layered filesystem or CSS cascade rules. Each layer only records "what differs from the layer below," and the final result is a snapshot of all layers merged in order. The core advantage of this design is change isolation: official upgrades only touch the bottom layers, user changes only exist in the top layer, with no physical overlap between them — merge conflicts are eliminated at the source. Compare this to the traditional "single config file" model, where everyone writes to the same file, upgrades frequently cause conflicts, and user changes are hard to trace back. DSH's choice of an empty root rather than pre-filled defaults deliberately forces all meaningful configuration to exist as explicit Patches, making each layer's responsibilities directly visible in the filesystem.
Profile and Bundle: Coarse-Grained Capability Slices
The official documentation gives a precise definition of Profile: a Profile is an ordered stack of plugin Bundle Patch layers, sitting beneath the user's own override layer.
In plain terms, a Profile is a coarse-grained slice of the launcher. It determines three things:
- Which Bundles to use as the foundation
- The order in which those Bundles are layered
- Where your override layer sits
All of this is written in the package.json inside the Profile directory. Take a local Web Profile as an example — it currently has three Bundles attached: two official ones (DSH-Base and DSH-WebApp) and one community plugin (DS-Market).

Note the word "ordered" — the order isn't decorative. It determines which Patch layer comes first and which comes last, and therefore determines the final merged result.
So what is a Bundle? One sentence: a Bundle is a packaged Patch layer for a set of plugins. A Bundle is an NPM package that ships with its own Coreless.patch.iml containing annotated plugin rows and their default configurations.
The Patch file bundled with each Bundle is the best learning material available — it explains each row line by line, and is more authoritative than any public documentation because it stays in sync with the version. DSH-Base manages core runtime capabilities; DSH-WebApp manages the browser interface layer.
Bundle resolution order also matters: DSH first looks for built-in Bundles from the DSH install location, then looks in the Profile's own node_modules. The latter is the entry point for third-party and custom plugins. To bring in any NPM package, use the dsh plugin command — it essentially forwards to pnpm, installs the package into the Profile's node_modules, and adds its name to the Bundles list.
The Patch Layering Mechanism: Later Writes Override Earlier Writes
This is the most critical mechanism in DSH's composition model. The full layering order is:
- Each Bundle's own Patch (in Bundles list order)
- Your Profile-level
Coreless.patch.iml - Home-level Patch
- Command-line Patch overrides
There is only one rule: later writes override earlier writes. The further back a layer is, the more it can override the same row written by earlier layers.

But "override" is the word most likely to be misunderstood. DSH's Patch is not a deep merge — it doesn't let you change one field while leaving the others untouched. It's a wholesale replacement. So a row whose semantics are shared across multiple Bundles is written only once in a Bundle layer and once in the user layer — not duplicated across every layer.
This is the most counterintuitive — and most important — rule in the composition model: changing a capability means changing the entire row, not a single field.
"Wholesale replacement" rather than "field-level merging" stands in sharp contrast to mainstream configuration systems like Kubernetes' Strategic Merge Patch or JSON Merge Patch. JSON Merge Patch (RFC 7396) allows you to pass only the fields you want to change, leaving unmentioned fields at their original values. DSH's row-level Patch, by contrast, is atomic replacement — you take the whole row and swap in a new one. The benefit of this design is semantic clarity and no ambiguity: the final state of a row is always determined solely by "the last layer that wrote it," eliminating hard-to-debug hybrid states like "field A comes from Bundle1, field B from Bundle2, field C from the user layer." The tradeoff is: even if you only want to tweak one parameter in a row, you must copy the entire row and modify it, which is more verbose. Understanding this tradeoff helps you avoid the classic mistake of "thinking you only changed one field, but actually cleared all the others."
Lazy Activation: Row Order Carries No Loading Semantics
Many people find their config changes don't take effect, and this is why. Open the DSH-Base Patch file, and the very first comment reads: "row order carries no loading semantics."
What does that mean? Plugins are not loaded in the order you write them in the file. Coreless activation is driven by service availability:
- Row A declares "I need a certain service"
- Row B provides that service
So B is activated first, and A follows. Whoever depends on whom, the dependency gets stood up first. The order in the file is just a manifest — not an execution sequence.
This mechanism also enforces one iron rule that trips up many Preset authors: any row that publishes a service must be wrapped in a domain called Isolate.
Why? Without isolation, the service gets mounted onto the process global scope. The first mount is fine, but the second time the same service name appears, there's a collision. So "rows that provide services" and "rows that consume them" must live in the same domain; while "rows that only consume global services" (such as those calling toolboxes or task systems) must remain outside the domain.
Understand lazy activation, and you understand half of DSH's architecture.
"Activation driven by service availability" is essentially a runtime implementation of Dependency Injection (DI) and Inversion of Control (IoC). Traditional scripts execute line by line, requiring the caller to ensure that depended-on modules are already loaded earlier in the file. DSH's Coreless runtime takes on the responsibility of dependency resolution — before activating any row, it scans the entire plugin tree's service declarations and consumption relationships, builds a directed dependency graph, and drives activation in topological order. This is conceptually very similar to systemd's Wants= / After= unit dependencies, or Spring IoC container Bean initialization ordering. The requirement for "Isolate domain" corresponds to namespace isolation within the process: the same service name in different Isolates refers to different instances, resolving service name conflicts when multiple plugin units run concurrently — analogous to each microservice instance exclusively owning its own port binding.
A Practical Walkthrough of the Three Core Files
Back to the three real files, line by line.

First: package.json. It does two things — declares external plugin dependencies (dependencies is currently empty), and lists the ordered bundles array in the Profile Manifest (three Bundles: DSH-Base, DSH-WebApp, DS-Market). This is the entire Profile's recipe. To adjust the foundation layer, change this array.
Second: Coreless.iml (the empty root). Nothing is written here.
Third: Coreless.patch.iml. This is your domain. It's the top-level array where each entry is a Patch item: you can target a specific row by ID to override its config, disable a row, insert new rows, or even write JS expressions. To enable a capability for your Agent, add a row here. Remember the rule: edit this file, not Coreless.iml.
Dynamic Plugins: Temporary In-Process Mounting
Finally, let's walk through a dynamic flow — opening a Coreless Preset session. The official note reads: treat the session like shell permissions.

The flow is a minimal closed loop:
coreless.definedefines a plugin (an apply object), registers a tool calledhaloEchovia harness, returns a PluginID and PackageIDcoreless.runactivates it, returns a PluginUnit with status Active- Call
haloEchodirectly with a message; it echoes back the same content coreless.undefinecleans it up
The three-level semantics here are important to internalize: Plugin is the stable identity, Package is the immutable code version, PluginUnit is each individual activation.
No files were touched throughout. Dynamic plugins are temporary in-process mounts — end the session or restart the process and they're gone. This is a separate path from static composition: static rows are written into Profile files; dynamic plugins live in runtime memory.
The three-level semantics of dynamic plugins (Plugin / Package / PluginUnit) map precisely to the software engineering concepts of class, immutable versioned artifact, and instance: Plugin is the stable identifier of a class, Package is an immutable artifact produced by a particular compilation/packaging run, and PluginUnit is the concrete instance allocated at runtime. This layered design allows the same Plugin to have multiple active Package versions simultaneously (for canary deployment / hot-update scenarios), and to run multiple concurrent PluginUnits under the same Package (for multi-tenant scenarios). The "temporary in-process" nature of dynamic mounting means it inherently has fault isolation properties: if a dynamic plugin crashes or misbehaves, a simple coreless.undefine cleans it up without affecting the static configuration layers written to files — restart the process and everything is restored. This makes dynamic plugins the ideal mechanism for rapidly experimenting with new capabilities without restarting the Agent.
Summary: Changing Capabilities Means Changing Plugin Composition
Returning to the big picture from the beginning — everything in DSH is layered on top of an empty root:
- Profile sets the foundation; Bundle packages plugin rows; Patch is the override layer
- Later writes override earlier writes; one Patch replaces the entire row
- Row order carries no loading semantics; activation is service-driven
- Static composition writes to files; dynamic plugins live in memory
So remember this: in DSH, changing capabilities means changing composition.
This "coreless + layered composition" design elevates Agent capability configuration from "changing parameters" to "changing composition." It ensures that user changes aren't polluted during upgrades, and that third-party plugin integration stays clean. Understanding it is the first step to mastering DSH.
Related articles

Vercel AI SDK Releases Vue 3.0.282 Patch Update
Vercel AI SDK releases @ai-sdk/vue@3.0.282 patch update, syncing with core package ai@6.0.282. Learn about the changes, release cadence, and upgrade recommendations.

Vercel AI SDK Sandbox Component Receives Patch Update
Vercel AI SDK releases sandbox-vercel@1.0.109 patch update, syncing the harness dependency to the same version. A look at this maintenance release and what it means for AI app developers.

Vercel AI SDK Vue 4.0.99 Released: Dependency Update Overview
The @ai-sdk/vue 4.0.99 patch release syncs the underlying ai@7.0.99 dependency. Learn what this means for Vue developers building AI apps with Vercel AI SDK.