CtrlK
BlogDocsLog inGet started
Tessl Logo

joko-moltbook

Queue-driven Moltbook posting agent with deduplication and monitoring

Install with Tessl CLI

npx tessl i github:oyi77/1ai-skills --skill joko-moltbook
What are skills?

Overall
score

18%

Does it follow best practices?

Validation for skill structure

Validation failed for this skill
This skill has errors that need to be fixed before it can move to Implementation and Activation review.
SKILL.md
Review
Evals

Joko Moltbook Agent

Queue-driven Moltbook posting agent with deduplication, idempotency, and monitoring.

Required Tools

MCP Servers

{
  "mcpServers": {
    "apify": {
      "command": "npx",
      "args": ["-y", "@apify/mcp-server"],
      "env": { "APIFY_API_TOKEN": "${APIFY_API_TOKEN}" }
    },
    "notion": {
      "command": "npx",
      "args": ["-y", "@makenotion/mcp-server"],
      "env": { "NOTION_API_KEY": "${NOTION_API_KEY}" }
    },
    "slack": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-slack"],
      "env": { "SLACK_BOT_TOKEN": "${SLACK_BOT_TOKEN}" }
    }
  }
}

Authentication

Setup

  1. Apify Token

    export APIFY_API_TOKEN="your-token"
  2. Notion (for content queue)

    • Create integration and share queue database
  3. Slack (for alerts)

    export SLACK_BOT_TOKEN="xoxb-your-token"

Pseudo Code

Example 1: Queue-Driven Posting

// 1. Fetch pending posts from Notion queue
const queue = await notion.query("Content Queue", {
  filter: { status: "pending" }
});

// 2. Process each with idempotency check
for (const item of queue) {
  const key = generateIdempotencyKey(item.content);
  
  // Check if already posted
  const exists = await cache.get(key);
  if (exists) {
    console.log(`Skipping duplicate: ${item.id}`);
    continue;
  }
  
  // Post to Moltbook
  const result = await moltbook.post(item.content);
  
  // Mark as posted
  await cache.set(key, result.postId);
  await notion.updatePage(item.id, { status: "posted" });
}

Example 2: Deduplication with Content Hash

// Generate deterministic hash for content
function hashContent(content) {
  return sha256(content.text + content.tags.sort().join());
}

// Check before posting
const contentHash = hashContent(newPost);
const existing = await db.posts.findOne({ contentHash });

if (existing) {
  console.log("Duplicate detected, skipping");
  return { status: "duplicate", existingPost: existing };
}

const result = await moltbook.post(newPost);
await db.posts.insert({ contentHash, postId: result.id });

Example 3: Monitor and Alert

// 1. Monitor posting health
const stats = await getPostingStats();

// 2. Check metrics
if (stats.failureRate > 0.1) {
  await slack.alert({
    channel: "#alerts",
    text: `High failure rate: ${stats.failureRate * 100}%`
  });
}

// 3. Daily summary
await slack.notify("#daily-reports", `
  Posts: ${stats.total}
  Success: ${stats.success}
  Failed: ${stats.failed}
`);

CLI Reference

CommandDescription
joko queue statusCheck queue size
joko post nowProcess queue immediately
joko statsShow posting statistics

Error Handling

Error CodeMeaningFix
AUTH_001Session expiredRefresh credentials
RATE_001Rate limitedBackoff 10 min
DUPLICATE_001Duplicate contentSkip, mark handled
QUEUE_001Queue emptyNothing to do

Common Patterns

Idempotency Key Generation

function generateIdempotencyKey(item) {
  return `moltbook:${sha256(item.text + item.createdAt)}`;
}

Exponential Backoff

async function withBackoff(fn, maxRetries = 5) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await fn();
    } catch (error) {
      if (i === maxRetries - 1) throw error;
      const delay = Math.min(1000 * Math.pow(2, i), 60000);
      await sleep(delay);
    }
  }
}

Skill v2.0 - Joko Moltbook

Repository
github.com/oyi77/1ai-skills
Last updated
Created

Is this your skill?

If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.