$dshubuser@dshub:~/plugins$
  • Plugins
  • Submit
  • Blog
Cordis: Five Concepts for Reading a Plugin Tree
2026/08/19

Cordis: Five Concepts for Reading a Plugin Tree

Build the smallest useful mental model of Cordis with Plugin, Context, inject, Events, and Effect.

The short answer: Cordis can be reduced to five ideas: plugins contribute capabilities, Context connects them by name, inject waits for dependencies, events coordinate without direct imports, and Effects reverse side effects.

Put the API names aside for a moment. Cordis answers one runtime question: how does a capability enter a running application, then leave safely when dependencies or code change?

01 / Five concepts, one runtime path

Cordis five concepts connected as a runtime chain from plugin contribution to reversible effects

These are not five unrelated features. They form a path from declaration to teardown:

ConceptQuestion it answersObservable result
PluginWhat does this capability contribute?A function, object, or Service class is mounted
ContextWhere can a plugin find capabilities?Services are resolved by stable names on ctx
injectWhen may the plugin start?It stays PENDING until dependencies exist
EventsHow can unknown consumers cooperate?Dispatch follows a declared mode
EffectWhat happens during unload?Disposers reverse registrations and external resources

02 / A Plugin describes its own contribution

A minimal plugin does not boot the entire application. It exports its contribution:

import type { Context } from '@deepseek-ai/cordis'

export const name = 'hello'

export function apply(ctx: Context) {
  console.log('hello from my first plugin')
}

Loader finds the module and calls apply(ctx). The plugin file can focus on behavior while the composition file decides which behavior enters this run.

Cordis accepts functions, objects with an apply method, and Service subclasses commonly used to expose named capabilities. Each becomes a plugin instance owned by a Fiber.

03 / Context connects named services

Cordis Context resolving named services through a shared root and child scopes

A provider registers a capability under a name. Consumers use entries such as ctx.tools, ctx.llm, or ctx.agents instead of importing a provider class. The composition can therefore replace the implementation.

Context is not an invitation to write arbitrary global state. Cordis Context is a proxy and scope container: property reads resolve services, while extend() and isolate() create child contexts without mutating the parent.

04 / inject turns startup order into dependencies

export const inject = ['greeter']

export function apply(ctx: Context) {
  console.log(ctx.greeter.greet('world'))
}

With inject, the plugin enters apply only after the greeter service exists. Swapping two rows in cordis.yml therefore does not change the result; service readiness determines when the plugin starts.

If the feature can work without a service, do not pretend it is a hard dependency. Probe an optional service at the use site with ctx.get('greeter').

05 / Events hide the listener set

Events fit the case where something happened but the sender should not know every consumer. TypeScript declaration merging adds the event name and payload to Events, then the caller chooses emit, parallel, serial, bail, or waterfall.

A stats service can emit stats/report while a logger listens independently. The dispatch mode is part of the public agreement: it determines waiting, return values, and short-circuit behavior.

06 / Effect makes registration reversible

Cordis Fiber owning event listeners, service registrations, and timers through reversible effects

Cordis does not treat registrations as permanent mutations scattered through the application. ctx.on(), service registration, child-plugin mounting, and explicit ctx.effect() attach cleanup to the current Fiber.

ctx.effect(() => {
  const timer = setInterval(() => console.log('tick'), 200)
  return () => clearInterval(timer)
})

When the plugin unloads, the disposer runs and the timer stops. HMR’s “old code out, new code in” behavior is built on this reversible relationship.

07 / There is no privileged kernel

DeepSeek Harness capabilities arranged as replaceable Cordis plugins without a privileged kernel

Together, these concepts make model adapters, tool registries, sessions, agent management, and even the agent loop replaceable plugins. Adding behavior normally means defining a service, providing an implementation, registering a consumer, or attaching to an existing event—not patching a privileged kernel.

In DeepSeek Harness, a profile chooses composition, Context connects capabilities, Fiber owns instances, and Effects reverse them. “Everything is a plugin” means replacement points and resource ownership stay visible.

Where to go next

  • Your first plugin
  • Services and Context
  • Lifecycle and effects

Implementation references: the Cordis primer, tutorial index, Context, and Events.

All Posts

Author

avatar for DSH Research
DSH Research

Categories

  • Agent Infrastructure
01 / Five concepts, one runtime path02 / A Plugin describes its own contribution03 / Context connects named services04 / inject turns startup order into dependencies05 / Events hide the listener set06 / Effect makes registration reversible07 / There is no privileged kernelWhere to go next

More Posts

Composition and HMR: Import New Code, Dispose the Old Fiber, Then Activate
Agent Infrastructure

Composition and HMR: Import New Code, Dispose the Old Fiber, Then Activate

Understand stable ids, configuration groups, and Cordis HMR’s unload-reload cycle, including how to diagnose plugins stuck in PENDING.

avatar for DSH Research
DSH Research
2026/08/28
Configuration: Give Plugins Validated Options and Defaults
Agent Infrastructure

Configuration: Give Plugins Validated Options and Defaults

Define Cordis plugin configuration with Schemastery and see how defaults, path-aware errors, and FAILED Fibers prevent a sick start.

avatar for DSH Research
DSH Research
2026/08/27
waterfall: Intercept, Wrap, and Short-Circuit with next()
Agent Infrastructure

waterfall: Intercept, Wrap, and Short-Circuit with next()

Follow a Cordis waterfall chain to see listeners delegate downstream, wrap results, or short-circuit when they own the decision.

avatar for DSH Research
DSH Research
2026/08/26

Newsletter

Join the community

Subscribe to our newsletter for the latest news and updates

[dshub] [zsh]$ dshub ls$ dshub submit$ dshub blog
-- NORMAL -- ✓ 2026 dshub