Skip to the content.

Auto-detect Skool posts by keyword and reply

Most Skool communities miss half the conversations that matter — a member mentions a pain point, another asks about an integration, someone references a competitor. You want to be in those threads with a useful reply, but checking the feed every 30 minutes for keywords isn’t a use of your time.

This recipe is the keyword-driven monitoring loop used in production at Cágala, Aprende, Repite. The cron runs every N hours, finds posts matching your keyword list that you haven’t replied to yet, drafts a contextual reply with an LLM, and sends it to Telegram for human approval before publishing. You get a notification, click ✅ or ❌, the published reply lands in the feed under your account.

It’s the same engine behind the skool-feed-comments skill — productionized to keep voice consistent and prevent the LLM from publishing anything cringe-worthy unsupervised.

Quick reference (TL;DR for agents)

   
Goal Surface high-signal posts by keyword + reply with LLM + human gate
Stack n8n / Python + LLM (Claude/GPT) + Telegram bot + the Apify-hosted actor
Actions used posts:filterposts:getCommentsposts:createComment
Setup time ~30 min (workflow + Telegram bot + first keyword list)
Ongoing cost $0.01 × N posts checked + $0.01 per reply published
Cadence Every 2-4 hours during waking hours (not 24/7 — overnight noise)
Mandatory gate Human approval via Telegram. NEVER auto-publish replies in production.

Why human-in-the-loop is non-negotiable

LLMs are great at drafting, terrible at judgment of what to say in a community thread. A confidently wrong reply from “you” damages trust faster than no reply at all. The human gate is cheap (one Telegram tap) and catches:

The reply is published under your account, not a bot. Members read “Cristian replied” — that has to mean Cristian agreed with the words.

Prerequisites

Step 1 — Filter the feed by keyword

posts:filter accepts a query param that searches title + body:

{
  "action": "posts:filter",
  "cookies": "...",
  "groupSlug": "your-community",
  "params": {
    "query": "n8n",
    "limit": 20,
    "since": "2026-05-28T00:00:00Z"
  }
}

For multiple keywords, loop the action (Skool doesn’t support OR in a single call). De-dupe by postId afterward.

Step 2 — Skip posts you already replied to

For each match, check if your user already commented:

{
  "action": "posts:getComments",
  "cookies": "...",
  "groupSlug": "your-community",
  "params": { "postId": "abc123..." }
}
my_user_id = "cf43939d0edf46378caed98a9d46eadb"  # your Skool user_id
for comment in comments:
    if comment["author"]["id"] == my_user_id:
        skip_post()  # already replied
        break

This is the cheap filter — most posts in your keyword list will already have your reply once the loop has been running a few cycles.

Step 3 — Draft reply with LLM

Send the post title + body + comments (for context of the existing thread) to your LLM with a prompt like:

You are drafting a reply on behalf of {your_name}, a {your_role}, in a community of {community_audience}.

POST TITLE: {title}
POST BODY: {body}
EXISTING COMMENTS: {comments}

Draft a reply that:
- Adds specific value (concrete tip, link to a recipe, useful question)
- Is 40-100 words, conversational, not salesy
- Mentions a relevant resource ONLY if it genuinely fits
- Uses neutral Spanish (no localisms)

If the post doesn't merit a reply (too vague, hostile, off-topic, already well-answered), respond with EXACTLY the string "SKIP" and nothing else.

Reply draft:

The SKIP token gives the LLM a graceful exit when there’s nothing useful to say — saves you the Telegram notification.

Step 4 — Send to Telegram for approval

import requests

def send_for_approval(post, draft, telegram_bot_token, chat_id):
    text = (
        f"📬 Post: {post['title']}\n"
        f"🔗 https://www.skool.com/{group_slug}/?p={post['shortId']}\n\n"
        f"💬 Draft:\n{draft}\n\n"
        f"Approve? ✅ /approve_{post['id']} | ❌ /skip_{post['id']}"
    )
    requests.post(
        f"https://api.telegram.org/bot{telegram_bot_token}/sendMessage",
        json={"chat_id": chat_id, "text": text, "parse_mode": "HTML"}
    )

The Telegram bot listens for /approve_<postId> and /skip_<postId> commands. On approve, it fires the next step. On skip, it just logs the decision.

Step 5 — Publish on approval

{
  "action": "posts:createComment",
  "cookies": "...",
  "groupSlug": "your-community",
  "params": {
    "postId": "abc123...",
    "content": "approved draft text here"
  }
}

Top-level comments require postId == rootId == parentId — the actor’s posts:createComment defaults this correctly when you only pass postId. (For nested replies, see Reply to onboarding comments.)

Production gotchas

See also


Use this in production — no setup

The hardest part of building Skool automation isn’t the API logic — it’s the auth (cookies expire every ~3.5 days, WAF token rotation, weekly Skool buildId changes). The Skool All-in-One API actor on Apify handles all of that.

→ Open the actor on Apify

New to Skool? Launch your community here — 14-day free trial. Need an n8n instance? Get started free — the workflow tool we use throughout these recipes.