Understand the DSH Plugin Model First
DeepSeek Harness is powered by Cordis and treats product behavior as composable plugins rather than a privileged core plus optional add-ons. A plugin receives a shared Context and contributes services, events, tools, UI behavior, policy, storage, or other capabilities through that context.
The minimal form is deliberately small: export a plugin name and an apply function. If your plugin depends on another service, declare it through inject so Cordis waits for that service before your plugin activates.
import type { Context } from '@deepseek-ai/cordis'
export const name = 'my-dsh-plugin'
export const inject = ['tools']
export function apply(ctx: Context) {
// Register capabilities through ctx here.
}Choose the Capability Your Plugin Owns
The architecture documentation maps new behavior to extension points. A plugin can be much more than a model-facing tool, so choose the seam that matches the behavior instead of forcing every feature through one API.
Model tool
Register a typed tool on ctx.tools.
Model provider
Register an adapter on ctx.llm.
Background work
Use ctx.jobs for durable or scheduled work.
Policy / interception
Listen on tools/*, agent/*, fs/*, or another documented event seam.
UI integration
Render session events or register Web client presentation behavior.
Service provider
Expose a replaceable service that other plugins consume through Context.
Build a Small Model-Facing Tool
A tool is a good first plugin because the contract is visible: define the input schema, return a canonical value, and render that value into model-facing content. DSH validates tool arguments before execute runs and removes the registration when the owning plugin unloads.
import type { Context } from '@deepseek-ai/cordis'
import { defineTool } from '@deepseek-ai/dsh-tools'
export const name = 'project-info'
export const inject = ['tools']
export function apply(ctx: Context) {
ctx.tools.register(defineTool({
name: 'project_info',
description: 'Return a small project summary.',
parameters: {
name: { type: 'string', required: true },
},
output: {
schema: { type: 'string' },
render: (_args, value) => [{ type: 'text', text: value }],
},
async execute(args) {
return 'Project: ' + args.name
},
}))
}For production tools, also design cancellation, structured output, policy hooks, replay-safe UI presentation, and tests around the real execution contract.
Package the Plugin as a DSH Bundle
For profile installation, a package can declare bundle metadata in package.json. The dsh.bundle declaration points to a Cordis patch file, and that patch contributes rows to the profile composition. This keeps the plugin installable while still allowing later profile and user patch layers to override it.
- Ship the patch file in the package files list.
- Expose the runtime entry that the Cordis Loader resolves.
- Declare peer dependencies that match the DSH services your plugin consumes.
- Keep the bundle focused: configuration rows should describe what the package actually mounts.
{
"name": "@example/my-dsh-plugin",
"type": "module",
"dsh": {
"bundle": {
"patch": "./cordis.patch.yml"
}
}
}- insert:
- id: my-dsh-plugin
name: '@example/my-dsh-plugin'Test the Load Path, Not Only the Function
Unit tests can validate your own function, but a plugin is only useful if Harness can resolve it, mount it, satisfy its injected services, and unwind its effects. Test the assembled path in a real DSH composition before publishing.
- Verify the plugin appears in the composed tree.
- Exercise the capability through the surface that will actually use it.
- Test failure and unload paths as well as the happy path.
- Keep your Node and peer dependency ranges aligned with the current Harness developer preview.
pnpm dsh web --patch ./scratch-plugin/cordis.ymldsh --profile web --dump-configPublish and Make the Plugin Discoverable
A community plugin can live outside the official monorepo and depend on the published @deepseek-ai packages it needs. When the package and installation path are stable, publish the repository and package, document the exact profile and install command, and add the dsh-plugin GitHub topic so users and registries can discover it.
- README: what the plugin does, target profile, installation, configuration, limitations, and verification steps.
- package.json: package identity, exports, version, license, engines, dependencies, and dsh.bundle metadata when applicable.
- Repository: dsh-plugin topic, releases or tags, changelog, and issue/support path.
- Verification: a reproducible command that proves the capability is loaded and working.
Primary references
This guide is grounded primarily in the current DeepSeek AI Harness repository and development documentation. Harness is still in developer preview, so exact commands and contracts can change with later releases.