Skip to content

feat(firecrawl): add search tool support#3260

Open
yasu-oh wants to merge 4 commits into
langgenius:mainfrom
yasu-oh:main
Open

feat(firecrawl): add search tool support#3260
yasu-oh wants to merge 4 commits into
langgenius:mainfrom
yasu-oh:main

Conversation

@yasu-oh

@yasu-oh yasu-oh commented Jun 7, 2026

Copy link
Copy Markdown
Contributor

Summary

Add Firecrawl Search API support to the Firecrawl tool plugin.

This change adds a new search tool backed by Firecrawl v2 POST /search, allowing users to search the web and optionally scrape returned search results through scrapeOptions.

Included changes:

  • Add FirecrawlApp.search() for POST /v2/search
  • Add tools/search.py implementation
  • Add tools/search.yaml tool definition
  • Register the Search tool in provider/firecrawl.yaml
  • Update Firecrawl README to include the new Search action
  • Add focused tests for endpoint/payload construction and option handling

Change Type

  • Documentation / non-plugin change
  • Non-LLM plugin (tools, extensions, datasource, etc.)
  • LLM plugin

Screenshots / Videos

N/A — this is a tool/API integration change. No UI screenshots were captured.

Before After
Firecrawl plugin supported Crawl Job, Crawl, Map, and Scrape actions. Firecrawl plugin also supports a Search action using Firecrawl v2 /search.

LLM Plugin Checklist

N/A — this is a Non-LLM tool plugin change.

Areas affected by this change (check all that apply)
  • Message flow (system messages, user ↔ assistant turn-taking)
  • Tool interaction flow (multi-round usage, Agent App and Agent Node)
  • Multimodal input (images, PDFs, audio, video, etc.)
  • Multimodal output (images, audio, video, etc.)
  • Structured output (JSON, XML, etc.)
  • Token consumption metrics
  • Other LLM functionality (reasoning, grounding, prompt caching, etc.)
  • New models / model parameter fixes

Version

  • Bumped top-level version in manifest.yaml (not the one under meta)
  • dify_plugin>=0.3.0,<0.6.0 is declared in pyproject.toml and locked in uv.lock (or kept in requirements.txt for legacy plugins without uv.lock) — SDK docs

Note: No dependency changes were made. The existing Firecrawl plugin currently declares dify_plugin>=0.9.0.

Testing

  • Local deployment — Dify version:
  • SaaS (cloud.dify.ai)

Focused local verification was performed from tools/firecrawl:

uv run --with pytest pytest tests/test_search.py -q

Result:

3 passed, 2 warnings

The warnings are from existing dify_plugin dependency behavior (gevent monkey patch / Pydantic deprecation), not from this change.

Additional checks:

uv run --with ruff ruff check tools/search.py tests/test_search.py

Result:

All checks passed!
uv run python -m compileall tools provider tests

Result:

compile OK

YAML parsing was also verified for:

provider/firecrawl.yaml: ok
tools/search.yaml: ok

Static security scan of added lines:

static security scan: ok

@dosubot dosubot Bot added size:M This PR changes 30-99 lines, ignoring generated files. enhancement New feature or request labels Jun 7, 2026
@yasu-oh yasu-oh temporarily deployed to tools/firecrawl June 7, 2026 03:26 — with GitHub Actions Inactive

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds a new "Search" tool to the Firecrawl plugin, enabling web searching and optional scraping of results. It implements the SearchTool class, updates the FirecrawlApp client to support the /v2/search endpoint, defines the tool configuration in YAML, and adds comprehensive tests. The feedback suggests safely retrieving the required query parameter using .get() to avoid potential KeyError exceptions during tool invocation.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

payload["scrapeOptions"] = scrape_options or None
payload = {k: v for (k, v) in payload.items() if v not in (None, "")}

search_result = app.search(query=tool_parameters["query"], **payload)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using direct dictionary access tool_parameters["query"] can raise a KeyError if the query parameter is missing or omitted during invocation. It is safer to use defensive programming and fetch it with .get("query") or raise a descriptive error.

Suggested change
search_result = app.search(query=tool_parameters["query"], **payload)
query = tool_parameters.get("query")
if not query:
raise ValueError("The 'query' parameter is required and cannot be empty.")
search_result = app.search(query=query, **payload)

@crazywoola

Copy link
Copy Markdown
Member

Please resolve the conflicts :)

@yasu-oh yasu-oh temporarily deployed to tools/firecrawl June 10, 2026 03:55 — with GitHub Actions Inactive
@yasu-oh yasu-oh deployed to tools/firecrawl June 10, 2026 04:02 — with GitHub Actions Active
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request size:M This PR changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants