Cloodot

Creating Skills

Build and deploy your first skill

This guide walks you through creating, testing, and deploying a skill.

Step 1: Plan Your Skill

Define the Skill Purpose

Ask yourself:

  • What problem does this skill solve?
  • What inputs will it need?
  • What output should it return?
  • Is it informational, action-based, or interactive?

Example: Order Status Skill

Purpose: Check the status of a customer order

Inputs:

  • Order ID (required)
  • Customer ID (optional)

Output:

  • Status message
  • Current status
  • Estimated delivery date

Type: Informational

Step 2: Define the Schema

Create the Skill Definition

const orderStatusSkill = {
  slug: "check_order_status",
  name: "Check Order Status",
  description: "Look up the current status of a customer's order",
  prompt: `Use this skill when a customer asks about their order status. 
           Takes an order ID and returns the current status (pending, 
           processing, shipped, delivered, or cancelled) along with 
           estimated delivery date.`,
  
  parameters: {
    type: "object",
    properties: {
      orderId: {
        type: "string",
        description: "The unique order identifier"
      },
      customerId: {
        type: "string",
        description: "Customer ID for verification (optional)"
      }
    },
    required: ["orderId"]
  },
  
  response: {
    type: "object",
    properties: {
      message: {
        type: "string",
        description: "Human-readable status message"
      },
      orderId: {
        type: "string"
      },
      status: {
        type: "string",
        enum: ["pending", "processing", "shipped", "delivered", "cancelled"]
      },
      estimatedDelivery: {
        type: "string",
        description: "ISO 8601 date string"
      },
      trackingUrl: {
        type: "string",
        description: "URL to track the shipment"
      }
    },
    required: ["message", "status"]
  },
  
  buttons: [
    {
      label: "Track Package",
      payload: "TRACK_PACKAGE"
    },
    {
      label: "Request Return",
      payload: "REQUEST_RETURN"
    }
  ]
}

Step 3: Write the Handler Function

Basic Handler Structure

async function handler(input) {
  const { config, parameters, context } = input
  
  try {
    // Extract parameters
    const { orderId, customerId } = parameters
    
    // Validate input
    if (!orderId) {
      return {
        message: "Error: Order ID is required",
        status: "error"
      }
    }
    
    // Logic to fetch order status
    // (This is where you'd call your API, database, etc.)
    const orderStatus = await getOrderStatus(orderId)
    
    // Return result
    return {
      message: `Your order ${orderId} is ${orderStatus.status}`,
      orderId: orderId,
      status: orderStatus.status,
      estimatedDelivery: orderStatus.estimatedDelivery,
      trackingUrl: orderStatus.trackingUrl
    }
    
  } catch (error) {
    return {
      message: `Error checking order status: ${error.message}`,
      status: "error"
    }
  }
}

Using Configuration

If your skill needs API credentials or configuration:

async function handler(input) {
  const { config, parameters } = input
  
  // Access configuration values
  const apiKey = config.apiKey
  const apiEndpoint = config.apiEndpoint
  const timeout = config.timeout || 5000
  
  try {
    // Use config to call external service
    const response = await fetch(`${apiEndpoint}/orders/${parameters.orderId}`, {
      headers: {
        'Authorization': `Bearer ${apiKey}`
      },
      timeout: timeout
    })
    
    const data = await response.json()
    
    return {
      message: `Order status: ${data.status}`,
      ...data
    }
    
  } catch (error) {
    return {
      message: `Failed to check order: ${error.message}`,
      status: "error"
    }
  }
}

Step 4: Define Configuration (If Needed)

If your skill needs configuration values:

const configDefinitions = [
  {
    key: "apiEndpoint",
    label: "API Endpoint",
    type: "STRING",
    description: "Your API endpoint URL",
    required: true,
    order: 1
  },
  {
    key: "apiKey",
    label: "API Key",
    type: "SECRET",
    description: "Your API authentication key",
    required: true,
    isSensitive: true,
    order: 2
  },
  {
    key: "timeout",
    label: "Request Timeout (ms)",
    type: "NUMBER",
    description: "Request timeout in milliseconds",
    required: false,
    defaultValue: "5000",
    order: 3
  }
]

Step 5: Create the SkillSet

Combine all skills into a SkillSet:

const skillSet = {
  name: "Order Management",
  slug: "order_management",
  tagline: "Order lookup and management skills",
  description: "Skills for checking order status, processing returns, and managing shipments",
  visibility: "PRIVATE",
  
  skills: [
    orderStatusSkill,
    // ... other skills
  ],
  
  configDefinitions: [
    {
      key: "apiEndpoint",
      label: "API Endpoint",
      type: "STRING",
      required: true,
      order: 1
    },
    {
      key: "apiKey",
      label: "API Key",
      type: "SECRET",
      required: true,
      isSensitive: true,
      order: 2
    }
  ],
  
  requiredIntegrationProviders: ["YOUR_API"] // If applicable
}

Step 6: Test Your Skill

Testing Locally

Before deployment, test your skill logic:

// Test data
const testInput = {
  config: {
    apiEndpoint: "https://api.example.com",
    apiKey: "test-key"
  },
  parameters: {
    orderId: "ORD-12345"
  },
  context: {
    conversationId: "conv_123",
    organizationId: "org_123"
  }
}

// Run handler
handler(testInput).then(result => {
  console.log("Result:", result)
})

Test Cases to Cover

  • Valid input with all parameters
  • Valid input with only required parameters
  • Invalid/missing required parameters
  • Edge cases (empty strings, null values, etc.)
  • Error scenarios (API down, timeout, etc.)
  • Boundary conditions

Step 7: Deploy the SkillSet

Via Dashboard

  1. Go to AI Settings > Skills
  2. Click Create New SkillSet
  3. Fill in basic information
  4. Add skills one by one
  5. Configure values if needed
  6. Deploy to make live

Via API

const response = await fetch('/api/skillsets', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer YOUR_API_KEY'
  },
  body: JSON.stringify(skillSet)
})

const created = await response.json()
console.log('SkillSet created:', created.id)

Step 8: Connect to Your AI Persona

Once deployed, connect the SkillSet to your AI persona:

  1. Go to AI Settings > Personas
  2. Select the persona
  3. Go to Skills tab
  4. Enable the SkillSet
  5. Configure values (API key, endpoint, etc.)
  6. Test in conversation

Complete Example: Payment Processing Skill

// Skill definition
const processPaymentSkill = {
  slug: "process_payment",
  name: "Process Payment",
  description: "Process a payment for a customer",
  prompt: `Process a customer payment. Accepts amount and payment method.
           Returns payment confirmation or error.`,
  
  parameters: {
    type: "object",
    properties: {
      amount: {
        type: "number",
        description: "Payment amount in dollars"
      },
      paymentMethod: {
        type: "string",
        enum: ["card", "bank", "crypto"],
        description: "Payment method"
      },
      customerId: {
        type: "string",
        description: "Customer ID"
      }
    },
    required: ["amount", "paymentMethod"]
  },
  
  response: {
    type: "object",
    properties: {
      message: { type: "string" },
      transactionId: { type: "string" },
      status: { type: "string" },
      amount: { type: "number" }
    }
  }
}

// Handler implementation
async function handler(input) {
  const { config, parameters } = input
  const { amount, paymentMethod, customerId } = parameters
  
  try {
    // Validate amount
    if (amount <= 0) {
      return {
        message: "Error: Invalid amount",
        status: "failed"
      }
    }
    
    // Call payment processor
    const response = await fetch(`${config.processorUrl}/charge`, {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${config.apiKey}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        amount,
        method: paymentMethod,
        customerId
      })
    })
    
    const result = await response.json()
    
    if (!response.ok) {
      return {
        message: `Payment failed: ${result.error}`,
        status: "failed"
      }
    }
    
    return {
      message: `Payment of $${amount} processed successfully`,
      transactionId: result.transactionId,
      status: "success",
      amount
    }
    
  } catch (error) {
    console.error('Payment error:', error)
    return {
      message: `System error: ${error.message}`,
      status: "error"
    }
  }
}

Troubleshooting

Handler Not Found

Error: "handler function not found"

Solution: Ensure your skill code includes:

async function handler(input) {
  // ...
}

Configuration Not Available

Error: config.apiKey is undefined

Solution:

  1. Check configuration is defined in SkillSet
  2. Ensure values are set in persona settings
  3. Verify config key matches the code

Skill Not Appearing in AI

Problem: Skill doesn't show up in conversation

Solutions:

  1. Confirm SkillSet is deployed
  2. Check persona has the SkillSet enabled
  3. Verify prompt is clear enough for AI to understand
  4. Test with explicit requests ("use the check order status skill")

Timeouts

Problem: Skill execution timing out

Solutions:

  1. Reduce external API call timeout
  2. Optimize database queries
  3. Use caching for common requests
  4. Increase Cloudflare worker timeout

Next Steps

On this page