Plugins
Plugins are how OpenVesper interacts with the outside world. They wrap APIs, expose tools, and ship with TypeScript types. Every external capability โ querying a price, sending a Telegram message, reading a file โ lives in a plugin.
Anatomy of a plugin
Each plugin is a workspace package:
packages/plugins/weather/
โโโ package.json Name, version, dependencies
โโโ tsconfig.json TypeScript config
โโโ src/
โ โโโ index.ts Plugin definition
โโโ README.md Usage and examples (optional)Minimal plugin
Here's a complete plugin with a single tool, in about 25 lines:
// packages/plugins/weather/src/index.ts
import axios from "axios";
import { definePlugin, defineTool, inputSchema } from "@openvesper/plugin-sdk";
async function getWeather(location: string) {
// Open-Meteo is free, no API key required
const r = await axios.get("https://api.open-meteo.com/v1/forecast", {
params: { latitude: 52.52, longitude: 13.41, current_weather: true },
});
return {
success: true,
data: { location, ...r.data.current_weather },
};
}
export default definePlugin({
name: "weather",
version: "1.0.0",
description: "Current weather and forecast for any location",
tools: [
defineTool({
name: "get_weather",
description: "Get current weather for a location",
inputSchema: inputSchema({
location: { type: "string", description: "City name" },
}, ["location"]),
handler: async (input) => getWeather(input.location as string),
category: "lifestyle",
permission: "external", // calls an external API
}),
],
});Plugin SDK reference
definePlugin(spec)
Top-level plugin definition. Returns the plugin so it can be loaded.
definePlugin({
name: string; // Unique plugin name
version: string; // semver
description: string; // One-line summary
tools: Tool[]; // Array of tools this plugin exposes
agents?: Agent[]; // Optional: agents shipped with this plugin
})defineTool(spec)
Define a single callable tool.
defineTool({
name: string; // Tool name, snake_case
description: string; // Shown to the LLM โ make it clear
inputSchema: object; // JSON Schema for input validation
handler: async (input) => ToolResult;
category: ToolCategory; // "crypto" | "research" | "lifestyle" | ...
permission?: Permission; // "external" | "filesystem" | "shell" | undefined
})inputSchema(props, required)
Helper to build a JSON Schema. Less verbose than writing JSON by hand.
inputSchema(
{
symbol: { type: "string", description: "Ticker, e.g. BTC" },
interval: { type: "string", description: "5m, 15m, 1h, 4h, 1d" },
},
["symbol"] // required fields
)ToolResult shape
Every tool returns the same shape so the runtime can handle it uniformly:
type ToolResult =
| { success: true; data: unknown }
| { success: false; error: string };The 47 shipped plugins
Plugins are grouped into 12 categories. Click any category for the full list at /integrations.
| Category | Plugins |
|---|---|
| Crypto core | crypto, derivatives, defi, whale, onchain, security |
| Solana | solana, solana-dev, bagsfm, memescan, base-meme |
| Trading data | strategies, macro, airdrop, nft, tracking |
| Comms | telegram, slack, discord, email |
| Productivity | calendar, notes, tracking, code |
| Research | research, news, twitter, youtube, books |
| System | filesystem, shell, code, browser, dns |
| Data | database, banking, ecommerce |
| Media | music, movies, voice, translate, imagegen |
| Smart home | smarthome, weather, maps |
| Misc | tracking, smarthome, sports, gaming |
Tool permissions
The permission field signals what the tool needs at runtime. The agent runtime uses this for confirmation prompts in interactive sessions and for audit logs.
| Permission | Meaning |
|---|---|
external | Calls an external HTTP API (CoinGecko, GitHub, etc.) |
filesystem | Reads or writes local files |
shell | Executes shell commands |
network | Opens arbitrary network connections |
mutation | Performs side-effects (transfer, post, send) |
Tools without a permission flag are assumed to be pure / read-only. Mutating tools (sending messages, transferring funds, modifying files) must declare one. See Sandboxing for details.
Writing your first plugin
1. Scaffold the directory
mkdir packages/plugins/myplugin
cd packages/plugins/myplugin2. Create package.json
{
"name": "@openvesper/plugin-myplugin",
"version": "1.0.0",
"type": "module",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"scripts": {
"build": "tsc"
},
"dependencies": {
"@openvesper/plugin-sdk": "workspace:*",
"axios": "^1.7.7"
}
}3. Create tsconfig.json
{
"extends": "../../../tsconfig.base.json",
"compilerOptions": {
"outDir": "dist",
"rootDir": "src"
},
"include": ["src"]
}4. Write your plugin
See the minimal plugin example at the top of this page.
5. Install and build
# From repo root
pnpm install
pnpm --filter @openvesper/plugin-myplugin build6. Register the plugin
Add the plugin to apps/cli/src/index.ts (or whichever app should expose it):
import myplugin from "@openvesper/plugin-myplugin";
// In the runtime setup:
runtime.use(myplugin);Design principles
Read-only by default
Most OpenVesper plugins are read-only. They fetch data from public APIs and return it. Mutating operations (sending, transferring, posting) are clearly marked and require explicit permission flags.
No key management
Plugins read credentials from environment variables only. They never write keys to disk, never transmit them to OpenVesper servers (there are no OpenVesper servers), and never log them. See Security.
Errors over exceptions
Tool handlers return { success: false, error: "..." } instead of throwing. This makes the runtime simpler and forces explicit error messaging that's helpful to the LLM.
What's next?
- Agents โ how agents reference plugins
- Skills โ modular instructions agents pull in
- All 47 plugins โ browse the catalogue