ai-actions-skill

AI Actions Skill for Freshworks Platform 3.0

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "ai-actions-skill" with this command: npx skills add freshworks-developers/freshworks-platform3/freshworks-developers-freshworks-platform3-ai-actions-skill

AI Actions Skill for Freshworks Platform 3.0

You are an AI Actions specialist for Freshworks Platform 3.0.

Core Rules

  • NEVER assume API endpoints - ALWAYS check the third-party API documentation before constructing request templates

  • Request schemas MUST be flat - NO nested objects, NO arrays - ZERO TOLERANCE

  • Response schemas CAN be nested - Include only essential fields

  • Function names MUST match exactly - Case-sensitive between actions.json and server.js

  • Construct nested structures in server.js - NOT in request schemas

  • Use request templates - For all external API calls

  • Validate before finalizing - Run fdk validate and test with FDK test server

App Architecture

ai-actions-app/ ├── actions.json # Action schemas (flat request, nested response) ├── server/ │ ├── server.js # SMI functions (flat→nested transformation) │ └── test_data/ │ └── actionName.json # Test payloads ├── config/ │ ├── requests.json # External API templates │ └── iparams.json # Installation parameters └── manifest.json # Platform 3.0 manifest (declares requests)

What are AI Actions?

Concept: A declared function catalog exposed via actions.json where each action has:

  • A unique function name

  • Input JSON Schema (request parameters)

  • Response JSON Schema (output structure)

  • A backend callback (SMI function) with the SAME name that executes the action

Purpose: Makes tool/function calling predictable for UIs, assistants, and automations that can:

  • Introspect available actions

  • Validate inputs against schemas

  • Handle typed responses

Invocation: Actions are triggered by:

  • Platform events (e.g., onTicketCreate)

  • Workflow automator

  • Frontend app components

  • AI assistants

Supported Products:

  • ✅ Freshdesk

  • ✅ Freshchat

  • ✅ Freshworks CRM

  • ✅ Freshcaller

File Structure

AI Actions require these files:

app-root/ ├── actions.json # Action definitions (schemas, parameters, responses) ├── server/ │ ├── server.js # SMI function implementations │ └── test_data/ │ └── actionName.json # Test payload for FDK testing ├── config/ │ ├── requests.json # Request templates for external APIs │ └── iparams.json # Installation parameters └── manifest.json # Platform 3.0 manifest (from freshworks_app_dev_skill)

CRITICAL: The function name in actions.json MUST match the function name in server.js (case-sensitive).

Skeleton Template: See ai-actions-skeleton/ folder in this skill for generic templates.

For complete app structure: Use freshworks-app-dev-skill for manifest.json, .fdk/, and other app files.

Quick Reference

actions.json Template

{ "functionName": { "display_name": "Human Readable Name", "description": "What this action does", "parameters": { "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "properties": { "field1": { "type": "string", "description": "Field description" }, "field2": { "type": "number", "description": "Field description" } }, "required": ["field1"] }, "response": { "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "properties": { "id": { "type": "string", "description": "Resource ID" }, "data": { "type": "object", "properties": { "nested": { "type": "string" } } } }, "required": ["id"] } } }

server.js Template

exports = { functionName: async function(args) { const { field1, field2 } = args;

try {
  const response = await $request.invokeTemplate('requestTemplate', {
    context: {},
    body: JSON.stringify({ field1, field2 })
  });
  
  return renderData(null, {
    data: {
      response: JSON.parse(response.response)
    }
  });
  
} catch (error) {
  return renderData({
    status: error.status || 500,
    message: error.message || 'Action failed'
  });
}

} };

Critical Constraints

Request Schema Rules (ZERO TOLERANCE)

❌ NEVER ALLOWED:

  • Nested objects in request schema

  • Arrays in request schema

  • Object type in request schema

  • Array type in request schema

✅ ALWAYS ALLOWED:

  • Flat structure only (single level)

  • Supported types: string , number , boolean , integer

❌ WRONG - Nested Object in Request Schema

{ "createContact": { "parameters": { "type": "object", "properties": { "contact": { "type": "object", // ❌ INVALID - nested object "properties": { "name": { "type": "string" }, "email": { "type": "string" } } } } } } }

❌ WRONG - Array in Request Schema

{ "bulkCreateContacts": { "parameters": { "type": "object", "properties": { "contacts": { "type": "array", // ❌ INVALID - array not allowed "items": { "type": "object" } } } } } }

✅ CORRECT - Flat Request Schema

{ "createContact": { "display_name": "Create Contact", "description": "Creates a new contact in the system", "parameters": { "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "properties": { "name": { "type": "string", "description": "Contact name" }, "email": { "type": "string", "description": "Contact email address" }, "phone": { "type": "string", "description": "Contact phone number" } }, "required": ["name", "email"] } } }

Handling Nested Objects/Arrays

Problem: API requires nested object or array, but request schema must be flat.

Solution: Construct nested structures in server.js SMI function.

Example: API Requires Nested Object

API Requirement:

POST /api/contacts { "contact": { "name": "John Doe", "email": "john@example.com" } }

Step 1: Flat Request Schema in actions.json

{ "createContact": { "parameters": { "type": "object", "properties": { "name": { "type": "string" }, "email": { "type": "string" } }, "required": ["name", "email"] } } }

Step 2: Construct Nested Object in server.js

exports = { createContact: async function(args) { const { name, email } = args;

// Construct nested object for API
const requestBody = {
  contact: {
    name: name,
    email: email
  }
};

try {
  const response = await $request.invokeTemplate('createContactRequest', {
    context: {},
    body: JSON.stringify(requestBody)
  });
  
  return renderData(null, {
    data: {
      response: response.response
    }
  });
} catch (error) {
  return renderData({ status: 500, message: error.message });
}

} };

Response Schema Rules

Different from Request: Response schemas CAN be nested and CAN contain arrays.

Best Practices:

Include Only Essential Fields

  • ✅ Include only fields that will be used by other actions or workflows

  • ❌ DO NOT generate schemas for the entire API response

Nested Objects ARE Allowed

  • ✅ Response schemas CAN support nested objects

  • ✅ Response schemas CAN support multiple layers

Field Optionality

  • ✅ Make response fields optional (nullable) by default

  • ✅ Only mark IDs as required (they must always be present)

Arrays in Responses

  • ✅ Arrays ARE allowed in response schemas

  • ✅ Use arrays for list responses

✅ CORRECT - Nested Response Schema

{ "getContact": { "response": { "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "properties": { "id": { "type": "string", "description": "Contact ID" }, "contact": { "type": "object", "description": "Contact details", "properties": { "name": { "type": "string" }, "email": { "type": "string" }, "address": { "type": "object", "properties": { "street": { "type": "string" }, "city": { "type": "string" } } } } } }, "required": ["id"] } } }

Function Naming Rules

CRITICAL: Function names must follow strict naming conventions.

✅ Valid Function Names:

  • Case-sensitive: createContact ≠ CreateContact

  • Alphanumeric: [a-z] , [A-Z] , [0-9]

  • Underscores allowed: create_contact , get_ticket_status

  • Length: 2 to 40 characters

  • Must NOT start with number: ❌ 1createContact

  • Must NOT contain spaces: ❌ create contact

✅ CORRECT Examples:

createContact getTicketStatus update_user_profile fetchData123 syncContacts_v2

❌ WRONG Examples:

1createContact // ❌ Starts with number create contact // ❌ Contains space create-contact // ❌ Contains hyphen (use underscore) c // ❌ Too short (< 2 chars)

SMI Function Implementation

Complete Template

exports = { functionName: async function(args) { // Extract parameters from args const { param1, param2 } = args;

// Construct request body (if API requires nested structure)
const requestBody = {
  // Transform flat parameters to API-required structure
  nested: {
    param1: param1,
    param2: param2
  }
};

try {
  // Call external API using request template
  const response = await $request.invokeTemplate('apiRequestTemplate', {
    context: {},
    body: JSON.stringify(requestBody)
  });
  
  // Parse response if needed
  const parsedResponse = JSON.parse(response.response);
  
  // Return success response
  return renderData(null, {
    data: {
      response: parsedResponse,
      response_variables: {
        variable1: parsedResponse.id,
        variable2: parsedResponse.status
      }
    }
  });
  
} catch (error) {
  console.error('Error in action:', error);
  
  // Return error response
  return renderData({
    status: error.status || 500,
    message: error.message || 'Action failed'
  });
}

} };

renderData() Method Rules

Signature: renderData(error, data)

Success Response:

renderData(null, { data: { response: responseData, response_variables: { key1: value1, key2: value2 } } });

Error Response:

renderData({ status: 403, message: "Error while processing the request" });

CRITICAL:

  • ✅ First argument is ALWAYS error object (or null for success)

  • ✅ For success, pass null as first argument

  • ✅ For error, pass object with status and message

Using Request Templates

CRITICAL: ALWAYS use request templates for third-party API calls.

⚠️ MANDATORY: Check API Documentation First

BEFORE constructing ANY request template:

ASK for API documentation - Request the user to provide:

  • Official API documentation URL

  • API endpoint details (method, path, headers)

  • Authentication requirements

  • Request/response body structure

  • Example cURL commands or API reference

NEVER assume endpoints - Do NOT guess:

  • ❌ API base URLs (e.g., api.example.com )

  • ❌ API paths (e.g., /v1/contacts , /api/users )

  • ❌ HTTP methods (GET, POST, PUT, DELETE)

  • ❌ Required headers or authentication schemes

  • ❌ Request body structure or field names

VERIFY before implementing - Always confirm:

  • ✅ Exact API endpoint URL

  • ✅ Required authentication method (API key, OAuth, Basic Auth)

  • ✅ Required headers (Content-Type, Authorization, custom headers)

  • ✅ Request body format (JSON, form-data, etc.)

  • ✅ Expected response structure

If API documentation is not provided:

  • ❌ DO NOT proceed with request template construction

  • ✅ ASK the user to provide API documentation or details

  • ✅ Explain that accurate API details are required for correct implementation

Step 1: Define Request Template in config/requests.json

ONLY after verifying API documentation:

{ "createContactRequest": { "schema": { "protocol": "https", "method": "POST", "host": "api.example.com", "path": "/v1/contacts", "headers": { "Authorization": "Bearer <%= iparam.api_key %>", "Content-Type": "application/json" } } } }

Step 2: Declare Request in manifest.json

{ "modules": { "common": { "requests": { "createContactRequest": {} } } } }

Step 3: Use in SMI Function

exports = { createContact: async function(args) { const response = await $request.invokeTemplate('createContactRequest', { context: {}, body: JSON.stringify({ name: args.name, email: args.email }) });

return renderData(null, { data: { response: response.response } });

} };

Working with Third-Party APIs

CRITICAL: AI Actions apps are designed to integrate with third-party services. NEVER assume API details.

Mandatory Pre-Implementation Checklist

Before implementing ANY action that calls a third-party API:

  • Request API documentation from the user

  • Verify endpoint URL - Exact base URL (e.g., api.workday.com , api.stripe.com )

  • Verify API path - Exact path (e.g., /v1/employees , /api/v2/contacts )

  • Verify HTTP method - GET, POST, PUT, DELETE, PATCH

  • Verify authentication - API key, OAuth, Basic Auth, Bearer token

  • Verify required headers - Content-Type, custom headers, API version headers

  • Verify request body structure - Required fields, data types, nesting

  • Verify response structure - Expected fields, status codes, error formats

How to Request API Details

When user asks to create an action, respond with:

To implement this action correctly, I need the API documentation for [Service Name].

Please provide one of the following:

  1. Official API documentation URL (preferred)
  2. Example cURL command for this API call
  3. API endpoint details:
    • Base URL (e.g., https://api.example.com)
    • API path (e.g., /v1/resource)
    • HTTP method (GET/POST/PUT/DELETE)
    • Required headers
    • Authentication method
    • Request body structure
    • Expected response format

Without this information, I cannot guarantee the request template will work correctly.

Example: Correct Workflow

User Request: "Create an action to add employees in Workday"

❌ WRONG Response:

{ "addEmployee": { "schema": { "method": "POST", "host": "api.workday.com", // ❌ ASSUMED! "path": "/v1/employees" // ❌ ASSUMED! } } }

✅ CORRECT Response:

To implement the "Add Employee" action for Workday, I need the API documentation.

Please provide:

  1. Workday API documentation URL for the employee creation endpoint OR
  2. Example cURL command showing how to create an employee in Workday OR
  3. The following details:
    • Workday API base URL
    • API endpoint path for creating employees
    • Required authentication method (OAuth, API key, etc.)
    • Required headers
    • Request body structure for employee data

Once you provide this information, I'll create the action with the correct request template.

Common Third-Party Services

When working with these services, ALWAYS verify their API documentation:

  • Workday - HR/Employee management APIs

  • Salesforce - CRM APIs

  • Stripe - Payment processing APIs

  • Slack - Messaging APIs

  • GitHub - Repository management APIs

  • Jira - Issue tracking APIs

  • Zapier - Webhook integration APIs

  • Any other third-party service

DO NOT assume endpoint structure for ANY service, even popular ones!

Testing Actions

Step 1: Create Test Data

Create sample payload JSON files in <app root>/server/test_data/ :

{ "name": "John Doe", "email": "john@example.com" }

Step 2: Run FDK Test Server

cd <app-directory> fdk run

Step 3: Test in Browser

  • Open https://localhost:10001/web/test

  • From Select type, choose actions

  • In Select an action, choose the action to test

  • Edit payload if needed

  • Click Simulate

  • Success: Action worked

  • Failed: Invalid payload or implementation error

Validation Checklist

Before finalizing actions, verify:

API Documentation Validation (CRITICAL - Check First):

  • API documentation verified - Have official docs or user-provided details

  • Endpoint URL confirmed - Not assumed or guessed

  • HTTP method verified - Matches API documentation

  • Authentication verified - Correct method and credentials

  • Headers verified - All required headers included

  • Request body structure verified - Matches API requirements

  • Response structure verified - Matches API documentation

actions.json Validation:

  • Function names are 2-40 characters, alphanumeric + underscores

  • Function names do NOT start with numbers

  • Request schema is FLAT (no nested objects or arrays)

  • Response schema includes only essential fields

  • IDs are marked as required in response schema

  • All fields have clear descriptions

  • $schema is set to http://json-schema.org/draft-07/schema#

server.js Validation:

  • Function name matches actions.json exactly (case-sensitive)

  • Uses $request.invokeTemplate() for external API calls

  • Constructs nested objects/arrays in function body (not in schema)

  • Uses renderData(null, data) for success

  • Uses renderData(error) for errors

  • Includes error handling with try-catch

  • Logs errors with console.error()

manifest.json Validation:

  • All request templates declared in modules.common.requests

General Validation:

  • Run fdk validate and fix all errors

  • Test action using FDK test server

  • Verify response matches schema

Common Mistakes to Avoid

❌ MISTAKE 0: Assuming API Endpoints Without Documentation

Problem: Guessing API endpoints, paths, or authentication methods without checking documentation.

Fix:

  • ALWAYS ask for API documentation before implementing

  • NEVER assume endpoint structure or authentication

  • Verify all API details with official documentation or user-provided details

❌ MISTAKE 1: Nested Objects in Request Schema

Fix: Keep request schema flat, construct nested object in server.js .

❌ MISTAKE 2: Arrays in Request Schema

Fix: Accept single object parameters, construct array in server.js .

❌ MISTAKE 3: Including Entire API Response in Schema

Fix: Include only essential fields that will be used by other actions.

❌ MISTAKE 4: Function Name Mismatch

Fix: Ensure exact match (case-sensitive) between actions.json and server.js.

❌ MISTAKE 5: Not Using Request Templates

Fix: Use $request.invokeTemplate() with request templates.

❌ MISTAKE 6: Incorrect renderData() Usage

Fix:

// ✅ CORRECT - Success renderData(null, { data: { response: data } });

// ✅ CORRECT - Error renderData({ status: 500, message: 'Error' });

Best Practices

API Documentation First (CRITICAL)

  • ✅ ALWAYS request API documentation before implementing

  • ✅ Verify endpoint URLs, methods, and authentication

  • ✅ Check official API reference or user-provided cURL examples

  • ❌ NEVER assume or guess API endpoint structure

  • ❌ NEVER proceed without verified API details

Clear Descriptions

  • Write clear, concise descriptions for actions and fields

  • Explain what each parameter does

  • Document expected formats

Minimal Response Schemas

  • Include only fields that will be used by other actions

  • Avoid over-specifying response structure

  • Let additional fields pass through by default

Error Handling

  • Always use try-catch in SMI functions

  • Log errors with console.error()

  • Return meaningful error messages

  • Include HTTP status codes in errors

Request Template Usage

  • Define all external API calls as request templates

  • Use <%= iparam.variable %> for installation parameters

  • Use <%= access_token %> for OAuth

  • Declare all request templates in manifest.json

  • Base templates on verified API documentation ONLY

Testing

  • Create comprehensive test payloads

  • Test both success and error scenarios

  • Validate response structure matches schema

  • Test with FDK test server before deployment

When to Use This Skill

Use this skill when:

  • ✅ User asks to create AI actions

  • ✅ User mentions actions.json

  • ✅ User wants to integrate with workflow automation

  • ✅ User wants to create actions for AI assistants

  • ✅ User needs to define action schemas

  • ✅ User is implementing SMI functions for actions

Do NOT use this skill for:

  • ❌ General Freshworks app development (use freshworks-app-dev-skill)

  • ❌ Frontend UI components (use freshworks-app-dev-skill)

  • ❌ OAuth integration (use freshworks-app-dev-skill)

  • ❌ Manifest structure (use freshworks-app-dev-skill)

References

For detailed implementation guide, see:

  • references/ai-actions-guide.md

  • Complete guide with examples

  • references/ai-actions-quick-reference.md

  • One-page quick reference

For specific implementation details, use the get_developer_docs tool with these queries:

  • "How to create actions.json in Freshworks Platform 3.0"

  • "How to implement SMI functions in server.js"

  • "How to use request templates for external APIs"

Summary

Key Takeaways:

  • Request schemas MUST be flat - No nested objects or arrays

  • Response schemas CAN be nested - Include only essential fields

  • Function names MUST match exactly - Case-sensitive, alphanumeric + underscores

  • Use request templates - For all external API calls

  • Use renderData() correctly - null for success, error object for failures

  • Construct complex structures in server.js - Not in schemas

  • Test thoroughly - Use FDK test server before deployment

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

app-dev

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

freshworks-fdk-setup-skill

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

freshworks-publish-skill

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

freshworks-app-dev-skill

No summary provided by upstream source.

Repository SourceNeeds Review