Building Custom Tools - Uplift AI API Docs

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:

MCP Tools: Model Context Protocol integrations that allow:

Tool Anatomy

Every tool consists of:

{
  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

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

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:

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:

// 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:

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. MCP tools allow your assistant to interact with MCP servers.

Troubleshooting

Tool not being called

Tool timing out

Handler errors

Parameters not received

Support Just reach out to us at founders@upliftai.org, we will love to figure out how to improve the experience.