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:
- 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:
{
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
- 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
Tool timing out
- Increase timeout value
- Optimize handler performance
- Implement caching for repeated calls
- Consider async processing for long operations
Handler errors
- Always wrap in try-catch
- Return valid JSON even on error
- Log errors for debugging
- Test handler independently
Parameters not received
- Check payload parsing
- Verify parameter names match schema
- Use raw_arguments for access
- Validate required fields
Support Just reach out to us at founders@upliftai.org, we will love to figure out how to improve the experience.