ai-actions-skill
npx skills add https://github.com/freshworks-developers/freshworks-platform3 --skill ai-actions-skill
Agent 安装分布
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 validateand 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
errorobject (ornullfor success) - â
For success, pass
nullas first argument - â
For error, pass object with
statusandmessage
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
- â API base URLs (e.g.,
-
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
-
$schemais set tohttp://json-schema.org/draft-07/schema#
server.js Validation:
- Function name matches
actions.jsonexactly (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 validateand 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 examplesreferences/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 –
nullfor success, error object for failures - Construct complex structures in server.js – Not in schemas
- Test thoroughly – Use FDK test server before deployment