# How to Register Local Tools for LLM Execution in Tambo AI: A Complete Guide

> Learn to register local tools for LLM execution in Tambo AI. This guide shows static and dynamic registration methods using TamboTool and useTambo hook for seamless integration.

- Repository: [tambo ai/tambo](https://github.com/tambo-ai/tambo)
- Tags: how-to-guide
- Published: 2026-02-16

---

**Register local tools for LLM execution in Tambo AI by wrapping JavaScript functions in `TamboTool` objects and passing them to `<TamboProvider>` for static registration or calling `registerTool()` from the `useTambo` hook for dynamic registration.**

Tambo AI enables LLM-driven applications to execute **local JavaScript tools** directly in the user's browser. When you register local tools for LLM execution in Tambo AI, you create a bridge between the model's reasoning capabilities and your application's functionality. This guide covers the complete implementation using the `tambo-ai/tambo` repository's React SDK.

## Understanding Local Tool Registration in Tambo AI

Local tools are plain JavaScript functions that the LLM can invoke during a conversation. When you register local tools for LLM execution, Tambo AI maintains a **tool registry** (`Map<string, TamboTool>`) that maps tool names to their implementations.

During conversation, when the model emits a `tool_use` event, the SDK looks up the tool name in this registry and executes the corresponding function via **`executeClientTool`** located in [`react-sdk/src/v1/utils/tool-executor.ts`](https://github.com/tambo-ai/tambo/blob/main/react-sdk/src/v1/utils/tool-executor.ts) ([source](https://github.com/tambo-ai/tambo/blob/main/react-sdk/src/v1/utils/tool-executor.ts#L98-L108)).

## Static vs Dynamic Tool Registration

Tambo AI supports two patterns to register local tools for LLM execution:

### Static Registration with TamboProvider

Static registration occurs at application startup. You pass an array of `TamboTool` objects to the `tools` prop of `<TamboProvider>`. The provider builds the registry once at mount time using the internal `registerAllTools` function.

This approach is ideal for core application functionality that must be available immediately.

### Dynamic Registration with useTambo

Dynamic registration allows you to add tools at runtime based on user actions or authentication state. The `useTambo` hook exposes `registerTool` and `registerTools` methods that update the registry on-the-fly.

This pattern is defined in [`react-sdk/src/v1/hooks/use-tambo-v1.ts`](https://github.com/tambo-ai/tambo/blob/main/react-sdk/src/v1/hooks/use-tambo-v1.ts) ([source](https://github.com/tambo-ai/tambo/blob/main/react-sdk/src/v1/hooks/use-tambo-v1.ts#L96-L101)).

## Step-by-Step: Register Local Tools for LLM Execution

Follow these steps to implement local tool registration in your Tambo AI application.

### Step 1: Define the Tool Function

Create the JavaScript function that performs the desired action. This function runs entirely in the browser.

```typescript
// utils/api.ts
export const getWeather = async (city: string) => {
  const res = await fetch(`/api/weather?city=${encodeURIComponent(city)}`);
  if (!res.ok) throw new Error(`HTTP ${res.status}`);
  return await res.json();
};

```

### Step 2: Create the TamboTool Definition

Wrap your function in a `TamboTool` object that provides metadata for the LLM. This definition includes Zod schemas for runtime validation.

```typescript
// tools/weatherTool.ts
import { TamboTool } from "@tambo-ai/react";
import { z } from "zod";
import { getWeather } from "../utils/api";

export const weatherTool: TamboTool = {
  name: "get_weather",
  description: "Fetch current weather information for a specified city",
  tool: getWeather,
  inputSchema: z.string().describe("The city to fetch weather for"),
  outputSchema: z.object({
    location: z.object({ name: z.string() }),
    temperature: z.number(),
    condition: z.string(),
  }),
};

```

The `inputSchema` and `outputSchema` are validated at runtime. Mismatched arguments produce clear errors rather than silent failures.

### Step 3: Register the Tool Statically or Dynamically

**Static registration** via `TamboProvider`:

```tsx
// src/lib/tambo.ts
import { TamboProvider } from "@tambo-ai/react";
import { weatherTool } from "./tools/weatherTool";

export const TamboApp = () => (
  <TamboProvider tools={[weatherTool]}>
    <App />
  </TamboProvider>
);

```

**Dynamic registration** via `useTambo`:

```tsx
// src/components/AuthGate.tsx
import { useTambo } from "@tambo-ai/react";
import { weatherTool } from "../tools/weatherTool";
import { useEffect } from "react";

export const AuthGate = () => {
  const { registerTool } = useTambo();

  useEffect(() => {
    registerTool(weatherTool);
  }, [registerTool]);

  return <>{/* rest of UI */}</>;
};

```

Both approaches ultimately populate the central registry managed by `registerAllTools` in [`apps/web/lib/tambo/tools/tool-registry.ts`](https://github.com/tambo-ai/tambo/blob/main/apps/web/lib/tambo/tools/tool-registry.ts) ([source](https://github.com/tambo-ai/tambo/blob/main/apps/web/lib/tambo/tools/tool-registry.ts#L10-L21)).

### Step 4: Enable Streaming Execution (Optional)

For tools that can handle partial arguments and provide real-time updates, enable streaming execution:

```tsx
export const chartTool: TamboTool = {
  name: "update_chart",
  description: "Update the chart visualization with new data",
  tool: updateChart,
  inputSchema: z.object({
    title: z.string().optional(),
    values: z.array(z.number()).optional(),
  }),
  outputSchema: z.void(),
  annotations: { tamboStreamableHint: true },
};

```

When `tamboStreamableHint: true` is set, the SDK invokes `executeStreamableToolCall` and `createThrottledStreamableExecutor` from [`react-sdk/src/v1/utils/tool-executor.ts`](https://github.com/tambo-ai/tambo/blob/main/react-sdk/src/v1/utils/tool-executor.ts) ([source](https://github.com/tambo-ai/tambo/blob/main/react-sdk/src/v1/utils/tool-executor.ts#L65-L78)). This throttles repeated calls while arguments stream in, enabling real-time UI updates without flooding the browser.

## How Tool Execution Works Under the Hood

When you register local tools for LLM execution in Tambo AI, the following execution flow occurs:

1. **Registry Construction**: Tools are stored in a `Map<string, TamboTool>` registry, either at provider mount time or dynamically via `registerTool`.

2. **Tool Invocation**: When the LLM emits a `tool_use` event, the SDK calls `executeClientTool` in [`react-sdk/src/v1/utils/tool-executor.ts`](https://github.com/tambo-ai/tambo/blob/main/react-sdk/src/v1/utils/tool-executor.ts) ([source](https://github.com/tambo-ai/tambo/blob/main/react-sdk/src/v1/utils/tool-executor.ts#L98-L108)).

3. **Validation**: Input arguments are validated against the `inputSchema` using Zod before execution.

4. **Execution**: The wrapped function runs in the browser, performing local computations or API calls.

5. **Result Handling**: The output is validated against `outputSchema`, optionally transformed via `transformToContent`, and returned as a `ToolResultContent` object that the SDK injects back into the conversation thread.

Type definitions for `TamboTool` are located in [`packages/core/src/ui-tools.ts`](https://github.com/tambo-ai/tambo/blob/main/packages/core/src/ui-tools.ts), while server-side tool counterparts reside in [`packages/backend/src/util/tools.ts`](https://github.com/tambo-ai/tambo/blob/main/packages/backend/src/util/tools.ts).

## Summary

- **Register local tools for LLM execution in Tambo AI** by wrapping JavaScript functions in `TamboTool` objects that include Zod schemas for validation.
- Use **static registration** via `<TamboProvider tools={...}>` for tools needed at application startup.
- Use **dynamic registration** via the `registerTool` method from `useTambo()` for runtime tool addition.
- Enable **streaming execution** by setting `annotations.tamboStreamableHint: true` for tools that support partial argument processing.
- The tool registry is maintained in [`react-sdk/src/v1/utils/tool-executor.ts`](https://github.com/tambo-ai/tambo/blob/main/react-sdk/src/v1/utils/tool-executor.ts) and [`apps/web/lib/tambo/tools/tool-registry.ts`](https://github.com/tambo-ai/tambo/blob/main/apps/web/lib/tambo/tools/tool-registry.ts), with execution handled by `executeClientTool`.

## Frequently Asked Questions

### What is the difference between static and dynamic tool registration in Tambo AI?

Static registration occurs when you pass tools to the `tools` prop of `<TamboProvider>`, building the registry once at component mount. Dynamic registration uses the `registerTool` function returned by `useTambo()` to add tools at runtime based on user actions or authentication state. Both methods ultimately populate the same central registry used by `executeClientTool`.

### How does Tambo AI validate tool inputs and outputs?

Tambo AI uses **Zod schemas** defined in the `inputSchema` and `outputSchema` properties of a `TamboTool` object. When a tool is invoked, arguments are validated against `inputSchema` before execution, and return values are validated against `outputSchema` afterward. This runtime validation prevents silent failures and provides clear error messages when data doesn't match expected shapes.

### Can I register tools that update the UI in real-time as the LLM streams arguments?

Yes. Set `annotations: { tamboStreamableHint: true }` in your `TamboTool` definition. This enables the streaming executor (`executeStreamableToolCall` and `createThrottledStreamableExecutor` in [`react-sdk/src/v1/utils/tool-executor.ts`](https://github.com/tambo-ai/tambo/blob/main/react-sdk/src/v1/utils/tool-executor.ts)) to invoke your tool repeatedly as partial arguments arrive, throttled to avoid performance issues. This pattern is ideal for tools that update charts or visualizations incrementally.