Add Creagency skill, CLI, and local MCP workflows to Claude Code, Codex, OpenClaw, or any local AI agent
# Quick install for Bash/Zsh/Terminal
mkdir -p ~/.agents/skills/creagency-api &&
curl -fsSL https://creagency.ai/.agents/skills/creagency-api/SKILL.md \
-o ~/.agents/skills/creagency-api/SKILL.md &&
echo "✓ Creagency skill installed to ~/.agents/skills/creagency-api/SKILL.md"I need you to install the Creagency API skill so you can help me manage social media posts.
Please follow these steps:
1. First, create the skill directory structure:
mkdir -p ~/.agents/skills/creagency-api
2. Download the skill file from Creagency's docs:
curl -fsSL https://creagency.ai/.agents/skills/creagency-api/SKILL.md \
-o ~/.agents/skills/creagency-api/SKILL.md
3. Once downloaded, confirm the skill is installed by listing the file:
ls -la ~/.agents/skills/creagency-api/
4. Now you can use the skill! Try saying:
"Use the creagency-api skill to help me schedule a post"
The skill file contains:
- Complete API workflow patterns for TypeScript & Python
- Error handling decision trees for all HTTP status codes
- Rate limiting strategies and best practices
- Platform-specific constraints (X, Instagram, LinkedIn, etc.)
- Ready-to-use tool definitions for agent integrationUse the skill for rules, the CLI for terminal workflows, and local stdio MCP for guarded tool calls. Hosted remote MCP is planned separately.
What's Inside This Skill
- ✓Complete API workflow recipes (TypeScript & Python)
- ✓Error handling decision trees for all HTTP codes
- ✓Rate limiting patterns & proactive monitoring
- ✓Advanced workflows: AI captions, cross-posting, bulk
- ✓Platform constraints (X, Instagram, LinkedIn, etc.)
- ✓Ready-to-use tool definitions for agent integration
This skill requires a Creagency API key to make actual API calls. The skill provides the patterns and code, but you'll need to authenticate.
Get Your API Key →Creagency Agent Skill Reference
Once you've installed the skill above, this guide provides complete documentation for using Creagency's public API, CLI, and local MCP tools. Includes workflow recipes, error handling patterns, rate limit strategies, and production-ready code.
Core Principles
Authentication
All API calls must include an API key in the Authorization header. The key resolves to your organization automatically—no need to specify workspace IDs.
Store API keys in environment variables—never hardcode them. Required scopes vary by endpoint; check the Scopes reference.
Workflow Recipes
Step-by-step patterns for the most common agent workflows. Each workflow shows the exact API call sequence with error handling.
Steps:
- Verify connected social accounts (GET /api/integrations/social/accounts)
- Validate platform selection against available accounts
- Create post draft (POST /api/posts)
- If scheduledAt provided: post is scheduled automatically
- If no scheduledAt: queue for publish (POST /api/posts/{id}/publish)
Agent Note: Always verify the platform account is connected before creating the post. If missing, ask the user to connect the account in the dashboard first.
Steps:
- Request signed upload URL (POST /api/media/uploads/sign)
- Upload file directly to object storage (R2/S3)
- Create asset metadata (POST /api/assets)
- Pass asset IDs when creating post (assetIds array)
Optimization: Upload media in parallel if multiple files. Each upload is independent and can proceed concurrently.
Steps:
- Query posts with filters (GET /api/posts?platform=x&limit=50)
- Check scheduledAt field to identify scheduled posts
- For rescheduling: PATCH /api/posts/{id} with new scheduledAt
- For unscheduling: POST /api/posts/{id}/unschedule
Steps:
- Validate post count against rate limits (max 10 posts/minute)
- Create posts sequentially with rate limit checks
- Report progress after each successful creation
- If rate limited (429): wait for reset window and continue
Warning: Posts creation is rate-limited to 10/minute. For large batches, implement progress saving to resume after interruptions.
Complete Implementations
Production-ready client implementations with error handling, retries, and rate limit management.
import { CreagencyClient } from './creagency-client';
// Initialize with API key from environment
const client = new CreagencyClient({
apiKey: process.env.CREAGENCY_API_KEY,
baseUrl: 'https://api.creagency.ai'
});
// Complete workflow: Create post with media
async function createAndSchedulePost(workflow: {
content: string;
platform: 'x' | 'linkedin' | 'instagram' | 'youtube';
mediaFiles: string[]; // local file paths
scheduledAt?: Date;
}) {
try {
// Step 1: Best-effort account preflight when integrations:read is available
try {
const accounts = await client.listConnectedAccounts();
const targetAccount = accounts.find(a => a.platform === workflow.platform);
if (!targetAccount) {
return {
success: false,
error: `No connected ${workflow.platform} account. Please connect in dashboard.`
};
}
} catch (error: any) {
if (error?.status !== 403) {
throw error;
}
}
// Step 2: Upload media (parallel)
const mediaAssets = await Promise.all(
workflow.mediaFiles.map(file => client.uploadMedia(file))
);
// Step 3: Create asset metadata
const assets = await Promise.all(
mediaAssets.map(media =>
client.createAsset({
name: media.filename,
mimeType: media.contentType,
sizeBytes: media.size
})
)
);
// Step 4: Create post
const post = await client.createPost({
content: workflow.content,
platforms: [workflow.platform],
assetIds: assets.map(a => a.id),
scheduledAt: workflow.scheduledAt?.toISOString()
});
// Step 5: If immediate publish requested
if (!workflow.scheduledAt) {
await client.publishPost(post.id);
}
return {
success: true,
postId: post.id,
status: workflow.scheduledAt ? 'scheduled' : 'publishing',
url: `https://app.creagency.ai/dashboard/posts/${post.id}`
};
} catch (error) {
return client.handleError(error);
}
}Error Handling Decision Tree
Agents must handle errors gracefully. Here's the complete decision pattern:
// Error handling decision tree for agents
class CreagencyErrorHandler {
handle(error: ApiError): AgentAction {
const { status, code, message } = error;
// 401: Authentication failure
if (status === 401) {
return {
type: 'STOP',
userMessage:
'API key is invalid, expired, or revoked. ' +
'Please check your CREAGENCY_API_KEY environment variable ' +
'or generate a new key in the dashboard.'
};
}
// 403: Scope/permission issue
if (status === 403) {
if (code === 'UPGRADE_REQUIRED') {
return {
type: 'ASK_USER',
userMessage:
'This operation requires a higher plan. ' +
'Current plan: Starter. Required: Growth+. ' +
'Would you like me to open the billing page?'
};
}
return {
type: 'STOP',
userMessage:
'API key lacks required scope for this operation. ' +
'This key is missing a required scope for the attempted workflow. ' +
'Continue with a reduced workflow or create a key with the exact scope needed.'
};
}
// 429: Rate limited
if (status === 429) {
const resetSeconds = error.headers['ratelimit-reset'];
return {
type: 'WAIT',
waitSeconds: parseInt(resetSeconds) + 1,
userMessage:
`Rate limit hit. Waiting ${resetSeconds} seconds before retry...`
};
}
// 400: Validation error
if (status === 400) {
// Extract field-specific errors
const fieldErrors = error.details?.fields;
if (fieldErrors) {
const fields = Object.keys(fieldErrors).join(', ');
return {
type: 'ASK_USER',
userMessage:
`Validation failed for fields: ${fields}. ` +
'Please correct the input and try again.'
};
}
return {
type: 'ASK_USER',
userMessage:
`Request validation failed: ${message}. ` +
'Please check the data format and try again.'
};
}
// 500+: Server errors
if (status >= 500) {
return {
type: 'RETRY',
maxRetries: 3,
backoffMs: 1000,
userMessage:
'Server error occurred. Will retry with exponential backoff...'
};
}
// Default: Unknown error
return {
type: 'STOP',
userMessage:
`Unexpected error (${status}): ${message}. ` +
'Please try again or contact support.'
};
}
}429 RATE_LIMITED - Wait and retry
503 SERVICE_UNAVAILABLE - Retry with backoff
504 GATEWAY_TIMEOUT - Retry with backoff
Network errors - Retry with backoff
401 UNAUTHORIZED - Stop, notify user
403 FORBIDDEN - Stop, check scopes/plan
400 VALIDATION_ERROR - Fix input, retry
404 NOT_FOUND - Stop, verify ID
Rate Limiting Pattern
Implement proactive rate limit management to avoid hitting limits:
// Rate limit handling pattern
class RateLimitManager {
private remaining: number = 60;
private resetTime: Date = new Date();
private minRemaining: number = 5;
async executeWithRateLimit<T>(
operation: () => Promise<{ headers: Headers; data: T }>
): Promise<T> {
// Pre-check: If running low, wait proactively
if (this.remaining <= this.minRemaining) {
const waitMs = this.resetTime.getTime() - Date.now();
if (waitMs > 0) {
console.log('Rate limit buffer low. Pausing for ' + waitMs + 'ms...');
await sleep(waitMs);
}
}
try {
const response = await operation();
// Update rate limit tracking from headers
this.remaining = parseInt(response.headers['ratelimit-remaining'] || '0');
const resetSeconds = parseInt(response.headers['ratelimit-reset'] || '60');
this.resetTime = new Date(Date.now() + resetSeconds * 1000);
return response.data;
} catch (error) {
if (error.status === 429) {
const retryAfter = parseInt(error.headers['retry-after'] || '60');
console.log('Rate limited. Waiting ' + retryAfter + 's...');
await sleep(retryAfter * 1000);
// Retry once
const retry = await operation();
return retry.data;
}
throw error;
}
}
}| Plan | Requests/Min | Posts/Min | Media/Min |
|---|---|---|---|
| Starter | 60 | 10 | 20 |
| Growth | 180 | 10 | 20 |
| Scale | 600 | 10 | 20 |
| Enterprise | 1,200 | 10 | 20 |
Tool Definition Pattern
When integrating Creagency into your agent's tool system, define tools with these schemas:
// Tool definition pattern for AI agents
// Use this when integrating Creagency into your agent's tool system
const creagencyTools = [
{
name: 'creagency_list_posts',
description: 'List posts for the organization with optional filtering',
parameters: {
type: 'object',
properties: {
platform: {
type: 'string',
enum: ['x', 'linkedin', 'instagram', 'youtube', 'tiktok', 'facebook', 'threads'],
description: 'Filter by social platform'
},
q: {
type: 'string',
description: 'Search term for post content'
},
limit: {
type: 'integer',
minimum: 1,
maximum: 100,
default: 20,
description: 'Number of posts to return'
},
favoriteOnly: {
type: 'boolean',
description: 'Return only favorited posts'
}
}
},
requiredScopes: ['posts:read']
},
{
name: 'creagency_create_post',
description: 'Create a new post draft or scheduled post',
parameters: {
type: 'object',
properties: {
content: {
type: 'string',
maxLength: 63206,
description: 'Post content/caption'
},
platforms: {
type: 'array',
items: { type: 'string' },
minItems: 1,
description: 'Target platforms (e.g., ["x", "linkedin"])'
},
scheduledAt: {
type: 'string',
format: 'date-time',
description: 'ISO 8601 datetime for scheduling. Omit for draft.'
},
assetIds: {
type: 'array',
items: { type: 'string' },
description: 'Media asset IDs to attach'
}
},
required: ['content', 'platforms']
},
requiredScopes: ['posts:write']
},
{
name: 'creagency_upload_media',
description: 'Upload media file and create asset',
parameters: {
type: 'object',
properties: {
filePath: {
type: 'string',
description: 'Local path to media file'
},
filename: {
type: 'string',
description: 'Desired filename for the asset'
}
},
required: ['filePath']
},
requiredScopes: ['assets:write']
},
{
name: 'creagency_publish_post',
description: 'Queue an existing post for immediate publishing',
parameters: {
type: 'object',
properties: {
postId: {
type: 'string',
description: 'ID of the post to publish'
}
},
required: ['postId']
},
requiredScopes: ['posts:write']
},
{
name: 'creagency_list_connected_accounts',
description: 'List connected social media accounts',
parameters: {
type: 'object',
properties: {}
},
requiredScopes: ['integrations:read']
}
];Advanced Workflows
Complex multi-step workflows for production use cases. These patterns handle AI generation, cross-platform posting, failure recovery, and bulk operations.
Use AI to generate a platform-optimized caption, then create the post with it. Includes polling for job completion.
// POST /api/posts/ai/caption-jobs
const job = await api.caption.generate({
content: "product launch announcement",
platform: "linkedin",
tone: "professional"
});
// Poll GET /api/posts/ai/caption-jobs/{id}
const caption = await pollForCompletion(job.id, 30000);
// Create post with generated caption
const post = await api.posts.create({
content: caption,
platforms: ["linkedin"]
});Quota Limits: AI captions have daily limits by plan (Starter: 15/day, Growth: 50/day, Scale: 125/day, Enterprise: Unlimited).
Create a single post that publishes to multiple platforms simultaneously. Validates that all platforms are connected first.
// Verify all platforms connected
const accounts = await api.accounts.list();
const connected = new Set(accounts.map(a => a.platform));
const requested = ["x", "linkedin", "instagram"];
const missing = requested.filter(p => !connected.has(p));
if (missing.length > 0) {
throw new Error(
'Not connected to: ' + missing.join(', ')
);
}
// Create single post for all platforms
const post = await api.posts.create({
content: "Big announcement! ",
platforms: requested,
assetIds: ["asset_123"] // Same media for all
});Automatically find posts that failed to publish and reschedule them for retry. Useful for handling temporary platform issues.
// List posts with status filter (if available)
const posts = await api.posts.list({ limit: 100 });
const failed = posts.filter(p => p.status === 'failed');
console.log('Found ' + failed.length + ' failed posts');
for (const post of failed) {
// Reschedule 1 hour from now
await api.posts.update(post.id, {
scheduledAt: new Date(Date.now() + 3600000).toISOString()
});
console.log('Rescheduled post ' + post.id);
}Create multiple posts in sequence with built-in rate limit safety. Pauses every 5 posts to avoid hitting the 10 posts/minute limit.
const postsToCreate = [
{ content: "Post 1", platform: "x" },
{ content: "Post 2", platform: "x" },
// ... 20 more
];
for (let i = 0; i < postsToCreate.length; i++) {
const data = postsToCreate[i];
await api.posts.create(data);
console.log('Created ' + (i + 1) + '/' + postsToCreate.length);
// Pause every 5 posts to stay under 10/min limit
if (i > 0 && i % 5 === 0) {
console.log('Pausing 10s for rate limit...');
await sleep(10000);
}
}Pro Tip: For large batches, save progress to disk so you can resume if interrupted. Track created post IDs in a log file.
// Advanced Workflow 1: Create Post with AI-Generated Caption
async function createPostWithAiCaption(params: {
topic: string;
platform: 'x' | 'linkedin' | 'instagram';
tone?: 'professional' | 'casual' | 'witty';
scheduledAt?: string;
}) {
console.log('[Workflow] Generating AI caption...');
// Step 1: Generate caption
const captionJob = await apiPost('/api/posts/ai/caption-jobs', {
content: params.topic,
platform: params.platform,
tone: params.tone || 'professional'
});
// Step 2: Poll for completion (max 30s)
let caption: string | null = null;
const startTime = Date.now();
while (Date.now() - startTime < 30000) {
const status = await apiGet('/api/posts/ai/caption-jobs/' + captionJob.id);
if (status.status === 'completed') {
caption = status.result;
break;
}
if (status.status === 'failed') {
throw new Error('Caption generation failed: ' + status.error);
}
await sleep(2000); // Poll every 2s
}
if (!caption) {
throw new Error('Caption generation timed out');
}
console.log('[Workflow] Caption generated, creating post...');
// Step 3: Create post with generated caption
const post = await apiPost('/api/posts', {
content: caption,
platforms: [params.platform],
scheduledAt: params.scheduledAt
});
return {
success: true,
postId: post.id,
caption: caption,
url: 'https://app.creagency.ai/dashboard/posts/' + post.id
};
}
// Advanced Workflow 2: Cross-Post to Multiple Platforms
async function crossPostToMultiplePlatforms(params: {
content: string;
platforms: string[];
scheduledAt?: string;
assetIds?: string[];
}) {
console.log('[Workflow] Cross-posting to ' + params.platforms.length + ' platforms...');
// Step 1: Verify all platforms connected when integrations:read is available
try {
const accounts = await apiGet('/api/integrations/social/accounts');
const connectedPlatforms = new Set(accounts.map((a: any) => a.platform));
const missing = params.platforms.filter(p => !connectedPlatforms.has(p));
if (missing.length > 0) {
throw new Error(
'Not connected to: ' + missing.join(', ') + '. ' +
'Connect accounts in dashboard first.'
);
}
} catch (error: any) {
if (error?.status !== 403) {
throw error;
}
}
// Step 2: Create single post targeting all platforms
const post = await apiPost('/api/posts', {
content: params.content,
platforms: params.platforms,
scheduledAt: params.scheduledAt,
assetIds: params.assetIds
});
console.log('Created cross-post: ' + post.id);
return {
success: true,
postId: post.id,
platforms: params.platforms,
url: 'https://app.creagency.ai/dashboard/posts/' + post.id
};
}
// Advanced Workflow 3: Reschedule Failed Posts
async function rescheduleFailedPosts(options?: {
newScheduledAt?: string;
platform?: string;
}) {
console.log('[Workflow] Finding failed posts...');
// Get all posts
const posts = await apiGet('/api/posts?limit=100');
// Filter for failed posts
const failedPosts = posts.filter((p: any) =>
p.status === 'failed' &&
(!options?.platform || p.platforms.includes(options.platform))
);
console.log('Found ' + failedPosts.length + ' failed posts');
let rescheduled = 0;
let failed = 0;
for (const post of failedPosts) {
try {
const newTime = options?.newScheduledAt ||
new Date(Date.now() + 3600000).toISOString();
await apiPatch('/api/posts/' + post.id, {
scheduledAt: newTime
});
console.log('Rescheduled post ' + post.id);
rescheduled++;
} catch (err) {
console.log('Failed to reschedule ' + post.id + ': ' + err);
failed++;
}
}
return { rescheduled, failed };
}
// Advanced Workflow 4: Bulk Create with Rate Limiting
async function bulkCreatePosts(postsData: Array<{
content: string;
platform: string;
scheduledAt?: string;
}>) {
console.log('[Workflow] Bulk creating ' + postsData.length + ' posts...');
let created = 0;
let failed = 0;
const results: any[] = [];
for (let i = 0; i < postsData.length; i++) {
const data = postsData[i];
console.log(' [' + (i + 1) + '/' + postsData.length + '] Creating post...');
try {
const post = await apiPost('/api/posts', {
content: data.content,
platforms: [data.platform],
scheduledAt: data.scheduledAt
});
results.push(post);
created++;
// Rate limiting safety: posts limited to 10/minute
if (i > 0 && i % 5 === 0 && i < postsData.length - 1) {
console.log(' [Rate limit safety: pausing 10s...]');
await sleep(10000);
}
} catch (err) {
console.log(' Failed: ' + err);
failed++;
}
}
return { created, failed, results };
}
// Helper functions
const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
const apiGet = (path: string) => { /* ... */ return {} as any; };
const apiPost = (path: string, data: any) => { /* ... */ return {} as any; };
const apiPatch = (path: string, data: any) => { /* ... */ return {} as any; };Platform-Specific Constraints
Validate content before sending to avoid platform rejections:
Max text: 280 characters
Max images: 4 per post
Video: 512MB max, 140s max
Images: JPEG, PNG, GIF, WebP
Max caption: 2,200 characters
Max images: 10 per post
Video: 650MB max (feed: 60s, reels: 90s)
Images: JPEG, PNG only
Max text: 3,000 characters
Max images: 20 per post
Video: 200MB max, 10 min max
Images: JPEG, PNG
Title: 100 characters max
Description: 5,000 characters max
Video: 256GB max, 12 hours max
Formats: MP4, MOV, AVI
Quick Reference
https://api.creagency.aiAuthorization: Bearer <key>GET /api/open-apiReference Implementation
Download complete, runnable reference clients to test your API key and explore all endpoints. Includes built-in test suite that verifies connectivity and demonstrates all workflows.
Complete TypeScript implementation with all endpoints, workflows, and test suite. Works with Node.js 18+ or Deno.
Location: docs/api/reference-client.ts
Complete Python implementation with dataclasses, type hints, and comprehensive test suite. Works with Python 3.9+.
Location: docs/api/reference_client.py
Changelog
Track updates to the Creagency API and this agent skill documentation.
Initial Release
- Complete public API coverage (Posts, Assets, Media, AI, Integrations)
- 4 basic workflow recipes (create post, upload media, schedule, bulk)
- 4 advanced workflows (AI caption, cross-post, reschedule failed, bulk with rate limiting)
- Error handling decision tree with retry logic
- Rate limiting patterns with proactive monitoring
- Tool definition patterns for agent integration
- Platform-specific constraints (X, Instagram, LinkedIn, YouTube)
- Reference implementations in TypeScript and Python
- Built-in test suites for both languages
- Rate limits documentation by subscription plan
Planned Future Updates
- Analytics API endpoints (post metrics, account insights)
- Team management endpoints (invitations, role changes)
- Advanced scheduling (recurring posts, best-time recommendations)
- Webhook integration patterns for real-time updates
- Batch operations API (when available)