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