KB LabsDocs
KB Labs/Guides/Plugin System

Plugin System

Plugins are the execution units of KB Labs. Every workflow step calls a plugin handler. Plugins are isolated, versioned, and independently deployable.

Architecture

Workflow step
    ↓
Plugin manifest (declares handlers, permissions)
    ↓
Execution backend (in-process / subprocess / worker-pool)
    ↓
Handler function (your TypeScript code)

The execution backend is pluggable. In development you typically run in-process. In production you can run handlers in isolated subprocesses or worker threads.

Plugin structure

my-plugin/
├── manifest.json       # Plugin metadata and handler registry
├── src/
│   ├── index.ts        # Handler exports
│   └── handlers/
│       └── my-handler.ts
├── package.json
└── tsconfig.json

manifest.json

{
  "name": "@my-org/my-plugin",
  "version": "1.0.0",
  "handlers": {
    "my-handler": {
      "entry": "./dist/handlers/my-handler.js",
      "description": "Does something useful"
    }
  },
  "permissions": {
    "network": false,
    "fs": ["read"]
  }
}

The permissions block is used when running in sandboxed mode. It's ignored in in-process mode.

Writing a handler

import type { HandlerContext } from '@kb-labs/sdk';

type Input = {
  url: string;
};

type Output = {
  status: number;
  body: string;
};

export async function handler(input: Input, ctx: HandlerContext): Promise<Output> {
  const res = await fetch(input.url);
  const body = await res.text();

  ctx.logger.info(`Fetched ${input.url} → ${res.status}`);

  return { status: res.status, body };
}

HandlerContext API

| Property | Type | Description | |----------|------|-------------| | logger | Logger | Structured logger scoped to the step | | cache | ICache \| null | Platform cache (in-memory or Redis) | | state | IStateClient | State Broker client | | runId | string | Current workflow run ID | | stepId | string | Current step ID |

Build and register

# Build the plugin
pnpm --filter my-plugin build

# Register with KB Labs CLI
kb plugins register ./my-plugin

# Clear discovery cache (required after every build!)
kb plugins clear-cache

Always run kb plugins clear-cache after building a plugin. The CLI caches plugin manifests for performance. Stale cache = stale commands.

Execution modes

| Mode | Use case | Isolation | |------|----------|-----------| | in-process | Development, low-latency | None | | subprocess | Production, untrusted code | Process boundary | | worker-pool | High-throughput, CPU-bound | Thread boundary |

Configure in kb.config.json:

{
  "execution": {
    "mode": "subprocess"
  }
}