Skip to main content

Challenge Gate

Detect bot walls and escalate CAPTCHA to a human.

Skill metadata​

SourceBundled (installed by default)
Pathskills/research/challenge-gate
Version1.0.0
AuthorVibeOS
LicenseMIT
Platformslinux, macos, windows
Tagsresearch, browser, captcha, bot-wall, human-in-the-loop
Related skillschoose-interaction-surface, professional-research, analysis-orchestration, ru-public-sources

Reference: full SKILL.md​

info

The following is the complete skill definition that VibeOS loads when this skill is triggered. This is what the agent sees as instructions when the skill is active.

Challenge Gate Skill

Handle CAPTCHA / Cloudflare / Turnstile / login walls without thrashing. Prefer avoid → one provider assist → human handoff → honest partial brief. Never invent page content behind a wall.

When to Use​

  • browser_navigate returns bot_detection_warning or challenge.
  • Title/snapshot shows captcha, “Just a moment”, Turnstile, “are you a robot”.
  • Extract/search fails because the target is behind a challenge.
  • Research skills hit a blocked source mid-gather.

Do not use to crack CAPTCHAs, farm solvers, or bypass paywalls silently.

Prerequisites​

  • Browser tools and/or web_search + web_extract.
  • clarify for human handoff (CLI / gateway / desktop).
  • Optional: Browserbase proxies/stealth, CDP /browser connect, warm Camofox profile.
  • Config (defaults in config.yaml under browser.challenge):
KeyDefaultMeaning
prefer_humantruePrefer L3 over solver thrash
max_auto_attempts1Max L1/L2 cycles before L3
human_timeout_seconds600Then L4 partial
allow_provider_solvetrueUse provider assist when available
record_artifactstrueWrite challenge.md

Skills that forbid bypass (ru-public-sources, etc.): skip L2, go Detect → optional Human → L4.

How to Run​

On any challenge signal, run layers in order. Stop when the page is clear or L4 applies.

L0 Detect → L1 Avoid → L2 Provider assist → L3 Human handoff → L4 Partial continue

Quick Reference​

LayerActionTools
L0Classify type/severitychallenge field, browser_vision
L1Prefer search/extract/MCP; one gentle retryweb_search, web_extract, MCP
L2One provider assist if configuredBrowserbase stealth/proxies
L3Ask human; wait for готово/doneclarify, screenshot
L4Mark blocked; continue other sourcessources.json, challenge.md

Procedure​

L0 — Detect​

  1. If response has challenge, use it. Else classify from title/body.
  2. Types: cloudflare_iuam, turnstile, hcaptcha, recaptcha_v2, login_wall, paywall, custom, unknown.
  3. Severity: soft | hard | human_only.
  4. Do not click randomly. Announce: “ChallengeGate L0 on <url>”.

L1 — Avoid (max max_auto_attempts)​

Prefer facts without the wall:

  1. web_search + web_extract for the same facts.
  2. MCP/OAuth for SaaS instead of login UI.
  3. Warm profile / CDP user Chrome if already trusted for that site.
  4. One slowed re-navigate (hub → target) only for soft severity.

Forbidden: endless reload; computer_use on the browser window as first choice.

L2 — Provider assist (once, opt-in)​

Only if allow_provider_solve and backend supports it (e.g. Browserbase proxies/stealth already configured). One attempt. Still blocked → L3.

L3 — Human handoff​

Call clarify with:

  • Screenshot (browser_vision / MEDIA path).
  • Ask from templates/human-handoff.md (RU/EN): reply готово / done or skip.
  • If challenge_gate.live_view_url is present on the last navigate response, paste that URL verbatim into the clarify question (labeled Live View:). Desktop will offer Open live browser so the user solves in the same Browserbase session (cookies preserved when BROWSERBASE_KEEP_ALIVE is on).
  • Note timeout → partial brief.

Surfaces (prefer first available): CDP user Chrome → headed/local or Browserbase Live View → computer_use only if browser tools cannot see a native WebView.

On готово/done: browser_snapshot again in the same session (do not browser_close first). Still challenged → ask once more, then L4.

Navigate payloads expose the resume contract under challenge_gate: preserve_session, resume_after_human: browser_snapshot_same_session, and a forbid list that includes close-before-resume. Prefer CDP user Chrome or Browserbase keep-alive so cookies warm the next navigate to the same host (Scenario E). Detect-only warm-up:

CHALLENGE_GATE_KEEP_SESSION=1 RUN_LIVE_CHALLENGE_DETECT=1 \
CHALLENGE_GATE_LIVE_URL='https://…' \
scripts/smoke-challenge-gate-live-detect.sh

Desktop: when the clarify question matches CAPTCHA/ChallengeGate copy, the UI shows Open live browser (when a Browserbase URL is in the question), Done / Skip page / Research Pro (answers: done / skip).

Durable kanban research jobs: block with kind=challenge (status stays blocked) so cron does not thrash overnight retries. Unblock after human clear or skip the source and continue.

Cron recipe (do not thrash)​

When a scheduled research job hits a wall:

  1. Append challenge.md / mark access: blocked_by_challenge.
  2. kanban_block / vibeos kanban block <id> --kind challenge --reason "…".
  3. Deliver a partial brief or alert — do not schedule tight retries on the same URL overnight.
  4. Human unblocks after clearing CAPTCHA (or closes the source as skipped).
  5. If unblock↔re-block loops, expect escalation to triage (BLOCK_RECURRENCE_LIMIT).

Operator manual E2E: docs/ops/challenge-gate-manual-e2e.md. Offline smoke: scripts/smoke-challenge-gate.sh.

L4 — Partial continue​

  1. Append/update challenge.md in the research workspace (template below).
  2. In sources.json set that URL access to blocked_by_challenge (or partial if some facts came from snippets).
  3. Continue with alternate public sources.
  4. Brief must state what was unreachable. Never fabricate wall content.
  5. If this was a kanban task: kanban_block / CLI with kind=challenge (or leave blocked until human resumes).

Artifact: challenge.md​

Prefer the helper (from this skill directory):

python3 scripts/append_challenge_log.py --path challenge.md --also-sources sources.json <<'EOF'
{"url":"https://…","type":"cloudflare_iuam","severity":"hard","detected_by":"title","layer_reached":"L4","resolved":"no","human_handoff":"yes","notes":"skipped"}
EOF

Or append manually:

# Challenge log

## Entry
- url: <URL>
- type: <challenge.type>
- severity: <soft|hard|human_only>
- detected_by: <title|snapshot|vision|provider>
- layer_reached: <L0|L1|L2|L3|L4>
- resolved: <yes|no|partial>
- human_handoff: <yes|no>
- notes: <one line>

sources.json field​

{
"url": "https://example.com/page",
"title": "...",
"access": "ok | challenge | blocked_by_challenge | partial",
"challenge_type": "cloudflare_iuam"
}

Pitfalls​

  • Do not spam browser_click on CAPTCHA widgets.
  • Do not treat CAPTCHA clear as permission to purchase or create accounts.
  • Do not use captcha-farm APIs unless the user explicitly configured an external solver (off by default; not in-tree).
  • Do not drive Chrome via computer_use when browser_* works.
  • Keep prompt-cache safe: do not swap toolsets mid-session to “enable solver”.

Verification​

  • Challenge classified within two tool turns of detection.
  • Auto attempts ≤ max_auto_attempts.
  • Hard wall → clarify or documented L4 skip.
  • challenge.md written when record_artifacts is true.
  • Brief does not claim facts only available behind an unresolved wall.