🏖️ BunnyAgent

Custom Tools

Add AI SDK tools to Bunny Agent runs

Bunny Agent uses the standard AI SDK tool API. Keep importing streamText and tool from ai; Bunny only provides the model provider and optional helper tools.

Quick Start

import { bunnyHttpTool, createBunnyAgent } from "@bunny-agent/sdk";
import { streamText } from "ai";
import { z } from "zod";

const bunny = createBunnyAgent({
  sandbox,
  env: {
    OPENAI_API_KEY: process.env.OPENAI_API_KEY!,
  },
});

const result = streamText({
  model: bunny("gpt-5.2"),
  prompt: "Get the weather in Paris.",
  tools: {
    weather: bunnyHttpTool({
      description: "Get current weather",
      inputSchema: z.object({ city: z.string() }),
      endpoint: {
        url: "https://your-app.com/api/tools/weather",
        headers: {
          Authorization: `Bearer ${process.env.TOOL_API_TOKEN}`,
        },
      },
    }),
  },
});

This keeps the call shape as standard AI SDK streamText({ tools }), while the Bunny helper adds provider-visible runtime metadata for the sandbox runner.

Runner-Executed Tools

The pi runner can also execute provider-side tools inside the sandbox. These tools are rendered as provider-executed dynamic tool calls in AI SDK UI streams.

Bunny supports two runner-executed tool styles:

Use caseAPI
The tool already exists as an HTTP APIbunnyHttpTool(...)
The tool implementation exists inside the sandbox filesystembunnySandboxTool(...)

Use these when you want the sandbox runner, not AI SDK, to execute the tool.

Standard AI SDK tool({ execute }) callbacks are client-executed tools. AI SDK does not pass their JavaScript execute functions through the provider boundary, so Bunny cannot turn arbitrary host closures into pi-runner tools from inside createBunnyAgent().

Direct HTTP Tools

If the tool already exists as an HTTP API and you want the sandbox runner to call it directly, use bunnyHttpTool.

import { bunnyHttpTool, createBunnyAgent } from "@bunny-agent/sdk";
import { streamText } from "ai";
import { z } from "zod";

const bunny = createBunnyAgent({ sandbox });

const result = streamText({
  model: bunny("gpt-5.2"),
  prompt: "Get the weather in Paris.",
  tools: {
    weather: bunnyHttpTool({
      description: "Get current weather",
      inputSchema: z.object({ city: z.string() }),
      endpoint: {
        url: "https://your-app.com/api/tools/weather",
        headers: {
          Authorization: `Bearer ${process.env.TOOL_API_TOKEN}`,
        },
      },
    }),
  },
});

The endpoint and headers are sent to the sandbox runner, so only use this when that credential is safe for the sandbox boundary.

Sandbox Module Tools

If the tool implementation already exists inside the sandbox filesystem, use bunnySandboxTool.

import { bunnySandboxTool, createBunnyAgent } from "@bunny-agent/sdk";
import { streamText } from "ai";
import { z } from "zod";

const bunny = createBunnyAgent({ sandbox });

const result = streamText({
  model: bunny("gpt-5.2"),
  prompt: "Summarize this repository.",
  tools: {
    repoStats: bunnySandboxTool({
      description: "Summarize repository stats",
      inputSchema: z.object({ path: z.string() }),
      module: "/workspace/tools/repo-stats.mjs",
      exportName: "execute",
    }),
  },
});

The runner imports the module inside the sandbox and calls the selected export.

On this page