skills/moltfluence-content-publish/SKILL.md
Use when a user wants to generate and publish content. Run trends to scripts to prompts to video generation to QA to Instagram publishing using x402 paid endpoints.
npx skillsauth add abhishek222983101/moltfluence-avax moltfluence-content-publishInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
4 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
You are the execution agent for content production and distribution.
Run the full bot flow from topic selection to published reel URL.
https://modfluencemonad.vercel.app when MOLTFLUENCE_API_URL is not set.EVM_PRIVATE_KEY is required only when a call returns 402 and payment is needed.x-user-id: <channel_user_id>.characterId, brief.id, script.id, jobId, mediaId.Use:
API_BASE="${MOLTFLUENCE_API_URL:-https://modfluencemonad.vercel.app}"
All paid endpoints (/api/x402/*) use x402 micropayments with USDC on Avalanche testnet (eip155:43113).
Payment-Required response header (base64-encoded JSON).PAYMENT-SIGNATURE: <base64-encoded-payload>.PAYMENT-SIGNATURE is NOT a raw 0x... hex string. It is a base64-encoded JSON envelope containing an EIP-3009 authorization + signature.undici fetch. The built-in Node fetch can break with x402 headers.Request objects.wrapFetchWithPayment() — it is unreliable in many runtimes.Install once:
npm install @x402/core @x402/evm viem undici
import { x402Client } from "@x402/core/client";
import { decodePaymentRequiredHeader, encodePaymentSignatureHeader } from "@x402/core/http";
import { ExactEvmScheme } from "@x402/evm";
import { privateKeyToAccount } from "viem/accounts";
import { fetch as undiciFetch } from "undici";
const API_BASE = process.env.MOLTFLUENCE_API_URL || "https://modfluencemonad.vercel.app";
const USER_ID = "<channel_user_id>";
const payer = privateKeyToAccount(process.env.EVM_PRIVATE_KEY as `0x${string}`);
const scheme = new ExactEvmScheme(payer);
const client = x402Client.fromConfig({
schemes: [{ network: "eip155:*", client: scheme }],
});
/**
* payFetch — handles x402 payment automatically WITH RETRIES.
* Use for ALL paid calls (/api/x402/*).
* Retries 3 times on transient facilitator errors.
*/
async function payFetch(url: string, init: RequestInit): Promise<Response> {
let lastError: Error | null = null;
for (let attempt = 0; attempt < 3; attempt++) {
try {
const unpaid = await undiciFetch(url, init);
if (unpaid.status !== 402) return unpaid;
const challengeB64 =
unpaid.headers.get("Payment-Required") ||
unpaid.headers.get("payment-required") ||
unpaid.headers.get("PAYMENT-REQUIRED");
if (!challengeB64) throw new Error("Got 402 but no Payment-Required header");
const paymentRequired = decodePaymentRequiredHeader(challengeB64);
const paymentPayload = await client.createPaymentPayload(paymentRequired);
const paymentSig = encodePaymentSignatureHeader(paymentPayload);
const paid = await undiciFetch(url, {
...init,
headers: { ...(init.headers ?? {}), "PAYMENT-SIGNATURE": paymentSig },
});
if (paid.ok) return paid;
if (paid.status === 402) {
const errorBody = await paid.text().catch(() => "");
lastError = new Error(`Payment attempt ${attempt + 1} failed: ${errorBody}`);
await new Promise(r => setTimeout(r, 2000));
continue;
}
return paid;
} catch (err) {
lastError = err as Error;
await new Promise(r => setTimeout(r, 2000));
}
}
throw lastError ?? new Error("payFetch failed after 3 attempts");
}
Just use that platform's x402 payment tool to handle the 402 challenge. You don't need the code above.
undici fetch — import { fetch as undiciFetch } from "undici". Do NOT use built-in Node fetch.Request object.wrapFetchWithPayment() — it is unreliable.payFetch above retries automatically. If all 3 retries fail, wait 30 seconds and call payFetch again. Payment WILL work.| Endpoint | Price | Notes |
|----------|-------|-------|
| POST /api/x402/generate-image | $0.01–$0.05 | Depends on image model (see below) |
| POST /api/x402/generate-video | $0.15–$2.40 | Depends on video model + duration/voice mode (see below) |
| POST /api/x402/publish-reel | $0.025 | Fixed price |
| Model | model param | Price | Speed | Best for |
|-------|--------------|-------|-------|----------|
| Flux Schnell | flux-schnell | $0.002 provider cost (billed min $0.01 on-chain) | ~5s | Fast drafts |
| Flux Dev | flux-dev | $0.015 | ~30-60s | Character portraits (DEFAULT) |
| Flux Dev Advanced | flux-dev-advanced | $0.02 | ~30-60s | Advanced control |
| Midjourney | midjourney | $0.05 | ~60-120s | Best aesthetics |
| Model | model param | Short duration price | Long duration price | Best for |
|-------|--------------|-----------|------------|----------|
| Hailuo (v2.3, 768p) | hailuo | $0.23 (6s) | $0.45 (10s) | Recommended default best value |
| Kling (voice: false) | kling | $0.20 (5s mode) | $0.40 | Premium visual quality |
| Kling (voice: true) | kling | $0.66 (5s mode) | $1.32 | Premium visual + native audio (mode: "pro") |
| Hunyuan Fast | hunyuan-fast | $0.20 (5s) | $0.40 (10s) | Budget + fast iteration |
| SkyReels V2 | skyreels-v2 | $0.15 | $0.15 | Cheapest rapid variants |
| Wan 2.6 | wan-2.6 | $0.60 (5s) | $2.40 (20s) | Best quality up to 20s |
EVM_PRIVATE_KEY is missing when 402 occurs, ask for wallet configuration and stop at that step.insufficient funds, tell user to fund wallet with USDC on Avalanche testnet.payFetch throws after retries, wait 30 seconds and try again. Do not give up.GET ${API_BASE}/api/x402/info for current network and facilitator details.const charRes = await fetch(`${API_BASE}/api/state/character`, {
headers: { "x-user-id": USER_ID },
});
const character = await charRes.json();
// character = { id: "char_...", niche: "Crypto", ... }
If no character exists, tell user to run moltfluence-character first.
auto trends OR manual topicThe trends endpoint now returns rich SynthesizedTopic objects from real-time research (Reddit, HackerNews, CoinGecko, Tavily), not just topic strings. Topics include engagement scores, controversy ratings, hooks, and visual concepts.
For detailed research behavior, see the moltfluence-content-research skill.
const trendsRes = await fetch(`${API_BASE}/api/swarm/trends`, {
method: "POST",
headers: { "Content-Type": "application/json", "x-user-id": USER_ID },
body: JSON.stringify({ niche: character.niche, manualTopic: "<optional>" }),
});
const trends = await trendsRes.json();
// trends.mode = "cached" | "auto-trends" | "manual-topic"
// trends.topics = SynthesizedTopic[] with title, angle, whyNow, hookIdea, engagementScore, controversyScore
Present topics to the user and let them pick one. Use the topic's title + angle as the topic string for script generation.
const scriptsRes = await fetch(`${API_BASE}/api/swarm/scripts`, {
method: "POST",
headers: { "Content-Type": "application/json", "x-user-id": USER_ID },
body: JSON.stringify({
characterProfile: character,
mode: "auto-trends",
topic: "<selected-topic>",
objective: "<optional>",
}),
});
const scripts = await scriptsRes.json();
moltfluence-prompt-compiler (free)const compileRes = await fetch(`${API_BASE}/api/swarm/prompt-compile`, {
method: "POST",
headers: { "Content-Type": "application/json", "x-user-id": USER_ID },
body: JSON.stringify({
profile: character,
brief: selectedBrief,
script: selectedScript,
primaryModel: "hailuo",
}),
});
const { promptPackage } = await compileRes.json();
const vidRes = await payFetch(`${API_BASE}/api/x402/generate-video`, {
method: "POST",
headers: { "content-type": "application/json", "x-user-id": USER_ID },
body: JSON.stringify({
prompt: promptPackage.primaryPrompt,
model: "hailuo",
tier: "basic",
duration: 10,
aspectRatio: "9:16",
voice: false,
characterId: character.id,
}),
});
const { jobId, model: usedModel } = await vidRes.json();
Character consistency:
characterId with video generation.imageUrl and uses it as image-to-video reference when available.imageUrl override if user explicitly wants a different actor.Important: The prompt MUST pass lint checks. It needs:
If you get "Prompt failed lint checks", fix the prompt and retry.
?model= query param)let vidStatus;
do {
await new Promise(r => setTimeout(r, 6000)); // poll every 6 seconds
const poll = await fetch(`${API_BASE}/api/x402/generate-video/${jobId}?model=${usedModel}`);
vidStatus = await poll.json();
} while (vidStatus.status === "pending" || vidStatus.status === "processing");
if (vidStatus.status === "completed") {
const videoUrl = vidStatus.videoUrl;
}
if (vidStatus.status === "failed") {
// vidStatus.error — offer to regenerate once
}
Video generation takes 1-3 minutes. Poll every 5-8 seconds.
Retention rule:
vidStatus.persisted and vidStatus.retention.MOLTFLUENCE_ASSET_PERSIST_ENDPOINT or BLOB_READ_WRITE_TOKEN on server so completed assets are copied to durable storage automatically.const pubRes = await payFetch(`${API_BASE}/api/x402/publish-reel`, {
method: "POST",
headers: { "content-type": "application/json", "x-user-id": USER_ID },
body: JSON.stringify({
videoUrl: videoUrl,
caption: "<caption matching character vibe>",
hashtags: ["moltfluence", "aiugc"],
characterId: character.id,
}),
});
const { success, reelUrl } = await pubRes.json();
{
"result": {
"characterId": "char_...",
"topic": "...",
"scriptId": "script_1",
"video": {
"jobId": "...",
"model": "hailuo",
"videoUrl": "https://..."
},
"publish": {
"success": true,
"mediaId": "...",
"reelUrl": "https://www.instagram.com/reel/..."
}
}
}
development
--- skill: moltfluence-script-writer version: 1.0.0 consumer: openclaw-tg-bot trigger: script-generation-request api_base: https://modfluencemonad.vercel.app model: groq/llama-3.3-70b --- # Skill: Character-Aware Script Generation ## Scope Gate Activate this skill ONLY when the user request matches one of: - Asks to generate scripts, write scripts, or create video scripts for a topic - Has selected a topic (from content research or provided manually) and wants script variants - Mentions scri
development
Convert persona + trend brief + script into linted model-ready prompts for supported PiAPI video models, with Hailuo as recommended default.
data-ai
Generate short-form video content for your AI influencer and publish to Instagram. Uses x402 micropayments on BSC mainnet.
development
--- skill: moltfluence-content-research version: 1.0.0 consumer: openclaw-tg-bot trigger: content-research-request api_base: https://modfluencemonad.vercel.app --- # Skill: Content Research Pipeline ## Scope Gate Activate this skill ONLY when the user request matches one of: - Asks for trending topics, viral topics, or "what's trending" in a niche - Wants to know what to make content about - Asks for content ideas, topic suggestions, or "what should I post about" - Mentions trend research, t