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

# Client Functions

> Register browser-side functions that AGO agents can invoke during conversations

Client functions let you extend what AGO agents can do by registering JavaScript functions in the browser. When the agent determines that a registered function is relevant, it calls it automatically -- the SDK executes the function locally and sends the result back to the agent.

This enables use cases like:

* **Navigating your application** -- open a specific page, scroll to a section, or show a modal
* **Reading application state** -- return the current user's cart, selected filters, or form values
* **Triggering UI actions** -- open a contact form, start a product tour, or play a video
* **Calling browser APIs** -- get the current time, geolocation, or clipboard contents

## How It Works

```
1. You register functions with the SDK
2. The SDK sends function schemas to AGO with each message
3. The agent decides when a function is relevant and invokes it
4. The SDK executes the function in the browser
5. The result is sent back to the agent
6. The agent uses the result to continue the conversation
```

The agent sees a description of each function and its parameters. Based on the conversation context, it decides whether and when to call a function -- you do not need to trigger it manually.

***

## Registering a Function

Use `client.registerFunction()` with three arguments: a **name**, a **handler**, and a **schema** that describes the function to the agent.

```javascript theme={null}
client.registerFunction(
  "getCurrentTime",
  async () => {
    return { time: new Date().toLocaleTimeString() };
  },
  {
    description: "Get the current time in the user's timezone",
    parameters: {
      type: "object",
      properties: {},
    },
  }
);
```

### Function with Parameters

```javascript theme={null}
client.registerFunction(
  "addToCart",
  async (args) => {
    const result = await addItemToCart(args.productId, args.quantity);
    return { success: true, cartTotal: result.total };
  },
  {
    description: "Add a product to the user's shopping cart",
    parameters: {
      type: "object",
      properties: {
        productId: {
          type: "string",
          description: "The product ID to add",
        },
        quantity: {
          type: "integer",
          description: "Number of items to add",
        },
      },
      required: ["productId"],
    },
  }
);
```

### Schema Reference

| Field                   | Required | Description                                                                                   |
| ----------------------- | -------- | --------------------------------------------------------------------------------------------- |
| `description`           | Yes      | A clear description of what the function does. The agent uses this to decide when to call it. |
| `parameters.type`       | Yes      | Always `"object"`                                                                             |
| `parameters.properties` | Yes      | An object describing each parameter (can be empty `{}` for no-parameter functions)            |
| `parameters.required`   | No       | Array of required parameter names                                                             |

Each property in `parameters.properties` accepts:

| Field         | Description                                                                 |
| ------------- | --------------------------------------------------------------------------- |
| `type`        | `"string"`, `"number"`, `"integer"`, `"boolean"`, `"array"`, or `"object"`  |
| `description` | Explains what the parameter is for (helps the agent provide correct values) |
| `enum`        | Array of allowed values (e.g., `["small", "medium", "large"]`)              |

***

## Naming Rules

Function names must follow these rules:

* Only letters, numbers, underscores, and hyphens
* Between 1 and 50 characters
* No spaces or special characters

Valid names: `getCurrentTime`, `add-to-cart`, `search_products`

Invalid names: `get current time`, `../hack`, `my@function`

***

## Unregistering a Function

Remove a function when it is no longer relevant:

```javascript theme={null}
client.unregisterFunction("addToCart");
```

This is useful when navigating between pages where different functions apply. For example, register cart functions only on the product page and unregister them when the user navigates away.

***

## Listing Registered Functions

```javascript theme={null}
const functions = client.getRegisteredFunctions();
functions.forEach((fn) => {
  console.log(fn.name, fn.description);
});
```

***

## Listening to Function Events

Track when functions are invoked and when results are returned:

```javascript theme={null}
// Fires when the agent invokes a function
client.on("function:invoke", (data) => {
  console.log(`Agent is calling ${data.functionName}`, data.arguments);
});

// Fires after the function executes and the result is sent back
client.on("function:result", (data) => {
  if (data.error) {
    console.error("Function failed:", data.error);
  } else {
    console.log("Function result:", data.result);
  }
});
```

***

## Error Handling

If a registered function throws an error, the SDK catches it and sends the error message back to the agent. The agent can then inform the user or try an alternative approach.

```javascript theme={null}
client.registerFunction(
  "getOrderStatus",
  async (args) => {
    const order = await fetchOrder(args.orderId);
    if (!order) {
      throw new Error("Order not found");
    }
    return { status: order.status, estimatedDelivery: order.eta };
  },
  {
    description: "Get the status of a customer order",
    parameters: {
      type: "object",
      properties: {
        orderId: {
          type: "string",
          description: "The order ID to look up",
        },
      },
      required: ["orderId"],
    },
  }
);
```

***

## Best Practices

### Write Clear Descriptions

The agent relies on the `description` field to decide when to call a function. Be specific about what the function does and when it should be used.

```javascript theme={null}
// Good -- specific and actionable
description: "Navigate the user to a specific product page by product ID"

// Bad -- vague
description: "Navigate somewhere"
```

### Return Structured Data

Return objects with descriptive keys so the agent can use the information in its response.

```javascript theme={null}
// Good
return { itemCount: 3, totalPrice: 49.99, currency: "USD" };

// Bad
return 3;
```

### Keep the Number of Functions Low

You can send up to **30** client functions with a message. Above that, the request is rejected.

Stay well under the limit whenever you can. The more functions the agent has to choose from, the harder it becomes to pick the right one -- past **10** functions in a single message, expect the agent to call the wrong function or miss the right one more often. Register only the functions relevant to the current page or state, and unregister the ones that no longer apply.

### Keep Functions Focused

Each function should do one thing. Register multiple focused functions rather than one function that does everything.

### Register Contextually

Register functions that are relevant to the current page or state. On a product page, register product-related functions. On the checkout page, register checkout-related functions.

```javascript theme={null}
// On the product page
client.registerFunction("addToCart", ...);
client.registerFunction("getProductDetails", ...);

// When navigating to checkout
client.unregisterFunction("addToCart");
client.unregisterFunction("getProductDetails");
client.registerFunction("applyCoupon", ...);
client.registerFunction("getCartSummary", ...);
```

***

## Complete Example

```javascript theme={null}
import { AgoClient } from "@useago/sdk";

const client = new AgoClient({
  baseUrl: "https://YOUR-DOMAIN.useago.com",
});

// Register functions
client.registerFunction(
  "searchProducts",
  async (args) => {
    const results = await fetch(`/api/products?q=${args.query}&limit=5`);
    return await results.json();
  },
  {
    description: "Search the product catalog by keyword",
    parameters: {
      type: "object",
      properties: {
        query: {
          type: "string",
          description: "Search keywords",
        },
      },
      required: ["query"],
    },
  }
);

client.registerFunction(
  "openProductPage",
  async (args) => {
    window.location.href = `/products/${args.productId}`;
    return { navigated: true };
  },
  {
    description: "Navigate the user to a specific product page",
    parameters: {
      type: "object",
      properties: {
        productId: {
          type: "string",
          description: "The product ID to navigate to",
        },
      },
      required: ["productId"],
    },
  }
);

// Listen to events
client.on("function:invoke", (data) => {
  console.log(`Calling ${data.functionName}...`);
});

// Send a message -- the agent may invoke registered functions
const response = await client.sendMessage("I'm looking for wireless headphones");
console.log(response.content);
```

***

## Related Documentation

* [JavaScript SDK](/features/sdk-integration) -- Full SDK setup and usage guide
* [SDK API Reference](/api/sdk-api) -- REST API endpoints
* [Tools](/features/tools) -- Server-side tools that agents can use
