Plugin SDK

Build custom plugins with workflows, channels, and capability handlers.

Plugin Manifest

Every plugin is a directory containing a manifest.json that declares its metadata, capabilities, and entry points:

json
{
  "name": "my-plugin",
  "version": "1.0.0",
  "description": "A custom Franklin plugin",
  "capabilities": ["my-tool"],
  "entry": "./index.js",
  "workflows": ["./workflows/default.json"],
  "channels": ["./channels/slack.js"]
}

Core Interfaces

Plugin

The top-level interface. A plugin registers one or more capability handlers that the agent can invoke as tools.

typescript
interface Plugin {
  name: string;
  version: string;
  capabilities: CapabilityHandler[];
  onLoad?(): Promise<void>;
  onUnload?(): Promise<void>;
}

CapabilityHandler

Each capability is a tool the agent can call. It defines a name, description, input schema, and an execute function.

typescript
interface CapabilityHandler {
  name: string;
  description: string;
  inputSchema: JSONSchema;
  execute(input: unknown): Promise<ToolResult>;
}

Workflow

Workflows define multi-step sequences that chain capabilities together. They are declared as JSON files in the plugin's workflows/ directory.

json
{
  "name": "deploy",
  "steps": [
    { "capability": "build", "input": { "target": "production" } },
    { "capability": "test", "input": { "suite": "smoke" } },
    { "capability": "publish", "input": { "registry": "npm" } }
  ]
}

Channel

Channels let plugins send and receive messages through external services (Slack, Discord, webhooks, etc.).

typescript
interface Channel {
  name: string;
  send(message: string): Promise<void>;
  onMessage(callback: (msg: string) => void): void;
}

Discovery Order

Franklin loads plugins in a specific order. Later sources override earlier ones if they declare the same capability name:

  1. Dev plugins .franklin/plugins/ in the current project directory. Highest priority, used during plugin development.
  2. User plugins ~/.blockrun/plugins/. Your personal plugins, available in every project.
  3. Bundled plugins— shipped with Franklin. Lowest priority, always available as fallbacks.

Dev plugins for rapid iteration

During development, place your plugin in .franklin/plugins/ inside your project. Franklin hot-reloads dev plugins on every agent turn, so you can iterate without restarting.

Building a Custom Plugin

Create a plugin that adds a hello tool:

bash
mkdir -p .franklin/plugins/hello-plugin
cd .franklin/plugins/hello-plugin

Create manifest.json:

json
{
  "name": "hello-plugin",
  "version": "1.0.0",
  "description": "Greets the user",
  "capabilities": ["hello"],
  "entry": "./index.js"
}

Create index.js:

javascript
module.exports = {
  name: "hello-plugin",
  version: "1.0.0",
  capabilities: [
    {
      name: "hello",
      description: "Say hello to someone",
      inputSchema: {
        type: "object",
        properties: {
          name: { type: "string", description: "Name to greet" }
        },
        required: ["name"]
      },
      async execute(input) {
        return { content: `Hello, ${input.name}!` };
      }
    }
  ]
};

Now start Franklin in the project directory. The agent will have access to the hello tool automatically.