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

# Tool Calling Example

> Create and attach a tool to an Anam persona, handle its arguments, return a result, and test function calling in a live conversation.

## What You'll Build

In this guide, you'll create a complete AI persona with tool calling capabilities. By the end, you'll have:

* A knowledge base with uploaded documents
* Multiple tools (knowledge, webhook, and client)
* A working persona that can search documents, call APIs, and trigger client actions

> [!NOTE]
>
> This guide takes approximately 15 minutes to complete. We'll use both the Anam Lab UI and API for a complete understanding.

## Prerequisites

Before starting, ensure you have:

* An Anam account (sign up at [anam.ai](https://anam.ai))
* An API key (create one at `/api-keys`)
* Basic familiarity with REST APIs
* (Optional) Node.js or Python for testing

## Step 1: Create a Knowledge Folder

Knowledge folders organize your documents for semantic search. Let's create one for product documentation.

> [tab] UI
>
> 1. Go to the [Prompt tab in Anam Lab](https://lab.anam.ai/build?tab=prompt) and find the **Knowledge** card
>
> 2. Select **Manage folders**, then **New folder**
>
> 3. Name it `Product Documentation`
>
> 4. Select **Create**, tick its checkbox to link it to this persona, then select **Done**
>
> > [!TIP]
> >
> > Your folder is created with a unique ID. Note this ID for later use.

> [tab] API
>
> ```javascript theme={"system"}
> const response = await fetch("https://api.anam.ai/v1/knowledge/groups", {
>   method: "POST",
>   headers: {
>     Authorization: "Bearer YOUR_API_KEY",
>     "Content-Type": "application/json",
>   },
>   body: JSON.stringify({
>     name: "Product Documentation",
>     description: "Technical guides and product information",
>   }),
> });
>
> const folder = await response.json();
> console.log("Folder ID:", folder.id);
> ```

## Step 2: Upload Documents

Upload documents to make them searchable. We'll use a PDF user guide as an example.

> [tab] UI
>
> 1. Open the **Knowledge library** from the **Knowledge** card and find your **Product Documentation** folder
>
> 2. Select the upload icon on its row
>
> 3. Drag your PDF onto the dialog, or select **Choose files**
>
> 4. Select **Upload 1 file**
>
> > [!TIP]
> >
> > Expand the folder to see the document. It is searchable once its status changes from `PROCESSING` to `READY`. See [monitoring upload progress](https://anam.ai/docs/personas/knowledge/uploading-documents.md#monitoring-upload-progress).

> [tab] API
>
> This uses the three-step signed upload process, the recommended route for any file because the upload itself goes straight to storage. A single multipart request to `POST /v1/knowledge/groups/{id}/documents` also works for small files.
>
> **Step 1: Request a Signed Upload URL**
>
> ```javascript theme={"system"}
> const uploadResponse = await fetch(
>   `https://api.anam.ai/v1/knowledge/groups/${YOUR_FOLDER_ID}/documents/presigned-upload`,
>   {
>     method: "POST",
>     headers: {
>       Authorization: "Bearer YOUR_API_KEY",
>       "Content-Type": "application/json",
>     },
>     body: JSON.stringify({
>       filename: "user-guide.pdf",
>       contentType: "application/pdf",
>       fileSize: 2048000,
>     }),
>   }
> );
>
> const { uploadUrl, documentId } = await uploadResponse.json();
> ```
>
> **Step 2: Upload Your File to the URL**
>
> ```javascript theme={"system"}
> const file = document.querySelector('input[type="file"]').files[0]; // Your File object
> await fetch(uploadUrl, {
>   method: "PUT",
>   headers: {
>     "Content-Type": file.type,
>   },
>   body: file,
> });
> ```
>
> **Step 3: Confirm the Upload**
>
> ```javascript theme={"system"}
> await fetch(
>   `https://api.anam.ai/v1/knowledge/documents/${documentId}/confirm-upload`,
>   {
>     method: "POST",
>     headers: {
>       Authorization: "Bearer YOUR_API_KEY",
>       "Content-Type": "application/json",
>     },
>     body: JSON.stringify({
>       fileSize: 2048000,
>     }),
>   }
> );
> ```
>
> > [!TIP]
> >
> > For complete, copy-pasteable code examples in different languages, see [Upload and update documents](https://anam.ai/docs/personas/knowledge/uploading-documents.md).

> [!WARNING]
>
> Documents must reach `READY` before they can be searched. Check the status rather than relying on a fixed waiting time.

## Step 3: Create a Session with Tools

Ephemeral personas support two ways to configure tools at runtime:

1. **Reference pre-created tools** using `toolIds` - Best for reusing tools across different sessions or personas
2. **Define tools inline** using `tools` array - Best for session-specific or dynamic tool configurations

> [tab] Using toolIds (Reusable)
>
> First, create reusable tools via the API. These can be used across multiple sessions and personas.
>
> > [accordion] Create a Knowledge Tool
> >
> > ```javascript theme={"system"}
> > const knowledgeTool = await fetch("https://api.anam.ai/v1/tools", {
> >   method: "POST",
> >   headers: {
> >     Authorization: "Bearer YOUR_API_KEY",
> >     "Content-Type": "application/json",
> >   },
> >   body: JSON.stringify({
> >     name: "search_product_docs",
> >     description: "Search product documentation when users ask technical questions about features, installation, or usage",
> >     type: "SERVER_RAG",
> >     config: {
> >       documentFolderIds: ["YOUR_FOLDER_ID"], // From Step 1
> >     },
> >   }),
> > }).then(res => res.json());
> > ```
>
> > [accordion] Create a Webhook Tool
> >
> > ```javascript theme={"system"}
> > const webhookTool = await fetch("https://api.anam.ai/v1/tools", {
> >   method: "POST",
> >   headers: {
> >     Authorization: "Bearer YOUR_API_KEY",
> >     "Content-Type": "application/json",
> >   },
> >   body: JSON.stringify({
> >     name: "check_order_status",
> >     description: "Check the status of a customer order when they provide an order ID",
> >     type: "SERVER_WEBHOOK",
> >     config: {
> >       url: "https://your-api.com/orders/status",
> >       method: "POST",
> >       headers: {
> >         "X-API-Key": "your-api-key",
> >       },
> >     },
> >   }),
> > }).then(res => res.json());
> > ```
>
> > [accordion] Create a Client Tool
> >
> > ```javascript theme={"system"}
> > const clientTool = await fetch("https://api.anam.ai/v1/tools", {
> >   method: "POST",
> >   headers: {
> >     Authorization: "Bearer YOUR_API_KEY",
> >     "Content-Type": "application/json",
> >   },
> >   body: JSON.stringify({
> >     name: "open_product_page",
> >     description: "Open a product page when the user wants to see more details about a product",
> >     type: "CLIENT",
> >     config: {
> >       parameters: {
> >         type: "object",
> >         properties: {
> >           productId: {
> >             type: "string",
> >             description: "The ID of the product to display",
> >           },
> >         },
> >         required: ["productId"],
> >       },
> >     },
> >   }),
> > }).then(res => res.json());
> > ```
>
> **Reference tools by ID in session**
>
> ```javascript theme={"system"}
> const sessionTokenResponse = await fetch("https://api.anam.ai/v1/auth/session-token", {
>   method: "POST",
>   headers: {
>     Authorization: "Bearer YOUR_API_KEY",
>     "Content-Type": "application/json",
>   },
>   body: JSON.stringify({
>     personaConfig: {
>       name: "Product Support Agent",
>       avatarId: "YOUR_AVATAR_ID",
>       avatarModel: "cara-4",
>       voiceId: "YOUR_VOICE_ID",
>       llmId: "YOUR_LLM_ID",
>       systemPrompt: `You are a helpful product support agent. You can:
> - Search product documentation to answer technical questions
> - Check order status for customers
> - Open product pages when customers want more details
>
> Be friendly, concise, and proactive in helping customers.`,
>       toolIds: [
>         knowledgeTool.id,
>         webhookTool.id,
>         clientTool.id,
>       ],
>     },
>   }),
> });
>
> const { sessionToken } = await sessionTokenResponse.json();
> ```
>
> > [!TIP]
> >
> > This approach lets you manage tools centrally and reuse them across multiple sessions and personas.

> [tab] Inline tools (Dynamic)
>
> Define the complete tool configuration directly in the session token request:
>
> ```javascript theme={"system"}
> const sessionTokenResponse = await fetch("https://api.anam.ai/v1/auth/session-token", {
>   method: "POST",
>   headers: {
>     Authorization: "Bearer YOUR_API_KEY",
>     "Content-Type": "application/json",
>   },
>   body: JSON.stringify({
>     personaConfig: {
>       name: "Product Support Agent",
>       avatarId: "YOUR_AVATAR_ID",
>       avatarModel: "cara-4",
>       voiceId: "YOUR_VOICE_ID",
>       llmId: "YOUR_LLM_ID",
>       systemPrompt: `You are a helpful product support agent. You can:
> - Search product documentation to answer technical questions
> - Check order status for customers
> - Open product pages when customers want more details
>
> Be friendly, concise, and proactive in helping customers.`,
>       tools: [
>         // Knowledge Tool - searches your uploaded documents
>         {
>           type: "server",
>           subtype: "knowledge",
>           name: "search_product_docs",
>           description: "Search product documentation when users ask technical questions about features, installation, or usage",
>           documentFolderIds: ["YOUR_FOLDER_ID"], // Folder ID from Step 1
>         },
>         // Webhook Tool - calls your external API
>         {
>           type: "server",
>           subtype: "webhook",
>           name: "check_order_status",
>           description: "Check the status of a customer order when they provide an order ID",
>           url: "https://your-api.com/orders/status",
>           method: "POST",
>           headers: {
>             "X-API-Key": "your-api-key",
>           },
>           parameters: {
>             type: "object",
>             properties: {
>               orderId: {
>                 type: "string",
>                 description: "The order ID to check",
>               },
>             },
>             required: ["orderId"],
>           },
>         },
>         // Client Tool - triggers events in your app
>         {
>           type: "client",
>           name: "open_product_page",
>           description: "Open a product page when the user wants to see more details about a product",
>           parameters: {
>             type: "object",
>             properties: {
>               productId: {
>                 type: "string",
>                 description: "The ID of the product to display",
>               },
>             },
>             required: ["productId"],
>           },
>           awaitResult: true,
>         },
>       ],
>     },
>   }),
> });
>
> const { sessionToken } = await sessionTokenResponse.json();
> ```
>
> > [!TIP]
> >
> > Inline tools are perfect for dynamic configurations, user-specific parameters, or when tool behavior needs to change per session.

## Step 4: Initialize SDK and Handle Events

**1. Initialize SDK client**

```javascript theme={"system"}
import { AnamClient, AnamEvent } from '@anam-ai/js-sdk';

const client = new AnamClient({
sessionToken: sessionToken,
});

console.log('Anam client initialized');

```

**2. Set up event listeners**

```javascript theme={"system"}
// Register a handler for the client tool
client.registerToolCallHandler('open_product_page', {
  onStart: async (payload) => {
    console.log('Tool called:', payload.toolName);
    console.log('Arguments:', payload.arguments);
    window.location.href = `/products/${payload.arguments.productId}`;
    return `Opened product ${payload.arguments.productId}`;
  },
});

// Register handlers for the webhook and knowledge tools

client.registerToolCallHandler('check_order_status', {
  onComplete: async (payload) => {
    const { toolName, result, executionTime } = payload;
    console.log(`Tool ${toolName} completed in ${executionTime}ms:`, result);
  }
})

client.registerToolCallHandler('search_product_docs', {
  onComplete: async (payload) => {
    const { toolName, result, executionTime } = payload;
    console.log(`Tool ${toolName} completed in ${executionTime}ms:`, result);
  }
})

// alternatively you can use the emitted events to register generic handlers
// client.addListener(AnamEvent.TOOL_CALL_COMPLETED, (event) => {
//   console.log(`Tool completed: ${event.toolName} in ${event.executionTime}ms`);
// })


// Handle session ready
client.addListener(AnamEvent.SESSION_READY, () => {
  console.log('Session ready - persona is active');
});

// Connect and start streaming
await client.streamToVideoElement('persona-video');
```

> [!TIP]
>
> Your persona can now search documents, call APIs, and trigger client actions!

## Testing Your Tools

Let's test the complete setup with example conversations:

### Testing Knowledge Tool

**User**: "How do I install the product?"

**Expected flow**:

1. LLM recognizes this as a technical question
2. Invokes `search_product_docs` tool
3. Retrieves relevant chunks from your user guide
4. Responds with accurate installation steps

### Testing Webhook Tool

**User**: "What's the status of my order ORD-12345?"

**Expected flow**:

1. LLM extracts order ID `ORD-12345`
2. Calls `check_order_status` webhook with `orderId: "ORD-12345"`
3. Receives response from your API
4. Tells user the current order status

### Testing Client Tool

**User**: "Show me more details about the premium plan"

**Expected flow**:

1. LLM identifies product name "premium plan"
2. Calls `open_product_page` client tool
3. SDK triggers the registered `open_product_page` handler
4. Navigation happens: `window.location.href = '/products/premium-plan'`

> [!TIP]
>
> Use your browser's developer console to see tool call events in real-time. This helps debug and understand the execution flow.

## Troubleshooting

> [accordion] Knowledge tool returns no results
>
> **Possible causes**:
>
> * Document still processing (check status)
> * Query doesn't match document content
> * Folder ID incorrect
>
> **Solutions**:
>
> 1. Wait for document status to be READY
> 2. Verify lifecycle events are firing i.e. `TOOL_CALL_STARTED`, `TOOL_CALL_COMPLETED` and `TOOL_CALL_FAILED` events.
> 3. Verify expected documents are being read see [ToolCallCompletedPayload.documentsAccessed](https://anam.ai/docs/javascript-sdk/reference/events.md#toolcallcompletedpayload)
> 4. Verify folder ID in tool configuration

> [accordion] Webhook tool times out
>
> **Possible causes**:
>
> * External API is slow (>60s timeout)
> * Network connectivity issues
> * Invalid endpoint URL
>
> **Solutions**:
>
> 1. Check endpoint URL is correct
> 2. Test endpoint independently with curl
> 3. Ensure API returns response within 60 seconds
> 4. Check authentication headers are valid
> 5. Verify lifecycle events are firing i.e. `TOOL_CALL_STARTED`, `TOOL_CALL_COMPLETED` and `TOOL_CALL_FAILED` events.

> [accordion] Client tool event not received
>
> **Possible causes**:
>
> * SDK client not properly initialized
> * Event listener not registered before session starts
> * Tool name mismatch
>
> **Solutions**:
>
> 1. Verify SDK client is initialized with valid session token
> 2. Register handler using `client.registerToolCallHandler(toolName, handler)` before calling `streamToVideoElement`
> 3. Match tool name exactly in your handler (case-sensitive)
> 4. Check browser console for any SDK initialization errors

## Best Practices

### Tool Naming

Use descriptive, action-oriented names:

```typescript theme={"system"}
// ✅ Good
search_product_docs;
check_order_status;
open_checkout_page;

// ❌ Bad
search;
api_call;
tool1;
```

### Tool Descriptions

Be specific about when the LLM should use the tool:

```typescript theme={"system"}
// ✅ Good
description: "Search product documentation when users ask technical questions about features, installation, troubleshooting, or usage";

// ❌ Bad
description: "Searches documents";
```

### System Prompts

Guide the LLM on how to use tools effectively:

```typescript theme={"system"}
systemPrompt: `You are a helpful support agent. You have access to:
- Product documentation (use search_product_docs for technical questions)
- Order tracking system (use check_order_status when users mention order numbers)
- Product pages (use open_product_page when users want to see details)

Always be helpful and proactive. If a user mentions an order number, offer to check its status.`;
```

## Next Steps

> [card] [Client Tool Events](https://anam.ai/docs/personas/tools/client-tools.md)
>
> Learn to handle client tool events in your application

> [card] [Knowledge Tools Deep Dive](https://anam.ai/docs/personas/knowledge/tools.md)
>
> Advanced knowledge tool configuration and optimization

> [card] [Webhook Tools Guide](https://anam.ai/docs/personas/tools/webhook-tools.md)
>
> Integrate external APIs with webhook tools

> [card] [SDK Reference](https://anam.ai/docs/javascript-sdk/reference/events.md#tool-call-events)
>
> Complete SDK documentation for tool events


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.