> ## Documentation Index
> Fetch the complete documentation index at: https://docs.teamai.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Client-side tools

> Register functions in your page that the agent can call during a conversation.

## What a client-side tool is

A client-side tool is a function on your page that the agent can call. You give it a name, a description, and a JSON Schema for its input. When the agent uses it, the SDK runs your function and returns the result to the agent, which continues its answer.

Use tools to read app state (the cart, the user's plan), act in the browser (navigate, open a panel, fill a form), or call your own APIs with the visitor's session.

## Register a tool

```javascript theme={null}
const chatbot = tai.getInstance("YOUR_ASSISTANT_ID");

chatbot.registerTool({
  name: "getOrderStatus",
  description: "Returns the shipping status of one of the customer's orders.",
  parameters: {
    type: "object",
    properties: {
      orderId: { type: "string", description: "The order number shown in the customer's account." },
    },
    required: ["orderId"],
  },
  execute: async ({ orderId }) => {
    const response = await fetch(`/api/orders/${orderId}/status`);
    if (!response.ok) return { error: `Order ${orderId} not found` };
    return response.json();
  },
});
```

<ParamField path="name" type="string" required>
  The tool name the agent calls. Use letters, digits, and underscores. Leading and trailing spaces are trimmed.
</ParamField>

<ParamField path="description" type="string" required>
  Tells the agent when to use the tool. Write it for the model: what the tool does, what it returns, when not to use it.
</ParamField>

<ParamField path="parameters" type="object" required>
  A JSON Schema object describing the input. Start with `type: "object"` and list fields under `properties`. This object is passed to the model as the tool's input schema without changes, so a bare map of field names is not valid.
</ParamField>

<ParamField path="execute" type="function" required>
  Receives the input the agent produced, matching your schema. May return a value or a Promise. The return value is JSON-serialized and given to the agent.
</ParamField>

<ParamField path="displayName" type="string">
  Shown in the chat while the tool runs. Defaults to `name`.
</ParamField>

A tool with no input still needs a schema:

```javascript theme={null}
parameters: { type: "object", properties: {} }
```

`registerTool()` throws if `name`, `description`, or `execute` is missing or `execute` is not a function.

## When tools reach the agent

You can register tools before or after the agent is ready. The SDK sends the full tool list to the iframe when the agent becomes ready and again on every `registerTool()` or `unregisterTool()` call. The iframe includes the current list with every request, so a tool registered between two messages is available for the second one.

The agent only sees the name, display name, description, and schema. Your `execute` function stays on your page.

## Execution rules

* Each call has 30 seconds. If `execute` has not settled by then, the agent receives no result and continues without it.
* A thrown error or rejected Promise is returned to the agent as `{ error: "Error executing tool: <message>" }`. Return an `{ error }` object yourself when you want to control the wording.
* A call for a tool name that is no longer registered returns `{ error: 'Tool "<name>" not found' }`.
* Return plain data. Functions, DOM nodes, and circular structures do not serialize.
* Tool calls happen while the assistant is `thinking` or `answering`, so `sendMessage()` returns `busy` until the answer that triggered the tool completes.

## Remove or list tools

```javascript theme={null}
chatbot.unregisterTool("getOrderStatus"); // returns true if it existed
chatbot.getRegisteredTools();             // ClientTool[]
```

## Example: navigation and app state

```javascript theme={null}
window.addEventListener("teamAIChatbotReady", () => {
  const chatbot = tai.getInstance("YOUR_ASSISTANT_ID");

  chatbot.registerTool({
    name: "getCart",
    description: "Returns the items and total currently in the visitor's shopping cart.",
    parameters: { type: "object", properties: {} },
    execute: () => window.app.cart.snapshot(),
  });

  chatbot.registerTool({
    name: "openPage",
    displayName: "Opening page",
    description: "Navigates the visitor to a page on this site. Use only paths that start with /.",
    parameters: {
      type: "object",
      properties: {
        path: { type: "string", description: "Site-relative path such as /pricing" },
      },
      required: ["path"],
    },
    execute: ({ path }) => {
      if (!path.startsWith("/")) return { error: "Only site-relative paths are allowed" };
      window.location.assign(path);
      return { navigated: path };
    },
  });
});
```

Validate every input inside `execute`. The schema guides the model but does not guarantee the values it sends.

## Tell the agent the tools exist

The agent sees the tool descriptions on every request, so it can use them without further prompting. For tools the agent should prefer, or should ask before using, add a line to the agent's instructions in TeamAI, for example "Use getCart before answering questions about prices or totals."
