Reforma
Adding your integration

Tools

Executable agent tools that run in the Reforma sandbox.

Tools let a plugin expose executable behavior to the agent inside the Reforma sandbox.

Use a tool for operations that are better expressed as code than instructions — for example, running a CLI, inspecting or transforming project files, controlling a preview, or intentionally overriding a built-in tool.

For task-specific instructions, use a skill. For SaaS APIs and authenticated external services, prefer MCP.

Tools are Reforma-specific.

Layout

Put each tool in its own TypeScript file under tools/:

tools/
  KitPing.ts
  Grep.ts

The filename defines the tool name:

KitPing.ts → KitPing
Grep.ts    → Grep

There is no separate name field in the tool definition.

By default, Reforma can namespace plugin tools when exposing them to the model. Set override: true only when the tool is intended to use its bare filename and replace a same-named host tool.

Define a tool

Default-export defineTool from @reforma/plugin-sdk:

import { defineTool, z } from "@reforma/plugin-sdk";

export default defineTool({
  description: "Echo a message from the plugin tool.",
  inputSchema: z.object({
    message: z.string().min(1).describe("Message to echo"),
  }),

  async execute({ message }, ctx) {
    return {
      pong: message,
      toolName: ctx.toolName,
    };
  },
});

z is a Zod re-export from the SDK.

Definition

FieldPurpose
descriptionRequired model-facing description of what the tool does
inputSchemaZod schema for tool input
execute(input, ctx)Runs the tool inside the Reforma sandbox
overrideOptional; expose the bare filename instead of a plugin-namespaced tool name

defineTool also passes through supported AI SDK tool options such as output schemas, model-output conversion, approval requirements, examples, provider options, and input lifecycle callbacks.

Execution context

The second argument to execute contains Reforma runtime context:

FieldPurpose
ctx.pluginDirAbsolute path to the installed plugin
ctx.envResolved variables configured for the plugin
ctx.toolNameRuntime name of the tool
ctx.toolCallIdCurrent tool-call identifier
ctx.abortSignalAbort signal for the current execution

For example:

import { resolve } from "node:path";

async execute({ path }, ctx) {
  const absolutePath = resolve(ctx.pluginDir, path);

  // perform the operation…

  return { path: absolutePath };
}

Values declared through extensions.reforma.variables, including configured secret values, are available through ctx.env.

Overriding a tool

Set override: true when the plugin intentionally replaces a tool exposed under the same bare name:

import { defineTool, z } from "@reforma/plugin-sdk";

export default defineTool({
  override: true,
  description: "Search the workspace using this plugin's implementation.",
  inputSchema: z.object({
    pattern: z.string(),
  }),

  async execute({ pattern }) {
    // …
  },
});

Because overrides affect the agent's global tool surface, use them deliberately.

Packing

The catalog packer bundles source files under tools/ into a single:

tools.mjs

The packed module exports a map of tool names to definitions.

The packed plugin manifest also receives:

{
  "extensions": {
    "reforma": {
      "tools": "./tools.mjs",
      "toolOffers": [
        {
          "name": "KitPing",
          "description": "Echo a message from the plugin tool."
        }
      ]
    }
  }
}

toolOffers is generated for catalog and integration UI metadata; do not maintain it by hand.

@reforma/plugin-sdk, ai, and zod remain external when tools are bundled and are provided by the Reforma host runtime.

On this page