Skip to the content.

Quick reference (TL;DR for agents)

Why Claude specifically?

The Apify-hosted Skool All-in-One API actor is AI-agent-native: never-throw contract, structured hint field for recovery, idempotency where it matters. Claude in particular benefits from this because:

  1. Claude’s tool-use API can return any tool result back to the model — Claude reads hint and self-corrects.
  2. Claude Desktop ships native MCP support — connect once, Claude sees every Skool action as a tool.
  3. Claude is good at judgment calls that Skool automation needs: which applicants to approve, what tone to use in a comment reply, what category a post fits.

Per Apify analytics, claude.ai is already the 5th-largest referrer to the actor — Claude users are discovering it organically.

Path 1 — Claude tool-use API (Python)

from anthropic import Anthropic
import httpx, json, os

anthropic = Anthropic(api_key=os.environ["ANTHROPIC_API_KEY"])

SKOOL_TOOL = {
    "name": "skool_action",
    "description": (
        "Perform a Skool action via the Apify-hosted Skool All-in-One API actor. "
        "Returns {success: true, data: ...} or {success: false, errorCode, hint}."
    ),
    "input_schema": {
        "type": "object",
        "properties": {
            "action": {
                "type": "string",
                "enum": [
                    "posts:list", "posts:filter", "posts:get", "posts:create", "posts:update", "posts:delete",
                    "posts:createComment", "posts:getComments", "posts:getCommentsFull", "posts:pin", "posts:unpin", "posts:vote",
                    "members:list", "members:pending", "members:approve", "members:reject", "members:ban", "members:batchApprove",
                    "events:list", "events:upcoming",
                    "classroom:listCourses", "classroom:getTree", "classroom:createCourse", "classroom:createFolder",
                    "classroom:createPage", "classroom:setBody", "classroom:updateCourse", "classroom:deleteUnit", "classroom:updateResources",
                    "files:uploadImage", "files:uploadFile",
                    "groups:get", "groups:setAutoDM",
                    "system:health", "system:debug", "auth:login"
                ]
            },
            "params": {"type": "object"}
        },
        "required": ["action", "params"]
    }
}

def call_skool_actor(action: str, params: dict) -> dict:
    resp = httpx.post(
        f"https://api.apify.com/v2/acts/cristiantala~skool-all-in-one-api/run-sync-get-dataset-items?token={os.environ['APIFY_TOKEN']}&build=latest&timeout=90",
        json={"action": action, "cookies": os.environ["SKOOL_COOKIES"], "groupSlug": "your-community", "params": params},
        timeout=120
    )
    data = resp.json()
    return data[0] if isinstance(data, list) and data else data

def run_agent(user_request: str):
    messages = [{"role": "user", "content": user_request}]
    while True:
        response = anthropic.messages.create(
            model="claude-opus-4-7",   # latest as of 2026
            max_tokens=4096,
            tools=[SKOOL_TOOL],
            messages=messages,
        )
        if response.stop_reason == "end_turn":
            return response.content[0].text
        if response.stop_reason == "tool_use":
            messages.append({"role": "assistant", "content": response.content})
            tool_results = []
            for block in response.content:
                if block.type == "tool_use":
                    result = call_skool_actor(block.input["action"], block.input["params"])
                    tool_results.append({
                        "type": "tool_result",
                        "tool_use_id": block.id,
                        "content": json.dumps(result),
                    })
            messages.append({"role": "user", "content": tool_results})

print(run_agent("Approve the latest 5 pending Skool members. Show me a one-line summary of each."))

Claude reads pending applicants, decides which to approve, calls the tool for each, summarizes. With prompt caching, the system prompt + tool schema cache and each subsequent call is fast.

Path 2 — Claude Desktop + MCP server

Claude Desktop natively supports MCP. Drop the Skool MCP server into your config and Claude sees every actor action as a tool.

See Skool MCP Server — Production Setup for full server code (Python, ~150 lines) and the Claude Desktop config snippet.

Quick version of the config (~/Library/Application Support/Claude/claude_desktop_config.json):

{
  "mcpServers": {
    "skool": {
      "command": "npx",
      "args": [
        "-y", "@apify/actors-mcp-server",
        "--token=YOUR_APIFY_TOKEN",
        "--actors=cristiantala/skool-all-in-one-api"
      ]
    }
  }
}

Restart Claude. Skool actions appear in the tools panel. Ask Claude to operate your community in natural language.

Path 3 — Claude Code Skill (drop-in)

If you’re a Claude Code user, install the bundled Skill:

mkdir -p ~/.claude/skills/skool-actor
curl -L https://raw.githubusercontent.com/ctala/skool-api-docs/main/skills/claude-code/skool-actor/SKILL.md \
  -o ~/.claude/skills/skool-actor/SKILL.md

mkdir -p ~/.claude/skills/skool-actor/scripts
for s in login.sh post.sh comment.sh approve.sh; do
  curl -L https://raw.githubusercontent.com/ctala/skool-api-docs/main/skills/claude-code/skool-actor/scripts/$s \
    -o ~/.claude/skills/skool-actor/scripts/$s
  chmod +x ~/.claude/skills/skool-actor/scripts/$s
done

Set env vars in ~/.zshrc:

export APIFY_TOKEN=apify_api_...
export SKOOL_EMAIL=admin@example.com
export SKOOL_PASSWORD=...
export SKOOL_GROUP_SLUG=your-community-slug
export SKOOL_COOKIES=                  # populated after first auth:login

Restart Claude Code. Now in any conversation:

“List my pending Skool members and approve the ones with verified LinkedIn.”

Claude Code reads the Skill, runs the right actor actions in sequence, and reports back.

Full guide: Skool + Claude Code — install steps, example session, helper scripts, and Claude Code-specific gotchas.

Real production agent loop

Pattern used on a production Skool community:

1. Cron triggers Claude → "review pending applicants and act"
2. Claude calls members:pending
3. For each pending member, Claude reads metadata (LinkedIn, survey answers)
4. Claude classifies: clear approve, clear reject, needs human review
5. Claude calls members:batchApprove for the clear approves
6. Claude posts a summary in Telegram for human review of borderline cases
7. Human responds in Telegram → Claude calls approve/reject as instructed

End-to-end: ~$0.50/run, runs once daily, replaces 30 minutes of manual screening per day.

Error recovery — Claude reads the hint

When the actor returns {success: false, errorCode: "WAF_EXPIRED", hint: "Re-run auth:login with email/password and store new cookies"}, Claude reads the hint and takes the right next step without any custom error-handling logic:

Tool result: {success: false, errorCode: “WAF_EXPIRED”, hint: “Re-run auth:login…”}

Claude: Cookies expired. Running auth:login now.

[tool: skool_action {action: “auth:login”, params: {email: …, password: …, groupSlug: …}}]

This is why the actor’s error schema is designed to be LLM-readable rather than human-machine-readable.

Common patterns

Pattern Implementation
Approval queue review Claude reads members:pending → classifies → members:batchApprove
Daily community digest Claude reads posts:list (last 24h) → summarizes → DMs you via Telegram
Tone-correct comment replies Claude reads unanswered posts → drafts in your voice → human approves → publishes
Course publishing from notes Claude reads markdown → classroom:createCourse + classroom:setBody per page
Auto DM A/B testing Claude rotates groups:setAutoDM between variants weekly, you measure conversion

Production gotchas


Plug Skool into Claude today

→ Open the Skool All-in-One API actor on Apify

Three integration paths: Claude tool-use API, Claude Desktop + MCP, Claude Code Skill. Pay-per-event (~$0.005-$0.01 per call).

No Skool community yet? Launch one in 10 minutes — 14-day free trial.