Skip to content

Add Firecrawl web monitoring example#5065

Open
htahir1 wants to merge 11 commits into
developfrom
example/firecrawl-web-monitor
Open

Add Firecrawl web monitoring example#5065
htahir1 wants to merge 11 commits into
developfrom
example/firecrawl-web-monitor

Conversation

@htahir1

@htahir1 htahir1 commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

What this does

Adds examples/firecrawl_web_monitor, an example that turns each Firecrawl monitor.page event into a ZenML pipeline run. Firecrawl monitors and scrapes a page; ZenML versions the raw event, normalized diff, change analysis, and final report as independently named artifacts (firecrawl_monitor_event, web_page_change, web_change_analysis, web_monitoring_report), so every check is comparable in the dashboard.

The pipeline:

ingest_firecrawl_event -> normalize_page_change -> analyze_page_change -> build_monitoring_report -> optionally_notify_slack
  • Event delivery: pull-based — run.py --monitor-id fetches the latest completed check from Firecrawl's API and runs the pipeline once per page result. No webhook infrastructure needed locally; the README documents triggering a pipeline snapshot via the ZenML REST API as the event-driven production path.
  • Analysis: uses an OpenAI model when an API key is stored in a ZenML secret (--llm-secret); otherwise falls back to Firecrawl's own meaningful-change judgment, and failing that a deterministic diff summary — each clearly labeled via the analyzer field. No credentials are needed for the first run (a realistic sample payload is bundled).
  • Alerting: meaningful changes can optionally be posted through the active stack's alerter (--notify-slack).
  • Extras: a Firecrawl monitor provisioning script (create_firecrawl_monitor.py, webhook optional) and an artifact history utility (history.py).

Why

Shows an event-driven, non-ML use of ZenML's artifact versioning and lineage: monitor-triggered runs, Pydantic contracts as artifacts, secrets-based LLM configuration, and portable Docker settings sourced from the example's pyproject.toml.

Implementation notes

  • zenml init is run in the example directory and the README instructs running all commands from there, so the source root and the relative pyproject_path in DockerSettings resolve correctly for remote image builds.
  • The example's pyproject installs no modules into site-packages (py-modules = []) — it exists purely to declare dependencies. This avoids shadowing generic module names and a Socket supply-chain false positive that matched the local constants.py against the obfuscated constants package on PyPI.
  • An earlier revision shipped a custom FastAPI webhook receiver; it was removed in favor of API pulling locally and snapshot triggers in production, dropping the fastapi/uvicorn dependencies.
  • Reviewed with a high-effort multi-agent code review; confirmed issues were fixed. Also validated live against a real Firecrawl monitor on the HN new-stories feed (which caught a null-diff edge case in baseline checks).
  • Every documented flow was executed successfully: fresh-clone quick start on released ZenML (0.96.1), local runs on an S3-backed stack, live --monitor-id pulls, snapshot creation via an AWS CodeBuild image builder, snapshot runs on a Kubernetes stack triggered both via Client().trigger_pipeline (including live payload + LLM secret as step-level parameter overrides) and via a raw external POST to the snapshot runs endpoint.
  • No test suite by design — examples in this repo are validated by running them.

Reviewer attention

  • The check-pulling path (fetch_firecrawl_check.py) maps Firecrawl's check-details response onto the same envelope as monitor.page webhook deliveries; per-page objects are identical per Firecrawl's docs, with monitorId/checkId merged in from the parent check.
  • Each page result becomes its own pipeline run, matching Firecrawl's one-event-per-page webhook semantics.

🤖 Generated with Claude Code

Turns each Firecrawl monitor.page webhook into a ZenML pipeline run that
versions the raw event, normalized diff, change analysis, and final
report as named artifacts. Analysis uses an OpenAI model when a ZenML
secret is provided and falls back to Firecrawl's own meaningful-change
judgment otherwise; a configured stack alerter can post meaningful
changes to Slack. Includes a FastAPI webhook receiver, a monitor
provisioning script, and an artifact history utility.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@htahir1 htahir1 added enhancement New feature or request release-notes Release notes will be attached and used publicly for this PR. labels Jul 10, 2026
@socket-security

socket-security Bot commented Jul 10, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addedpypi/​wheel@​0.47.099100100100100

View full report

@socket-security

socket-security Bot commented Jul 10, 2026

Copy link
Copy Markdown

All alerts resolved. Learn more about Socket for GitHub.

This PR previously contained dependency changes with security issues that have been resolved, removed, or ignored.

View full report

@github-actions github-actions Bot added the internal To filter out internal PRs and issues label Jul 11, 2026
Socket flagged the example branch because its manifest parser read the
setuptools py-modules list as PyPI dependencies and matched "constants"
against the obfuscated `constants` package on PyPI. The example never
depended on that package, but installing generic top-level module names
(constants, models, run) also shadows other projects in shared venvs.
The project now installs dependencies only; all code runs from the
example directory as the README already instructs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Documentation Link Check Results

Absolute links check passed
Relative links check passed
Last checked: 2026-07-17 09:46:13 UTC

htahir1 and others added 4 commits July 10, 2026 17:21
Firecrawl's monitoring API supports reading check results directly
(GET /v2/monitor/{id}/checks), so the local flow does not need webhook
infrastructure: `run.py --monitor-id` pulls the latest completed check
and runs the pipeline once per page result. The custom FastAPI receiver
is removed along with the fastapi/uvicorn dependencies; event-driven
production setups should trigger a ZenML pipeline snapshot via the REST
API instead, which the README now documents. Monitor creation makes the
webhook optional for the same reason.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Versions written from another environment (e.g. an S3 store without the
s3 integration installed locally) crashed history.py; they are now
reported and skipped. The README notes that zenml init scopes the
active stack to the directory and resets it to default, which silently
sent fresh-clone runs to the local store, and that S3-backed stacks
need the s3 integration installed before the first run.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The first check of a monitor reports pages with status 'new' and an
explicit null diff, which failed FirecrawlPageData validation when
pulling real checks via the API. Found by running the pipeline against
a live monitor; the bundled sample payload never exercised this.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Examples in this repo do not ship test suites; the pipeline is
validated by running it. Removing the tests also removes the need for
the dev optional dependencies.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@htahir1 htahir1 mentioned this pull request Jul 11, 2026
12 tasks
htahir1 and others added 5 commits July 10, 2026 22:24
Server-triggered runs of static pipelines reject pipeline-level
parameters; verified against a live snapshot trigger.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Fold the stack-set ordering into the quick-start block, remove the
redundant raw-payload section (superseded by --monitor-id), and delete
configs/prod.yaml, which nothing referenced.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Fix demo correctness and honesty issues raised in review of #5065:

- Align configs/snapshot.yaml goal with the baked pricing payload so a
  default snapshot run no longer analyzes a price diff against an
  unrelated "AI stories" goal.
- Select the newest monitor check by timestamp instead of assuming the
  checks API returns newest-first, falling back to the first entry when
  no recognized timestamp field is present.
- Warn when a monitor.page event carries multiple pages, since only the
  first is normalized; a multi-page event would otherwise drop pages
  silently.
- Document ongoing Firecrawl/OpenAI cost and add a curl snippet to delete
  a monitor after a demo, and note the pip fallback for the install step.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request internal To filter out internal PRs and issues release-notes Release notes will be attached and used publicly for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant