Install
openclaw skills install @scrapfly/scrapfly-alertingThreshold-based alerting on Scrapfly account metrics. Wire up rules like "alert me when scrape success rate drops below 95% for 10 minutes" and receive notifications via email, webhook, or in-app. Use when the user asks to "set up an alert", "monitor my scrape success rate", "tell me when my scrapes start failing", "alert on ASP block rate", "watch a specific domain", or any task involving the Scrapfly alerting product. Covers the three call paths: REST API, MCP alert_* tools, and the scrapfly alert CLI subcommand. Enterprise plan feature; GATED behind the ALERTING feature flag on customer accounts.
openclaw skills install @scrapfly/scrapfly-alertingScrapfly Alerting lets customers attach threshold rules to project
metrics (success rate, block rate, error count, cost, latency, ...) and
receive notifications when a rule sustains a breach over a configurable
window. Three call paths share the same backend: REST API on
api.scrapfly.io, MCP alert_* tools, and the scrapfly alert CLI
subcommand. Pick whichever fits the caller — the same payload shapes,
same state machine, same notification channels.
This skill is meant to be read by an AI agent that has been asked to set up an alert or manage existing alerts on a Scrapfly account. The golden rule is: never invent a threshold. Always ground the choice in real account behavior, then validate against history before committing.
list, get, snooze a
noisy alert, unsnooze after a maintenance window, etc.)count-active)permanent:feature_flag:alerting tag will see a 403 on write
endpoints; read endpoints stay accessible to staff for triage.scp-live-...). The MCP and CLI surfaces
resolve project context from the api-key — pass --project-uuid /
project_uuid only when the customer explicitly names a non-default
project.This is the same flow used by all three call paths. Run it in order; each step grounds the next.
metric_id values and their allowed_dimensions. Never invent a
metric ID; always pick from the registry.confirm=true
(or the CLI's interactive confirm) to commit.Concrete worked example: "alert me when my scrape success rate drops
noticeably below current baseline" → discover baseline 65.93% → choose
threshold 55% (10pt below normal) → preview shows fired_count: 0 over
last 24h → create with email channel. The agent never guessed; every
number came from real data.
When the agent is connected to the Scrapfly MCP server, ten alert tools
plus two monitoring tools cover the full surface. Read tools have no
side-effect; write tools require confirm=true to commit.
| Tool | Mode | Purpose |
|---|---|---|
monitoring_get_metrics | read | Per-product aggregates: pick product (scrape, screenshot, extraction, crawl, browser), period (last5m, last1h, last24h, last7d, subscription), and optionally aggregation (account, project, target). |
monitoring_get_target_metrics | read | Per-domain breakdown for one site. domain is required; group_subdomain rolls subdomains together. |
alert_metric_families | read | Discover legal metric_id values + their allowed_dimensions. Call before alert_create. |
alert_list | read | List the caller's alerts with optional filters (state, project_uuid, metric_id). |
alert_get | read | Full alert row including the per-alert HMAC signing key for webhook channels. |
alert_preview | read | Replay an unsaved rule against history. Use to validate the threshold before alert_create. |
alert_create | write (confirm) | Persist a new alert. Leave project_uuid empty to inherit. |
alert_update | write (confirm) | Patch fields. Server auto-snoozes for sustained_minutes after a successful edit. |
alert_delete | write (confirm) | Permanent. |
alert_snooze | write (confirm) | Mute notifications. Pass minutes:N OR until_resolved:true. |
alert_unsnooze | write (confirm) | Clear active snooze. |
alert_test | write (confirm) | Fire a synthetic notification on every configured channel without touching state. |
MCP example (the data-driven workflow from above, expressed as tool calls):
// Step 1 — baseline
{"tool":"monitoring_get_metrics","parameters":{"product":"scrape","period":"last7d","aggregation":["account"]}}
// Step 2 — discover the registry
{"tool":"alert_metric_families","parameters":{}}
// Step 3 — preview the chosen threshold against last-24h history
{"tool":"alert_preview","parameters":{
"metric_id":"scrape.success_rate",
"comparator":"lt","threshold":55,
"sustained_minutes":5,"range_minutes":1440
}}
// Step 4 — dry-run create (no confirm)
{"tool":"alert_create","parameters":{
"name":"Scrape Success Rate Low",
"metric_id":"scrape.success_rate",
"comparator":"lt","threshold":55,
"sustained_minutes":5,
"notify_channels":[{"kind":"email","target":"ops@example.com"}]
}}
// Step 5 — commit
{"tool":"alert_create","parameters":{ ...same..., "confirm":true }}
info_account.account.account_id is NOT the project UUID. Do not
pass it as project_uuid — that returns
ERR::ALERT::PROJECT_NOT_FOUND. Leave project_uuid and
project_name empty unless the customer explicitly named a
non-default project; the server resolves the api-key's current
project automatically.alert_preview uses the same
state-machine Tick() the live evaluator uses, so the historical
count is exactly what production would have produced under the same
rule. A rule that fired 15 times in the last 24h will spam the
customer.DRY RUN — POST /alert would be invoked with: { ... } so the user
can review before paying notification cost.The scrapfly CLI exposes the same surface as scrapfly alert ...
subcommands. Output is the standard {success, product, data|error}
JSON envelope so you can pipe it through jq.
# Discover what's available
scrapfly alert metric-families
# Tune the threshold against history
scrapfly alert preview \
--metric scrape.success_rate \
--comparator lt \
--threshold 95 \
--sustained-minutes 10 \
--range-minutes 1440
# Create the alert (channels are repeatable)
scrapfly alert create \
--name "Scrape Success Rate Low" \
--metric scrape.success_rate \
--comparator lt \
--threshold 95 \
--sustained-minutes 10 \
--channel email:ops@example.com \
--channel webhook:https://hooks.example.com/scrapfly
# Or from a version-controlled file (IaC-style)
scrapfly alert create --file ./alerts/success_rate.json
# Manage existing alerts
scrapfly alert list --state triggered
scrapfly alert get <alert-uuid>
scrapfly alert series <alert-uuid> --range-minutes 1440
scrapfly alert update <alert-uuid> --threshold 90
scrapfly alert snooze <alert-uuid> --minutes 30
scrapfly alert snooze <alert-uuid> --until-resolved
scrapfly alert unsnooze <alert-uuid>
scrapfly alert test <alert-uuid>
scrapfly alert delete <alert-uuid>
Full flag reference: scrapfly alert create --help (or any subcommand
plus --help). The flags map 1:1 to the REST payload below.
Direct HTTP if you're not using MCP or the CLI. Same endpoints, same payloads.
POST /alert?key=scp-live-...
Content-Type: application/json
{
"name": "Scrape Success Rate Low",
"metric_id": "scrape.success_rate",
"comparator": "lt",
"threshold": 95,
"sustained_minutes": 10,
"notify_channels": [
{"kind": "email", "target": "ops@example.com"},
{"kind": "webhook", "target": "https://hooks.example.com/scrapfly"}
]
}
Server-side defaults fill in when zero values are sent:
eval_cadence_seconds: 300sustained_minutes: the metric family's recommended default (or 5)evaluation_window_m: sustained_minutesno_data_policy: ignorerenotify_minutes: 60recovery_minutes: 0 (instant recovery)Other endpoints follow the same shape: GET /alert, GET /alert/:uuid, GET /alert/metric-families, GET /alert/count-active, GET /alert/:uuid/series, POST /alert/preview, PUT /alert/:uuid, DELETE /alert/:uuid, POST /alert/:uuid/snooze, POST /alert/:uuid/unsnooze, POST /alert/:uuid/test.
Each channel has a kind and a target:
| Kind | Target | Notes |
|---|---|---|
email | RFC 5322 address | Delivered via the Scrapfly mailer. Subject carries the alert name and the breach value. |
webhook | HTTPS URL | POST with HMAC-SHA256 signature in X-Scrapfly-Signature. Per-alert key generated on create; read it from alert_get or the create response. |
inapp | empty string | Surfaces in the dashboard's bell-icon notification panel. |
The dedup layer suppresses re-fires that fall in the same minute
bucket. The renotify cadence (renotify_minutes, default 60) controls
how often a sustained breach re-notifies, capped at 6 / day per alert.
Alerts transition between these lifecycle states (alert_list filters
on state):
ok — no breach.pending — breach observed but hasn't yet sustained for
sustained_minutes.triggered — breach sustained; notifications fired.recovering — non-breaching but hasn't yet sustained
recovery_minutes of clean data (default 0 = instant recovery).no_data — the eval window had zero rows. Behavior controlled by
no_data_policy.snoozed — operator-muted via alert_snooze. Resumes on
unsnooze or the until_resolved sentinel auto-clears at the next OK
transition.count-active sums triggered + pending + recovering — the
"needs operator attention" set. Don't include snoozed or no_data.
ERR::ALERT::UNKNOWN_METRIC — metric_id not in the registry. Re-call alert_metric_families.ERR::ALERT::INVALID_DIMENSIONS — passed a key that isn't in the metric family's allowed_dimensions.ERR::ALERT::INVALID_THRESHOLD — non-finite number, or comparator not in gt|lt|gte|lte|eq|neq.ERR::ALERT::INVALID_SUSTAINED_WINDOW — sustained_minutes outside 1–1440.ERR::ALERT::CHANNEL_UNREACHABLE — zero channels OR channel kind not in email|webhook|inapp OR a test call couldn't deliver to its channel.ERR::ALERT::PROJECT_NOT_FOUND — project_uuid didn't match the api-key's project. Most often: the agent passed account_id here by mistake. Fix: omit the field and let the server fall back.ERR::ALERT::NOT_FOUND — alert doesn't exist OR isn't yours. The server collapses both cases to prevent enumeration. Don't try to distinguish.ERR::ALERT::EVAL_TIMEOUT — the preview/series query took too long. Reduce range_minutes.ERR::ALERT::INTERNAL — generic server-side failure; check the response body's details field.scrapfly-cli — the CLI binary the scrapfly alert subcommand ships with.scrapfly-agent-rules — cross-tool golden rules including the monitoring→preview→create flow.scrapfly-scraper — the underlying scrape product; metric IDs like scrape.success_rate come from there.