Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

17.4 Plugin Development: tool / llm / skill / subagent

🐋 "Add a capability = write a plugin, not touch the core."


Four Plugin Types

TypeMount pointPurpose
toolctx.toolsadd a tool
llmctx.llmadd a model
skillctx.skillRegistryadd a SKILL.md workflow
subagentctx.subagentadd a sub-agent type

Four plugin interfaces


Writing a Tool Plugin

import { Context } from 'cordis';
import { z } from 'zod';

export function weatherPlugin(ctx: Context, config: { apiKey: string }) {
  ctx.tools.register('weather', {
    name: 'weather',
    description: 'Query current weather for a city.',
    schema: z.object({ city: z.string().describe('city name, e.g. "Shanghai"') }),
    async run(args: { city: string }) {
      const res = await fetch(`https://api.openweathermap.org/data/2.5/weather?q=${args.city}&appid=${config.apiKey}`);
      const data = await res.json();
      return `City ${data.name}: ${data.weather[0].description}, ${Math.round(data.main.temp - 273.15)}°C`;
    },
  });
}

Three essentials: schema (zod, strong-typed), description (read by the LLM), run (async).

Writing an LLM Plugin

export function myLlmPlugin(ctx: Context, config: { endpoint: string; apiKey: string }) {
  ctx.llm.register('my-llm', {
    async stream(messages, opts) { /* fetch + read SSE */ },
    async complete(messages, opts) { /* non-streaming */ },
  });
}

Set llm.provider: "my-llm" in config — the Agent loop code changes zero.

Writing a Skill Plugin

ctx.skillRegistry.register({
  name: 'code-review',
  description: 'Multi-dimensional code review',
  skillFile: './skills/code-review/SKILL.md',
});

Because it's Anthropic SKILL.md-compatible, you can reuse community skills from Claude Code / OpenClaw.

Writing a Subagent Plugin

ctx.subagent.register('research', {
  description: 'Research a topic independently, return a structured summary.',
  async run(prompt: string) {
    const sub = ctx.spawn({ isolate: true });
    return await sub.run(prompt);
  },
});

The main Agent dispatches it via the Task tool; the sub-agent runs in an isolated context.

Plugin Dependencies

ctx.plugin(weatherPlugin, { apiKey: 'xxx', before: ['core.llm'], after: ['core.kernel'] });

Explicit dependency graph → correct load order + early missing-dependency errors (see 17.3).

The create Profile Loop

dsh --profile create dev   # watches ./plugins/**, hot-reloads in ~200ms

Edit → save → live, no restart.


Section Summary

TopicKey point
4 typestool / llm / skill / subagent
tool essentialsschema + description + run
llm pluginllm.provider switch, zero loop change
skill pluginreuse Anthropic SKILL.md
dependenciesbefore/after explicit ordering

Next section: 17.5 Comparison: DSH vs Claude Code / OpenClaw / Hermes