TypeScript SDK

Install the SDK:

npm install rebuno

Authentication

The kernel uses --bearer-token / REBUNO_BEARER_TOKEN to configure bearer token authentication. The TypeScript SDK accepts an apiKey parameter which maps to this bearer token. The SDK sends the token as an Authorization: Bearer <apiKey> header on all HTTP requests and SSE connections to the kernel.

const agent = new MyAgent({
  agentId: "researcher",
  kernelUrl: "http://localhost:8080",
  apiKey: "your-secret-token", // maps to --bearer-token on the kernel
});

In development mode (when the kernel is started without --bearer-token), apiKey can be omitted.

Writing an Agent

Local Tools

Register tools with agent.addTool(). The agent holds the implementation and executes it in-process after the kernel approves the intent.

import { z } from "zod";
import { BaseAgent, AgentContext, defineTool } from "rebuno";

class MyAgent extends BaseAgent {
  async process(ctx: AgentContext) {
    const tools = ctx.getTools();
    const result = await tools[0].execute({ query: "what is rebuno" });
    return { answer: result };
  }
}

const agent = new MyAgent({
  agentId: "my-agent",
  kernelUrl: "http://localhost:8080",
});

agent.addTool(
  defineTool({
    id: "web_search",
    description: "Search the web for information.",
    inputSchema: z.object({ query: z.string() }),
    execute: async (input) => {
      return { results: await doSearch(input.query) };
    },
  }),
);

agent.run();

Remote Tools

Declare tool schemas with agent.addRemoteTool(). The execute function is never called — a separate runner process handles execution.

agent.addRemoteTool(
  defineTool({
    id: "web_search",
    description: "Search the web for information.",
    inputSchema: z.object({ query: z.string() }),
    execute: async () => ({}), // body is never called
  }),
);

The rest of the agent code is identical. ctx.getTools() returns wrapped tools that route to the runner transparently.

Mixing Local and Remote Tools

An agent can use both. The SDK routes each call to the right place.

agent.addTool(
  defineTool({
    id: "calculator",
    description: "Evaluate a math expression.",
    inputSchema: z.object({ expression: z.string() }),
    execute: async (input) => ({ result: eval(input.expression) }),
  }),
);

agent.addRemoteTool(
  defineTool({
    id: "web_search",
    description: "Search the web for information.",
    inputSchema: z.object({ query: z.string() }),
    execute: async () => ({}),
  }),
);

MCP Tools

Connect to MCP servers to use their tools as local tools. Requires @modelcontextprotocol/sdk as a dependency.

const agent = new MyAgent({
  agentId: "my-agent",
  kernelUrl: "http://localhost:8080",
});

// Stdio server
agent.mcpServer({
  name: "filesystem",
  command: "npx",
  args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"],
});

// HTTP server
agent.mcpServer({ name: "github", url: "http://localhost:3000/mcp" });

MCP tools are prefixed with the server name (e.g., filesystem.read_file) and appear alongside local and remote tools in ctx.getTools(). See Tools for namespacing, config-based setup, and partial failure behavior.

You can also load MCP servers from a config object:

agent.mcpServersFromConfig({
  filesystem: {
    command: "npx",
    args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"],
  },
  github: {
    url: "http://localhost:3000/mcp",
  },
});

Framework Integration

ctx.getTools() returns WrappedTool objects that can be converted to framework-specific formats using adapters.

// Vercel AI SDK
import { toVercelTools } from "rebuno/tools/adapters/vercel";
const tools = toVercelTools(ctx.getTools());

// LangChain
import { toLangchainTools } from "rebuno/tools/adapters/langchain";
const tools = await toLangchainTools(ctx.getTools());

// Mastra
import { toMastraTools } from "rebuno/tools/adapters/mastra";
const tools = toMastraTools(ctx.getTools());

Direct Tool Invocation

You can also invoke tools directly without getTools():

class MyAgent extends BaseAgent {
  async process(ctx: AgentContext) {
    // Invoke and wait for result
    const result = await ctx.invokeTool("web_search", { query: "rebuno" });

    // Submit multiple tools in parallel
    const stepA = await ctx.submitTool("web_search", { query: "topic A" });
    const stepB = await ctx.submitTool("web_search", { query: "topic B" });
    const results = await ctx.awaitSteps([stepA, stepB]);

    // Wait for an external signal (human approval, webhook, etc.)
    const approval = await ctx.waitSignal("approval");

    return { answer: results };
  }
}

Constructor Parameters

BaseAgent

ParameterTypeDefaultDescription
agentIdstringrequiredUnique identifier for this agent. Must match the agent ID used in policy and execution creation.
kernelUrlstringrequiredURL of the rebuno kernel (e.g., http://localhost:8080).
apiKeystring""Bearer token for authenticating with the kernel. Maps to the kernel's --bearer-token / REBUNO_BEARER_TOKEN.
consumerIdstring""Unique identifier for this SSE connection instance. If empty, auto-generated as {agentId}-{random}. See Consumer ID.
reconnectDelaynumber3.0Base delay in seconds before reconnecting after an SSE connection failure.
maxReconnectDelaynumber60.0Maximum delay in seconds between reconnection attempts (exponential backoff cap).

BaseRunner

ParameterTypeDefaultDescription
runnerIdstringrequiredUnique identifier for this runner.
kernelUrlstringrequiredURL of the rebuno kernel.
capabilitiesstring[][]List of tool IDs this runner can execute (e.g., ["web_search", "doc_fetch"]).
apiKeystring""Bearer token for authenticating with the kernel. Maps to the kernel's --bearer-token / REBUNO_BEARER_TOKEN.
namestring""Human-readable name for the runner. Defaults to runnerId if empty.
reconnectDelaynumber2.0Base delay in seconds before reconnecting after an SSE connection failure.
maxReconnectDelaynumber60.0Maximum delay in seconds between reconnection attempts (exponential backoff cap).

Note: The runner's consumerId is auto-generated as {runnerId}-{random} and cannot be overridden via the constructor.

AgentContext

Created internally by the SDK when the kernel assigns an execution. You do not construct it directly. See AgentContext Reference for the full list of methods and properties available inside process().

Consumer ID

The consumerId identifies a specific SSE connection instance for a given agent. It serves several purposes:

  • Multiple consumers: Multiple processes can connect with the same agentId but different consumerId values for redundancy and load distribution.
  • Round-robin assignment: The kernel round-robins execution assignments across all connected consumers for the same agent.
  • Uniqueness: Each consumerId must be unique per connection. If omitted, the SDK auto-generates one.
// Two instances of the same agent for redundancy
const agent1 = new MyAgent({
  agentId: "researcher",
  kernelUrl: "...",
  consumerId: "researcher-instance-1",
});
const agent2 = new MyAgent({
  agentId: "researcher",
  kernelUrl: "...",
  consumerId: "researcher-instance-2",
});

AgentContext Reference

MethodDescription
ctx.getTools()Return framework-compatible wrapped tools
ctx.invokeTool(toolId, arguments, idempotencyKey?)Invoke a tool and wait for the result
ctx.submitTool(toolId, arguments, idempotencyKey?)Submit a tool invocation, return stepId immediately
ctx.awaitSteps(stepIds)Wait for multiple parallel tool invocations to complete
ctx.waitSignal(signalType)Wait until an external signal is received
ctx.complete(output?)Mark execution as complete
ctx.fail(error)Mark execution as failed
PropertyDescription
ctx.executionIdCurrent execution ID
ctx.sessionIdCurrent session ID
ctx.agentIdAgent ID
ctx.inputInput data from the execution request
ctx.labelsExecution labels
ctx.historyPrevious steps in this execution

Writing a Runner

Runners execute tools on behalf of agents that use addRemoteTool(). They maintain a persistent SSE connection to the kernel, receive job assignments via push, and report results over HTTP.

import { BaseRunner } from "rebuno";

class MyRunner extends BaseRunner {
  async execute(toolId: string, args: unknown): Promise<unknown> {
    const arguments_ = args as Record<string, unknown>;
    if (toolId === "web_search") {
      return { results: await doSearch(arguments_.query as string) };
    }
    throw new Error(`Unknown tool: ${toolId}`);
  }
}

const runner = new MyRunner({
  runnerId: "my-runner",
  kernelUrl: "http://localhost:8080",
  capabilities: ["web_search"],
});

runner.run();

MCP-backed Runner

A runner can serve MCP tools without any custom execute() logic:

import { BaseRunner } from "rebuno";

const runner = new BaseRunner({
  runnerId: "mcp-tools",
  kernelUrl: "http://localhost:8080",
});

runner.mcpServer({
  name: "filesystem",
  command: "npx",
  args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"],
});

runner.run();

MCP tool IDs are automatically registered as capabilities. Jobs for MCP tools are routed directly to the MCP server; non-MCP tools fall through to execute().

Using the Client

The RebunoClient provides a low-level API for interacting with the kernel directly.

import { RebunoClient } from "rebuno";

const client = new RebunoClient({
  baseUrl: "http://localhost:8080",
  apiKey: "your-secret-token", // optional
});

// Create an execution
const execution = await client.createExecution("my-agent", {
  query: "what is rebuno",
});

// Stream events
for await (const event of client.streamEvents(execution.id)) {
  console.log(event.type, event.payload);
}

// Send a signal (e.g., human approval)
await client.sendSignal(execution.id, "approval", { approved: true });

RebunoClient Options

ParameterTypeDefaultDescription
baseUrlstringrequiredBase URL of the rebuno kernel.
apiKeystringundefinedBearer token for authentication.
timeoutnumber35000Request timeout in milliseconds.
maxRetriesnumber3Maximum retry attempts for failed requests.
retryBaseDelaynumber1.0Base delay in seconds between retries.
retryMaxDelaynumber10.0Maximum delay in seconds between retries.
fetchFetchFnglobalThis.fetchCustom fetch function.

Client Methods

MethodDescription
createExecution(agentId, input?, labels?)Start a new execution
getExecution(executionId)Get execution details
listExecutions(options?)List executions with optional filters
cancelExecution(executionId)Cancel a running execution
sendSignal(executionId, signalType, payload?)Send a signal to an execution
getEvents(executionId, afterSequence?, limit?)Get events for an execution
streamEvents(executionId, afterSequence?)Stream events as an async generator
health()Check kernel health
ready()Check kernel readiness

Tool Adapters

The SDK provides adapters for popular AI frameworks. Each adapter converts WrappedTool objects from ctx.getTools() into the format expected by the framework.

Vercel AI SDK

import { toVercelTools } from "rebuno/tools/adapters/vercel";

const tools = toVercelTools(ctx.getTools());
// Returns Record<string, CoreTool> keyed by sanitized tool name

LangChain

import { toLangchainTools } from "rebuno/tools/adapters/langchain";

const tools = await toLangchainTools(ctx.getTools());
// Returns StructuredTool[] for use with LangChain agents

Mastra

import { toMastraTools } from "rebuno/tools/adapters/mastra";

const tools = toMastraTools(ctx.getTools());
// Returns tools with { context } execute signature

External Tools

You can also register tools from external frameworks directly:

import { tool } from "ai"; // Vercel AI SDK

agent.addExternalTool("my-tool", tool({
  description: "...",
  parameters: z.object({ ... }),
  execute: async (input) => { ... },
}));

The ToolRegistry auto-detects Vercel, LangChain, and Mastra tool formats.

Timeouts

Step timeouts are controlled by policy rules. When a policy rule includes timeout_ms in its then block, that value is used as the step deadline. Otherwise the global StepTimeout (default: 5 min) applies. See Policy for details.