Skip to main content

Documentation Index

Fetch the complete documentation index at: https://redop.useagents.site/docs/llms.txt

Use this file to discover all available pages before exploring further.

Use middleware when you need to wrap execution for a request. Use a plugin when you want to bundle middleware, hooks, tools, resources, or prompts into one reusable unit. If the behavior is analytics, logging, or metrics that should happen after the response is already written, prefer onAfterResponse(...) inside the plugin over onAfterHandle(...).

Build middleware first when the behavior is request-scoped

Middleware is the fastest path when you want to:
  • block or allow execution
  • decorate ctx
  • time calls
  • wrap next()
import { middleware, Redop } from "@redopjs/redop";

const requestIdPrefix = middleware(async ({ ctx, next }) => {
  (ctx as Record<string, unknown>).shortRequestId = ctx.requestId.slice(0, 8);
  return next();
});

new Redop({ serverInfo: { name: "middleware-demo" } })
  .middleware(requestIdPrefix)
  .tool("hello", {
    handler: ({ ctx }) => ({
      requestId: ctx.requestId,
      shortRequestId: (ctx as Record<string, unknown>).shortRequestId,
    }),
  });

Build a plugin when you want a reusable package of behavior

definePlugin(...) is the cleanest path when you want to share behavior across multiple servers.
import { definePlugin, Redop } from "@redopjs/redop";

const timingPlugin = definePlugin({
  name: "timing",
  version: "0.1.0",
  description: "Measure tool duration",
  setup() {
    return new Redop()
      .onBeforeHandle(({ ctx }) => {
        (ctx as Record<string, unknown>).startedAt = performance.now();
      })
      .onAfterHandle(({ ctx, tool }) => {
        const startedAt = (ctx as Record<string, unknown>).startedAt as number | undefined;
        if (startedAt == null) return;

        const ms = +(performance.now() - startedAt).toFixed(2);
        console.log(`[timing] ${tool} finished in ${ms}ms`);
      });
  },
});

new Redop({ serverInfo: { name: "plugin-demo" } }).use(timingPlugin({}));

A plugin can ship more than middleware

A plugin can register:
  • middleware
  • hooks
  • tools
  • resources
  • prompts
import { definePlugin, Redop } from "@redopjs/redop";

const healthPlugin = definePlugin({
  name: "health",
  version: "0.1.0",
  setup() {
    return new Redop().tool("health", {
      description: "Return service health",
      handler: () => ({ ok: true, ts: Date.now() }),
    });
  },
});

Rule of thumb

  • choose middleware for one request-layer behavior
  • choose a plugin when you want a reusable bundle
  • use definePlugin(...) when you want a stable, publishable plugin API

See also