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

# Building Custom Tools

> Extend your assistant with powerful custom functions

<Note>
  **Beta Feature**: Tools API is in beta and actively being improved based on feedback.
</Note>

## What are Tools?

Tools are functions executed on the user's device via RPC from the UpliftAI Agent. This architecture enables two types of tool integrations:

**Custom Tools**: Functions you implement directly in your application to:

* Access external APIs and services
* Perform calculations and data processing
* Interact with databases
* Execute business logic

**MCP Tools**: Model Context Protocol integrations that allow:

* Connection to MCP servers
* Access to local file systems
* Integration with development environments
* Bridge to enterprise systems and databases

## Tool Anatomy

Every tool consists of:

```javascript theme={null}
{
  name: "tool_name",           // Unique identifier
  description: "What it does",  // Used by LLM to decide when to use
  parameters: {                 // JSON Schema for parameters
    type: "object",
    properties: {
      param1: {
        type: "string",
        description: "Parameter description"
      }
    },
    required: ["param1"]
  },
  timeout: 10,                  // Seconds before timeout
  handler: async (data) => {    // Your implementation
    // Process and return result
  }
}
```

## Creating Tools

### Basic Tool Example

```javascript theme={null}
const weatherTool = {
  name: 'get_weather',
  description: 'Get current weather for any city',
  parameters: {
    type: 'object',
    properties: {
      city: {
        type: 'string',
        description: 'City name'
      },
      units: {
        type: 'string',
        enum: ['celsius', 'fahrenheit'],
        description: 'Temperature units'
      }
    },
    required: ['city']
  },
  timeout: 10,
  handler: async (data) => {
    const payload = JSON.parse(data.payload);
    const { city, units = 'celsius' } = payload.arguments.raw_arguments;
    
    // Call weather API
    const response = await fetch(`https://api.weather.com/v1/current?city=${city}`);
    const weather = await response.json();
    
    return JSON.stringify({
      result: weather,
      presentationInstructions: `The current temperature in ${city} is ${weather.temp}°${units[0].toUpperCase()}`
    });
  }
};
```

### Advanced Tool with Error Handling

```javascript theme={null}
const addToCartTool = {
  name: 'add_to_cart_and_checkout',
  description: 'Add items to shopping cart and optionally navigate to checkout',
  parameters: {
    type: 'object',
    properties: {
      items: {
        type: 'array',
        items: {
          type: 'object',
          properties: {
            productId: { type: 'string' },
            quantity: { type: 'number' }
          }
        },
        description: 'Products to add to cart'
      },
      goToCheckout: {
        type: 'boolean',
        description: 'Navigate to checkout after adding items'
      }
    },
    required: ['items']
  },
  timeout: 5,
  handler: async (data) => {
    try {
      const payload = JSON.parse(data.payload);
      const { items, goToCheckout = false } = payload.arguments.raw_arguments;
      
      // Validate items array
      if (!Array.isArray(items) || items.length === 0) {
        throw new Error('No items provided');
      }
      
      // Add items to cart with fun animation
      let totalAdded = 0;
      for (const item of items) {
        // Add to cart state
        await cart.addItem(item.productId, item.quantity);
        totalAdded += item.quantity;
        
        // Trigger fun cart animation
        document.querySelector('.cart-icon')?.classList.add('bounce');
      }
      
      // Update cart badge
      updateCartBadge(totalAdded);
      
      // Navigate to checkout if requested
      if (goToCheckout) {
        // Small delay for animation to complete
        setTimeout(() => {
          window.location.href = '/checkout';
        }, 500);
        
        return JSON.stringify({
          result: { itemsAdded: totalAdded, navigating: true },
          presentationInstructions: `Great! I've added ${totalAdded} items to your cart. Taking you to checkout now! 🛒`
        });
      }
      
      return JSON.stringify({
        result: { itemsAdded: totalAdded },
        presentationInstructions: `I've added ${totalAdded} items to your cart! Say "checkout" when you're ready to purchase.`
      });
      
    } catch (error) {
      console.error('Cart tool error:', error);
      return JSON.stringify({
        error: error.message,
        presentationInstructions: 'Oops! I couldn\'t add those items to your cart. Please try again.'
      });
    }
  }
};
```

## Tool Response Format

The response is a string, but to enhance LLM response and understanding, a JSON structure like the following is recommended:

```javascript theme={null}
return JSON.stringify({
  // Required: The actual result data
  result: any,
  
  // Optional: How to present to user
  presentationInstructions: string,
  
  // Optional: Error information
  error: string
})
```

## Registering Tools

If you want to use tools client side, you must register their implementations.

### Static Registration

Register tools when creating the assistant or room:

```jsx theme={null}
// During assistant creation (API)
{
  config: {
    agent: {
      tools: [weatherTool, databaseTool]
    }
  }
}

// In React component
<UpliftAIRoom
  token={token}
  serverUrl={wsUrl}
  tools={[weatherTool, databaseTool]}
>
  <AssistantView />
</UpliftAIRoom>
```

### Dynamic Registration

Add or remove tools during a session:

```javascript theme={null}
const { addTool, removeTool, updateTool } = useUpliftAIRoom();

// Add a new tool
await addTool({
  name: 'calculator',
  description: 'Perform mathematical calculations',
  parameters: { /* ... */ },
  handler: async (data) => { /* ... */ }
});

// Remove a tool
await removeTool('calculator');

// Update existing tool
await updateTool({
  name: 'calculator',
  description: 'Advanced calculator with trigonometry',
  // ... updated configuration
});
```

## MCP (Model Context Protocol) Integration

**Coming soon** let us know if you want MCP integrations at [founders@upliftai.org](mailto:founders@upliftai.org)

MCP tools allow your assistant to interact with MCP servers

## Troubleshooting

<AccordionGroup>
  <Accordion title="Tool not being called">
    * Ensure tool name is unique
    * Check description clearly explains when to use
    * Verify parameters schema is valid JSON Schema
    * Test with explicit prompts mentioning the tool
    * Ensure the configuration and registered name match
  </Accordion>

  <Accordion title="Tool timing out">
    * Increase timeout value
    * Optimize handler performance
    * Implement caching for repeated calls
    * Consider async processing for long operations
  </Accordion>

  <Accordion title="Handler errors">
    * Always wrap in try-catch
    * Return valid JSON even on error
    * Log errors for debugging
    * Test handler independently
  </Accordion>

  <Accordion title="Parameters not received">
    * Check payload parsing
    * Verify parameter names match schema
    * Use raw\_arguments for access
    * Validate required fields
  </Accordion>

  <Accordion title="Support">
    Just reach out to us at [founders@upliftai.org](mailto:founders@upliftai.org), we will love to figure out how to improve the experience.
  </Accordion>
</AccordionGroup>
