Skill Schema & Validation
Define skill structure and validation requirements
Skill definitions must conform to a strict schema to be validated and deployed correctly.
Skill Definition Schema
Complete Skill Schema
{
slug: string // Required: Unique identifier
name: string // Required: Display name (1-100 chars)
description: string // Required: What it does (1-500 chars)
prompt: string // Required: AI description (1-2000 chars)
definition: string // Required: JavaScript code
parameters: Record<string, any> // Required: Input schema
response: Record<string, any> // Required: Output schema
buttons?: Array<{ // Optional: Quick action buttons
label: string
payload: string
}>
}Field Validation Rules
slug
- Type: String
- Length: 1-64 characters
- Pattern:
^[a-z0-9_]+$(lowercase, numbers, underscores only) - Uniqueness: Must be unique within the SkillSet
- Examples:
check_order_status,send_email_2,process_payment
name
- Type: String
- Length: 1-100 characters
- Purpose: Display name shown to users and in UI
- Examples: "Check Order Status", "Send Email", "Process Payment"
description
- Type: String
- Length: 1-500 characters
- Purpose: Brief explanation of what the skill does
- Examples: "Look up the status of a customer order in the system"
prompt
- Type: String
- Length: 1-2000 characters
- Purpose: Instructions for the AI on how to use this skill
- Usage: The AI reads this when deciding whether to call the skill
- Format: Should describe:
- When to use this skill
- What parameters it expects
- What information it returns
- Any important caveats
Good Prompt Example:
Use this skill to check the delivery status of a customer's order.
It takes the order ID as input and returns the current status
(pending, processing, shipped, delivered, cancelled).definition
- Type: String (JavaScript/TypeScript code)
- Requirements:
- Must contain a
handlerfunction - Must be async function
- Cannot use dangerous APIs (eval, require fs, etc.)
- Must contain a
- Validation: Code is analyzed for:
- Presence of handler function
- Dangerous operations (blocked)
- Syntax validity
Valid Definition Structure:
async function handler(input) {
const { config, parameters, context } = input
// Your logic here
return {
message: "Response",
// ... other fields
}
}Invalid Patterns (will be rejected):
// ❌ Missing handler function
function processOrder() { return "result" }
// ❌ Using dangerous APIs
const fs = require('fs')
// ❌ Using eval
eval(userCode)
// ❌ Non-async handler
function handler(input) { }parameters
- Type: JSON Schema object
- Purpose: Defines expected input from the AI
- Format: JSON Schema format
Example - Order Status Check:
{
"type": "object",
"properties": {
"orderId": {
"type": "string",
"description": "The unique order identifier"
},
"customerId": {
"type": "string",
"description": "Customer ID (optional for verification)"
}
},
"required": ["orderId"]
}Parameter Types Supported:
stringnumberintegerbooleanarrayobject
response
- Type: JSON Schema object
- Purpose: Defines structure of data returned by the skill
- Format: JSON Schema format
- AI Usage: AI uses this to understand what it will receive
Example - Order Status Response:
{
"type": "object",
"properties": {
"message": {
"type": "string",
"description": "Status message for the user"
},
"orderId": {
"type": "string"
},
"status": {
"type": "string",
"enum": ["pending", "processing", "shipped", "delivered", "cancelled"]
},
"estimatedDelivery": {
"type": "string",
"description": "ISO date string"
}
},
"required": ["message", "status"]
}buttons (Optional)
Quick action buttons that appear after skill execution.
Structure:
{
label: string // 1-50 characters, button text
payload: string // 1-200 characters, action identifier
}Example:
buttons: [
{
label: "Track Package",
payload: "TRACK_PACKAGE"
},
{
label: "Return Order",
payload: "RETURN_ORDER"
}
]Configuration Schema
Skills can accept configuration values from the organization:
Config Definition
{
key: string // Unique config key
label: string // Display label
type: ConfigType // Value type
description?: string // Help text
required: boolean // Must be set?
defaultValue?: string // Default value
order: number // Display order
options: string[] // For SELECT types
validation?: string // Regex or validation rule
isSensitive: boolean // Hide in UI (for API keys)
}Supported Config Types
enum ConfigValueType {
STRING = "STRING", // Text input
NUMBER = "NUMBER", // Number input
BOOLEAN = "BOOLEAN", // Checkbox
SELECT = "SELECT", // Dropdown list
MULTI_SELECT = "MULTI_SELECT", // Multiple selection
SECRET = "SECRET" // Hidden API key/password
}Config Definition Example:
{
key: "api_key",
label: "API Key",
type: "SECRET",
description: "Your payment processor API key",
required: true,
isSensitive: true,
order: 1
}SkillSet Definition
SkillSets are collections of related skills:
{
name: string // 1-100 chars
slug: string // 1-64 chars, ^[a-z0-9_]+$
tagline?: string // 1-200 chars
description: string // 1-1000 chars
logoImageUrl?: string // Valid URL
bannerImageUrl?: string // Valid URL
visibility: 'PUBLIC' | 'PRIVATE' // Distribution
privacyPolicyUrl?: string // Valid URL
termsOfServiceUrl?: string // Valid URL
skills: SkillDefinition[] // At least 1 skill
configDefinitions?: ConfigDefinition[] // Optional shared config
requiredIntegrationProviders?: string[] // Required integrations
}Handler Function Signature
async function handler(input: {
config: Record<string, any>
parameters: Record<string, any>
context: {
conversationId?: string
organizationId?: string
// ... organization context
}
}): Promise<{
message: string // Response to AI (required)
[key: string]: any // Other response fields
}>Validation Examples
✅ Valid Skill
{
slug: "get_weather",
name: "Get Weather",
description: "Check weather for a location",
prompt: "Use to get current weather information",
definition: `
async function handler(input) {
const { parameters } = input
return {
message: \`Weather in \${parameters.city}: Sunny\`,
temperature: 72
}
}
`,
parameters: {
type: "object",
properties: {
city: { type: "string" }
},
required: ["city"]
},
response: {
type: "object",
properties: {
message: { type: "string" },
temperature: { type: "number" }
}
}
}❌ Invalid Skill
{
slug: "GET-WEATHER", // ❌ Invalid slug (uppercase, hyphen)
name: "Get Weather For Current Location And Time Zone", // ❌ Too long
description: "Weather", // ❌ Too short
prompt: "", // ❌ Required, empty
definition: "function test() {}", // ❌ No handler function
parameters: {/* ... */},
response: {/* ... */}
}Error Messages
Common Validation Errors
| Error | Cause | Fix |
|---|---|---|
| "slug must be 1-64 chars, alphanumeric + underscore" | Invalid slug format | Use only lowercase, numbers, underscores |
| "slug must be unique" | Slug already exists | Choose a different slug |
| "handler function not found" | No handler in definition | Define async function handler(input) {} |
| "eval not allowed in definition" | Using eval() | Remove eval calls |
| "require not allowed in definition" | Using require() | Remove require calls |
| "name must be 1-100 characters" | Name too long/short | Adjust name length |
| "parameters must be valid JSON schema" | Invalid schema | Fix JSON schema syntax |
Deployment Checklist
Before deploying a SkillSet:
- All slug values are unique
- Handler function is defined in each skill
- No dangerous APIs (eval, require, fs)
- Parameters schema is valid JSON Schema
- Response schema is valid JSON Schema
- Description and prompt are meaningful
- Configuration values have defaults if optional
- Config keys are unique within SkillSet
- URLs (logo, privacy, terms) are valid if provided