Building a Custom Tool for DeepSeek Harness, from Hello World to Installable Bundle
Harness gives every tool the same execution pipeline regardless of origin, so custom tools, MCP servers, and built-ins all hit the same pre-execute hooks for permissions and approval. That uniformity removes a whole category of integration surprises when mixing tool sources in a single agent.
A new walkthrough takes a DeepSeek Harness plugin from a minimal console-logging module to a model-callable tool with configurable parameters, external resource management, and a distributable bundle. The framework's Cordis runtime calls `apply` at load time, passing a context object that automatically cleans up registrations on unload. Tools defined with `defineTool` go through a waterfall pipeline—pre-execute, execute, post-execute—that permission policies and approval mechanisms can intercept, the same pipeline used by MCP-bridged tools.
Configuration is handled by exporting a Schema alongside the plugin; invalid config fails loudly at load time rather than producing silent runtime bugs. Hot module replacement recycles the entire plugin fiber when `cordis.yml` changes, so config edits take effect without a process restart. External resources like database connection pools are managed through `ctx.effect()`, whose cleanup function runs automatically on dispose, dependency loss, or shutdown.
Packaging turns a plugin into an installable bundle with a `package.json` that declares `dsh.bundle`, a patch file, and a compiled entry point. Bundles install into named profiles and load in a defined order, with later layers winning on conflict. The walkthrough also covers service isolation—multiple agent groups can each get their own `ctx.shell` instance with separate timeout configs—and the three plugin forms: function, object, and class-based service providers.
Harness treats tool registration as a resource with a lifecycle—the disposer returned by `ctx.tools.register()` means tools appear and disappear cleanly when plugins hot-reload, which avoids stale tool listings that plague many agent frameworks.
Exporting a Schema alongside the plugin interface is a design choice that moves validation to load time. A misconfigured plugin fails immediately with a clear error rather than running with wrong defaults, which shifts debugging left by minutes or hours in production.
The execution pipeline is identical for native tools and MCP-bridged tools. That means a permission policy written for one tool source automatically applies to the other, eliminating the need for parallel security logic.
Service isolation through `isolate` in the YAML config means a single Harness process can host multiple agents with conflicting requirements—one with a 5-second shell timeout, another with 60 seconds—without them stepping on each other.