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:
{
"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.
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.
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.
{
"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.).
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:
- Dev plugins —
.franklin/plugins/in the current project directory. Highest priority, used during plugin development. - User plugins —
~/.blockrun/plugins/. Your personal plugins, available in every project. - Bundled plugins— shipped with Franklin. Lowest priority, always available as fallbacks.
Dev plugins for rapid iteration
.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:
mkdir -p .franklin/plugins/hello-plugin
cd .franklin/plugins/hello-pluginCreate manifest.json:
{
"name": "hello-plugin",
"version": "1.0.0",
"description": "Greets the user",
"capabilities": ["hello"],
"entry": "./index.js"
}Create index.js:
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.