From langdock-dev
This skill should be used when the user asks to "build a langdock action", "create langdock integration", "write action script for langdock", "langdock ld.request", "langdock metadata format", or needs guidance on Langdock action conventions, authentication patterns, and script structure.
npx claudepluginhub mberto10/mberto-compoundThis skill uses the workspace's default tool permissions.
Build production-ready Langdock integration actions that connect external APIs to Langdock assistants.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Searches prompts.chat for AI prompt templates by keyword or category, retrieves by ID with variable handling, and improves prompts via AI. Use for discovering or enhancing prompts.
Dispatches parallel agents to independently tackle 2+ tasks like separate test failures or subsystems without shared state or dependencies.
Build production-ready Langdock integration actions that connect external APIs to Langdock assistants.
Before writing any code, fetch the target API's documentation:
Use WebFetch to retrieve API documentation from the provider's docs URL.
Extract: endpoints, authentication method, required parameters, response format.
Identify these key aspects:
Follow the exact Langdock conventions below.
Every action script MUST start with metadata comments:
// name = Action Name In Title Case
// description = One-line description of what this action does
// parameterName = Description of parameter (e.g. 'example value')
// optionalParam = Description with default (default: 'someValue')
Rules:
name and description are requiredconst options = {
url: `https://api.example.com/endpoint?apikey=${data.auth.apikey}`,
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
body: null,
};
Note: Use lowercase apikey for query string auth.
const options = {
url: 'https://api.example.com/endpoint',
method: 'POST',
headers: {
Authorization: `Bearer ${data.auth.apiKey}`,
'Content-Type': 'application/json',
},
body: { /* request body */ },
};
Note: Use camelCase apiKey for Bearer auth.
const options = {
url: 'https://api.example.com/endpoint',
method: 'GET',
headers: {
'X-API-Key': data.auth.api_key,
'Content-Type': 'application/json',
},
body: null,
};
const options = {
url: 'https://api.example.com/endpoint',
method: 'GET',
headers: {
Authorization: `Bearer ${data.auth.access_token}`,
'Content-Type': 'application/json',
},
body: null,
};
Note: Langdock handles token refresh automatically for OAuth connections.
Access user inputs via data.input.parameterName:
// Required parameter
const symbol = data.input.symbol;
// Optional with default
const limit = data.input.limit || 10;
// Conditional inclusion
const params = new URLSearchParams();
params.append('symbol', data.input.symbol);
if (data.input.startDate) {
params.append('from', data.input.startDate);
}
| Type | Access Pattern | Example |
|---|---|---|
| TEXT | data.input.fieldId | String value |
| NUMBER | data.input.fieldId | Numeric value |
| BOOLEAN | data.input.fieldId | true/false |
| SELECT | data.input.fieldId | Selected option value |
| FILE | data.input.fieldId | {fileName, mimeType, base64} |
| OBJECT | data.input.fieldId | Parsed JSON object |
// name = Get Stock Quote
// description = Retrieves current stock quote for a symbol
// symbol = Stock ticker symbol (e.g. 'AAPL')
const options = {
url: `https://api.example.com/quote/${data.input.symbol}?apikey=${data.auth.apikey}`,
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
},
body: null,
};
const response = await ld.request(options);
return response.json;
// name = Create Task
// description = Creates a new task in the project management system
// title = Task title
// description = Task description (optional)
// priority = Task priority (default: 'medium')
const options = {
url: 'https://api.example.com/tasks',
method: 'POST',
headers: {
Authorization: `Bearer ${data.auth.apiKey}`,
'Content-Type': 'application/json',
},
body: {
title: data.input.title,
description: data.input.description || '',
priority: data.input.priority || 'medium',
},
};
const response = await ld.request(options);
return response.json;
const response = await ld.request(options);
return response.json;
const response = await ld.request(options);
const data = response.json;
return {
symbol: data.symbol,
price: data.latestPrice,
change: data.change,
changePercent: `${(data.changePercent * 100).toFixed(2)}%`,
};
const options = {
url: 'https://api.example.com/file/123',
method: 'GET',
headers: { Authorization: `Bearer ${data.auth.apiKey}` },
responseType: 'binary', // or 'stream'
};
const response = await ld.request(options);
return {
fileName: 'document.pdf',
mimeType: 'application/pdf',
buffer: response.buffer,
};
try {
const response = await ld.request(options);
if (response.status !== 200) {
return {
error: true,
message: `API returned status ${response.status}`,
details: response.json,
};
}
return response.json;
} catch (error) {
return {
error: true,
message: 'Request failed',
details: error.message,
};
}
| Function | Purpose |
|---|---|
ld.request(options) | Execute HTTP request |
ld.log(...values) | Debug output (visible in test results) |
JSON.stringify(obj) | Serialize to JSON |
JSON.parse(str) | Parse JSON string |
btoa(str) | Base64 encode |
atob(str) | Base64 decode |
encodeURIComponent(str) | URL encode |
// name = Get Company Financials
// description = Retrieves income statement and balance sheet for a company
// symbol = Stock ticker symbol (e.g. 'AAPL')
// period = Reporting period: 'annual' or 'quarterly' (default: 'annual')
// limit = Number of periods to return (default: 4)
const symbol = data.input.symbol;
const period = data.input.period || 'annual';
const limit = data.input.limit || 4;
const options = {
url: `https://financialmodelingprep.com/api/v3/income-statement/${symbol}?period=${period}&limit=${limit}&apikey=${data.auth.apikey}`,
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
},
body: null,
};
try {
const response = await ld.request(options);
if (response.status !== 200) {
return { error: true, message: `API error: ${response.status}` };
}
return {
symbol: symbol,
period: period,
data: response.json,
retrieved: new Date().toISOString(),
};
} catch (error) {
return { error: true, message: error.message };
}
apikey vs apiKey vs api_key)data.input.*encodeURIComponent if needed