Files
deepseek-harness/docs/cordis-tutorial/index.md
T
Yichen Jiang 0a2ac90617 docs: fix reference sidebar ordering and group the subsystem pages
The VitePress config declared no position for the subsystem or other-interface
sections, so `indexOf` returned -1 and sorted them ahead of every declared
group: the reference landing page's own sidebar entry sat 1549px below the
fold. Four subsystem pages also shared `order` values with pages in the same
section, resolved only by sort stability and array concatenation order.

Section placement and collapse move into the manifest as a per-locale
declaration, and `sectionSpec` throws for an undeclared section instead of
sorting it silently to the top. Subsystem pages are grouped by concern, the
six topical groups collapse until one holds the page being read, and page
order derives from array position.

The projector drops the language-switcher line and repository badge the
canonical pages carry for their GitHub readers. The navigation bar gains the
DeepSeek wordmark, a release-stage tag, and a favicon; the sidebar scrollbar
rests invisible and appears while scrolling. Subsystem pages carry a two-level
outline, and the two plugin-development tracks now cross-link.
2026-08-12 13:52:27 +08:00

4.2 KiB

Cordis tutorial

English | 中文

Cordis is the plugin framework underneath the DeepSeek Harness SDK: a small runtime where every capability — tools, LLM adapters, file access, the agent loop itself — is a plugin mounted into a shared context. This tutorial teaches Cordis hands-on: each chapter is a runnable example you build in a scratch directory inside this repository, ending with a plugin wired into real harness services.

The audience is agent developers. You do not need deep TypeScript experience; the TypeScript notes below explain the syntax that may be unfamiliar, and every chapter shows the exact commands and expected output.

If you want the condensed concept reference instead of a walkthrough, read the Cordis primer. The exhaustive API reference lives in the generated cordis-surface regions on the subsystem pages and the Cordis core API pages.

To write plugins for the harness itself — loaded from a cordis.yml and driven from the Web UI rather than the launcher below — start from your first Harness plugin.

Setup

You need a clone of this repository with dependencies installed; the development guide lists the prerequisites. No API key is needed for this tutorial; every example runs keylessly.

git clone https://github.com/deepseek-ai/deepseek-harness.git
cd deepseek-harness
pnpm install

Create the scratch directory the chapters work in. tmp/ is gitignored, so nothing you write there touches version control:

mkdir -p tmp/cordis-tutorial
cd tmp/cordis-tutorial

Every chapter runs the same command from this directory:

node --import tsx ../../vendor/cordis/bin.js

That one-file launcher (see vendor/cordis/bin.js) creates a root Context, mounts the Loader plugin, and tells it to load ./cordis.yml from the current directory. Everything else — which plugins exist, how they are configured — comes from that YAML file, which you will write in a moment. The --import tsx flag lets Node run the TypeScript files the config points at without a build step.

Chapters

  1. Your first plugin — a plugin is a function; the loader mounts it.
  2. Lifecycle and effects — Cordis-managed registrations are undone when their plugin unloads.
  3. Services — expose a capability on ctx and depend on it with inject.
  4. Events — typed events, broadcast dispatch, and the waterfall short-circuit.
  5. Configuration — validated config from cordis.yml, failing loud on bad input.
  6. Composition and HMR — the config file as a plugin tree, hot reload, and diagnosing a plugin that never loads.
  7. Into the harness — register a model-callable tool against real harness services.

TypeScript notes

The examples use three TypeScript features beyond ordinary modern JavaScript:

  • Type annotations describe values without changing runtime behavior: ctx: Context says that ctx has the Cordis context API, who: string accepts text, and string[] means an array of strings.
  • import type { Context } from '@deepseek-ai/cordis' imports only type information. It vanishes at runtime, so a plugin file that needs Context solely for annotations adds no runtime dependency.
  • Declaration merging (declare module '@deepseek-ai/cordis' { ... }) adds your entries to interfaces that Cordis already declares — for example the type of a new ctx.greeter property or event name. It generates no runtime wiring; the plugin separately provides the service or emits the event. Chapter 3 shows the pattern in full.

Chapter 5 also uses an interface to describe a configuration object's fields and a generic type such as Schema<Config> to say which object fields a schema validates. You can copy those declarations as shown; the surrounding text explains what each one connects.