Skip to content

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:

tsx
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

typescript
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

tsx
{
  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

tsx
{
  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

tsx
{
  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

tsx
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

tsx
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

tsx
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

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

tsx
{
  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:

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

tsx
{
  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:

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

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

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

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

Built with VitePress