Skip to content

Plugins

A team-root plugin.ts extends the runtime with code — custom tools, and the executor actions that back gated ones. Every agent in the tree inherits it, though each agent’s own tools.json still gates who can actually call what it exposes.

import { definePlugin } from '@runravel/ravel';
import { z } from 'zod';
export default definePlugin({
name: 'scribe',
env: ['NOTES_API_KEY'],
tools: [
{
name: 'note_append',
description: 'Append a line to the team scratchpad.',
schema: z.object({ text: z.string() }),
handler: async (input, ctx) => {
await ctx.memory.append('team', 'scratchpad', input.text);
return { ok: true };
},
},
{
name: 'publish_note',
description: 'Publish the scratchpad externally. Irreversible.',
schema: z.object({ noteId: z.string() }),
handler: async () => ({ status: 'proposed' }),
},
],
actions: {
publish_note: async (input, ctx) => {
// the real, approved side effect — runs deterministically once a
// human approves the "publish_note" proposal, no extra model call.
},
},
});
  • tools become an in-process MCP server (named plugin) that agents can call, subject to the policy set in their own tools.json.
  • actions register on the executor. A tool with policy: "ask" must have a same-named action — otherwise an approved proposal has nothing to actually run.

Every tool handler receives a context object:

Field What it gives you
memory Read/write access to agent, team, and org memory scopes
teamScope The team this plugin is running for
nodeId The calling agent’s path in the org tree
cwd The team’s working directory
env Resolved values for the env vars this plugin declared

Declare the environment variable names your plugin’s tools need in the env array on definePlugin. The runtime resolves them from the calling agent’s .env chain and makes them available on ctx.env — the plugin never has to reach into process.env directly.

A plugin loads once per ravel serve process, inherited by the nearest ancestor’s declaration down the tree. Changing plugin code requires restarting the server — ravel watch’s hot-reload covers agent.md / tools.json / processes, not plugin code.