Tool Calling
Learn how to extend the Cyborg chat assistant with custom tools that can perform actions on behalf of users.
Overview
Tool calling allows the AI assistant to execute custom functions you define. When the user asks the assistant to perform an action, it can call your tools with the appropriate parameters.
Defining Tools
Tools are defined using the useCyborg hook with a JSON Schema-like interface:
import { useCyborg } from '@cyborg-sdk/react'
function ProductPage({ product }) {
useCyborg({
tools: [
{
name: 'add_to_cart',
description: 'Add a product to the shopping cart',
parameters: {
productId: {
type: 'string',
description: 'The product ID to add',
required: true
},
quantity: {
type: 'number',
description: 'Number of items to add',
required: false
}
},
handler: async ({ productId, quantity = 1 }) => {
await cartService.add(productId, quantity)
return { success: true, message: `Added ${quantity} item(s) to cart` }
}
}
]
})
return <ProductDisplay product={product} />
}Tool Definition Interface
interface ToolDefinition {
name: string // Unique tool identifier
description: string // What the tool does (shown to AI)
parameters: Record<string, ToolParameter> // Parameter definitions
handler: (params: any) => Promise<any> // Function to execute
}
interface ToolParameter {
type: 'string' | 'number' | 'boolean' | 'object' | 'array'
description: string // Parameter description (shown to AI)
required?: boolean // Whether parameter is required
enum?: string[] // Allowed values (for string type)
}Parameter Types
String Parameters
{
name: 'search_products',
description: 'Search for products',
parameters: {
query: {
type: 'string',
description: 'Search query',
required: true
},
category: {
type: 'string',
description: 'Product category',
enum: ['electronics', 'clothing', 'home'],
required: false
}
},
handler: async ({ query, category }) => {
return await searchProducts(query, category)
}
}Number Parameters
{
name: 'set_quantity',
description: 'Set item quantity in cart',
parameters: {
itemId: {
type: 'string',
description: 'Cart item ID',
required: true
},
quantity: {
type: 'number',
description: 'New quantity (1-99)',
required: true
}
},
handler: async ({ itemId, quantity }) => {
return await updateCartQuantity(itemId, quantity)
}
}Boolean Parameters
{
name: 'toggle_notifications',
description: 'Enable or disable notifications',
parameters: {
enabled: {
type: 'boolean',
description: 'Whether notifications should be enabled',
required: true
}
},
handler: async ({ enabled }) => {
await setNotifications(enabled)
return { enabled }
}
}Page-Specific Tools
Tools are scoped to where they're registered. Register different tools on different pages:
E-commerce Product Page
function ProductPage({ product }) {
useCyborg({
context: { product },
tools: [
{
name: 'add_to_cart',
description: 'Add this product to cart',
parameters: {
quantity: { type: 'number', description: 'Quantity', required: false }
},
handler: async ({ quantity = 1 }) => {
await cartService.add(product.id, quantity)
return { success: true }
}
},
{
name: 'add_to_wishlist',
description: 'Save this product to wishlist',
parameters: {},
handler: async () => {
await wishlistService.add(product.id)
return { success: true }
}
}
]
})
return <ProductDisplay product={product} />
}Dashboard Page
function Dashboard() {
useCyborg({
tools: [
{
name: 'export_report',
description: 'Export dashboard data as CSV or PDF',
parameters: {
format: {
type: 'string',
description: 'Export format',
enum: ['csv', 'pdf'],
required: true
},
dateRange: {
type: 'string',
description: 'Date range for the report',
enum: ['week', 'month', 'year'],
required: false
}
},
handler: async ({ format, dateRange = 'month' }) => {
const url = await exportService.generate(format, dateRange)
return { downloadUrl: url }
}
}
]
})
return <DashboardView />
}Handling Tool Results
Tool handlers should return meaningful results that the AI can communicate to the user:
Success Response
handler: async ({ productId }) => {
const result = await cartService.add(productId)
return {
success: true,
message: 'Product added to cart',
cartTotal: result.total,
itemCount: result.itemCount
}
}Error Response
handler: async ({ productId }) => {
try {
await cartService.add(productId)
return { success: true }
} catch (error) {
return {
success: false,
error: 'Product is out of stock'
}
}
}Async Operations
Tools support async operations with loading states:
{
name: 'process_order',
description: 'Submit and process the current order',
parameters: {},
handler: async () => {
// Long-running operation
const order = await orderService.submit()
await paymentService.process(order.id)
await emailService.sendConfirmation(order)
return {
success: true,
orderId: order.id,
estimatedDelivery: order.deliveryDate
}
}
}Tool Descriptions Best Practices
Good descriptions help the AI understand when to use each tool:
// Good - Clear and specific
{
name: 'add_to_cart',
description: 'Add a product to the shopping cart. Use when user wants to buy or purchase an item.',
// ...
}
// Bad - Too vague
{
name: 'add_to_cart',
description: 'Adds item',
// ...
}Include Context in Descriptions
{
name: 'apply_discount',
description: 'Apply a discount code to the current order. The code should be alphanumeric and case-insensitive.',
parameters: {
code: {
type: 'string',
description: 'Discount code (e.g., SAVE20, FREESHIP)',
required: true
}
}
}Combining Tools with Context
Tools work best when combined with context:
function CheckoutPage({ cart, user }) {
useCyborg({
context: {
cartItems: cart.items,
cartTotal: cart.total,
userAddress: user.defaultAddress
},
instructions: 'Help the user complete their purchase. Suggest applying discounts if available.',
tools: [
{
name: 'apply_discount',
description: 'Apply discount code to order',
parameters: {
code: { type: 'string', description: 'Discount code', required: true }
},
handler: async ({ code }) => await applyDiscount(code)
},
{
name: 'update_shipping',
description: 'Change shipping address',
parameters: {
addressId: { type: 'string', description: 'Address ID', required: true }
},
handler: async ({ addressId }) => await updateShipping(addressId)
},
{
name: 'place_order',
description: 'Complete the purchase',
parameters: {},
handler: async () => await placeOrder()
}
]
})
return <CheckoutForm cart={cart} />
}Security Considerations
Validate Parameters
Always validate tool parameters:
handler: async ({ quantity }) => {
if (quantity < 1 || quantity > 99) {
return { error: 'Quantity must be between 1 and 99' }
}
// proceed
}Authenticate Actions
Ensure tools respect user permissions:
handler: async ({ orderId }) => {
const order = await orderService.get(orderId)
if (order.userId !== currentUser.id) {
return { error: 'Not authorized to modify this order' }
}
// proceed
}Avoid Sensitive Operations
Don't expose dangerous operations as tools:
// Don't do this
{
name: 'delete_account',
description: 'Permanently delete user account',
// Too dangerous for AI to trigger
}
// Instead, guide users to settings
{
name: 'open_account_settings',
description: 'Open account settings page',
handler: async () => {
router.push('/settings/account')
return { message: 'Opening account settings' }
}
}Next Steps
- useCyborg Hook - Full API reference
- Context-Aware Chat - Dynamic context
- Conversation History - Persist conversations