Skip to main content
There are two good ways to author plugins in redop.

1. Return a Redop instance directly

Use this when you want the least ceremony.
const tenantPlugin = (opts: { header?: string }) =>
  middleware(async ({ request, ctx, next }) => {
    ctx.tenantId = request.headers[opts.header ?? "x-tenant-id"] ?? "public";
    return next();
  });

2. Use definePlugin(...)

Use this when you want metadata and a reusable package-friendly shape.
const notesPlugin = definePlugin({
  name: "notes-plugin",
  version: "0.1.0",
  description: "Bundle namespaced note tools",
  setup: ({ namespace = "notes" }) =>
    new Redop().group(namespace, (notes) =>
      notes.tool("list", {
        handler: () => ({ notes: [] }),
      })
    ),
});

Plugin authoring guidelines

  • accept a single options object
  • prefer request for transport data
  • prefer ctx for mutable shared state
  • use group(...) when you expose public tools
  • keep auth and control flow in middleware
  • keep generic observability in global hooks

Best example in this repo

See Plugin example for auth metadata, tenancy, rate limiting, and namespaced tools working together.