Provider Plugins
Provider plugins extend SimpleClaw with custom LLM providers, memory systems, and specialized tools.Provider Plugin Interface
import type {
SimpleClawPluginService,
SimpleClawPluginServiceContext,
ProviderAuthContext,
ProviderAuthResult,
} from "simpleclaw/plugin-sdk";
export interface SimpleClawPluginService {
id: string;
name?: string;
version?: string;
// Lifecycle
init?(ctx: SimpleClawPluginServiceContext): Promise<void>;
shutdown?(): Promise<void>;
// Authentication
auth?(ctx: ProviderAuthContext): Promise<ProviderAuthResult>;
// Provider methods
invoke?(ctx: any, request: any): Promise<any>;
models?(): Promise<ModelInfo[]>;
// HTTP routes
routes?: PluginRoute[];
}
LLM Provider Example
import type {
SimpleClawPluginService,
SimpleClawPluginServiceContext,
} from "simpleclaw/plugin-sdk";
export const customLLMProvider: SimpleClawPluginService = {
id: "custom-llm",
name: "Custom LLM Provider",
version: "1.0.0",
async init(ctx: SimpleClawPluginServiceContext) {
ctx.logger.info("Initializing Custom LLM provider");
// Load API keys from config
const config = await ctx.config.get("providers.customllm");
this.apiKey = config?.apiKey;
},
async auth(ctx) {
// OAuth flow or API key validation
try {
const response = await fetch("https://api.example.com/auth", {
headers: {
"Authorization": `Bearer ${this.apiKey}`,
},
});
const profile = await response.json();
return {
success: true,
profile: {
id: profile.userId,
name: profile.username,
email: profile.email,
},
};
} catch (error) {
return {
success: false,
error: error.message,
};
}
},
async models() {
return [
{
id: "custom-llm/gpt-ultra",
name: "GPT Ultra",
contextWindow: 200000,
maxOutputTokens: 8192,
},
{
id: "custom-llm/gpt-mini",
name: "GPT Mini",
contextWindow: 128000,
maxOutputTokens: 4096,
},
];
},
async invoke(ctx, request) {
const { messages, model, temperature, maxTokens } = request;
const response = await fetch("https://api.example.com/chat", {
method: "POST",
headers: {
"Authorization": `Bearer ${this.apiKey}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
model,
messages,
temperature,
max_tokens: maxTokens,
}),
});
const data = await response.json();
return {
message: data.choices[0].message,
usage: {
promptTokens: data.usage.prompt_tokens,
completionTokens: data.usage.completion_tokens,
totalTokens: data.usage.total_tokens,
},
};
},
};
Memory Provider Example
import type { SimpleClawPluginService } from "simpleclaw/plugin-sdk";
export const vectorMemoryProvider: SimpleClawPluginService = {
id: "vector-memory",
name: "Vector Memory Store",
async init(ctx) {
// Initialize vector database connection
this.db = await connectToVectorDB(ctx.config.get("providers.vectormemory"));
},
async invoke(ctx, request) {
const { action, params } = request;
switch (action) {
case "store":
return await this.storeMemory(params);
case "search":
return await this.searchMemory(params);
case "recall":
return await this.recallContext(params);
default:
throw new Error(`Unknown action: ${action}`);
}
},
async storeMemory(params) {
const { sessionKey, text, embedding } = params;
await this.db.insert({
sessionKey,
text,
embedding,
timestamp: Date.now(),
});
return { ok: true };
},
async searchMemory(params) {
const { query, limit = 10 } = params;
const results = await this.db.search({
query,
limit,
});
return {
results: results.map(r => ({
text: r.text,
score: r.score,
timestamp: r.timestamp,
})),
};
},
};
Tool Provider Example
import type { SimpleClawPluginService, AnyAgentTool } from "simpleclaw/plugin-sdk";
import { Type } from "@sinclair/typebox";
export const customToolProvider: SimpleClawPluginService = {
id: "custom-tools",
name: "Custom Tool Provider",
async init(ctx) {
// Register custom tools
ctx.registerTools([
{
name: "weather_get",
description: "Get current weather for a location",
input_schema: Type.Object({
location: Type.String({ description: "City name or coordinates" }),
units: Type.Optional(Type.Union([
Type.Literal("celsius"),
Type.Literal("fahrenheit"),
])),
}),
handler: async (input) => {
const response = await fetch(
`https://api.weather.example.com/current?location=${input.location}&units=${input.units || "celsius"}`
);
const data = await response.json();
return {
temperature: data.temp,
conditions: data.conditions,
humidity: data.humidity,
};
},
},
{
name: "calendar_create_event",
description: "Create a calendar event",
input_schema: Type.Object({
title: Type.String(),
start: Type.String({ description: "ISO 8601 datetime" }),
duration: Type.Number({ description: "Duration in minutes" }),
description: Type.Optional(Type.String()),
}),
handler: async (input) => {
const eventId = await createCalendarEvent({
title: input.title,
start: new Date(input.start),
duration: input.duration,
description: input.description,
});
return {
eventId,
url: `https://calendar.example.com/events/${eventId}`,
};
},
},
]);
},
};
HTTP Routes
Providers can expose HTTP endpoints:import type { SimpleClawPluginService } from "simpleclaw/plugin-sdk";
import { registerPluginHttpRoute } from "simpleclaw/plugin-sdk";
export const webhookProvider: SimpleClawPluginService = {
id: "custom-webhooks",
async init(ctx) {
// Register HTTP routes
registerPluginHttpRoute({
pluginId: "custom-webhooks",
method: "POST",
path: "/webhooks/custom",
handler: async (req, res) => {
const body = await req.json();
// Process webhook
await processWebhook(body);
res.json({ ok: true });
},
});
},
};
Configuration
Define provider config schema:import { z } from "zod";
import { emptyPluginConfigSchema } from "simpleclaw/plugin-sdk";
export const CustomLLMConfigSchema = z.object({
apiKey: z.string(),
baseUrl: z.string().url().optional(),
timeout: z.number().default(30000),
retries: z.number().default(3),
});
// Export schema for validation
export const configSchema = {
schema: CustomLLMConfigSchema.shape,
uiHints: {
apiKey: {
label: "API Key",
sensitive: true,
help: "Get your API key from the provider dashboard",
},
timeout: {
label: "Request Timeout (ms)",
advanced: true,
},
},
};
Authentication Flow
Implement OAuth or API key auth:import type {
ProviderAuthContext,
ProviderAuthResult,
} from "simpleclaw/plugin-sdk";
import { buildOauthProviderAuthResult } from "simpleclaw/plugin-sdk";
export async function auth(ctx: ProviderAuthContext): Promise<ProviderAuthResult> {
const { code, redirectUri } = ctx;
// Exchange code for access token
const response = await fetch("https://api.example.com/oauth/token", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
code,
client_id: process.env.CLIENT_ID,
client_secret: process.env.CLIENT_SECRET,
redirect_uri: redirectUri,
grant_type: "authorization_code",
}),
});
const data = await response.json();
// Get user profile
const profileResponse = await fetch("https://api.example.com/user", {
headers: { "Authorization": `Bearer ${data.access_token}` },
});
const profile = await profileResponse.json();
return buildOauthProviderAuthResult({
accessToken: data.access_token,
refreshToken: data.refresh_token,
expiresAt: Date.now() + data.expires_in * 1000,
profile: {
id: profile.id,
name: profile.name,
email: profile.email,
},
});
}
Plugin Packaging
{
"name": "@simpleclaw/provider-custom",
"version": "1.0.0",
"main": "dist/index.js",
"simpleclaw": {
"extensions": [
{
"type": "provider",
"id": "custom-llm",
"entry": "./dist/index.js"
}
]
},
"dependencies": {
"simpleclaw": "^2026.3.0",
"@sinclair/typebox": "^0.32.0"
}
}
Testing
import { describe, test, expect } from "vitest";
import { customLLMProvider } from "./index.js";
describe("Custom LLM provider", () => {
test("authenticates successfully", async () => {
const ctx = createMockAuthContext();
const result = await customLLMProvider.auth(ctx);
expect(result.success).toBe(true);
expect(result.profile).toBeDefined();
});
test("invokes chat completion", async () => {
const ctx = createMockContext();
const response = await customLLMProvider.invoke(ctx, {
model: "custom-llm/gpt-ultra",
messages: [
{ role: "user", content: "Hello!" },
],
});
expect(response.message).toBeDefined();
expect(response.usage.totalTokens).toBeGreaterThan(0);
});
});
Next Steps
Channel Plugins
Build messaging platform integrations
Plugin SDK
Complete SDK reference