Skip to content

Add Keenable Search tool node (keyless by default)#6542

Open
ilya-bogin-keenable wants to merge 2 commits into
FlowiseAI:mainfrom
keenableai:feat/keenable-search-node
Open

Add Keenable Search tool node (keyless by default)#6542
ilya-bogin-keenable wants to merge 2 commits into
FlowiseAI:mainfrom
keenableai:feat/keenable-search-node

Conversation

@ilya-bogin-keenable

Copy link
Copy Markdown

Adds a Keenable Search tool node, alongside the existing
SearXNG/Tavily/Brave/Exa/Serper search nodes.

The difference from the other search nodes is that it doesn't require an API
key. By default it uses Keenable's keyless public endpoint, so it works out of
the box. Providing a key (in the node config) switches to the authenticated
endpoint and lifts the rate limits.

Changes

  • packages/components/nodes/tools/KeenableSearch/: a custom Tool (via the
    SSRF-safe secureFetch), following the SearXNG node shape. Maps results to
    {title, link, snippet} JSON.
  • Optional API key, mode (pro/realtime), base-URL override, max results.
    realtime mode is validated to require a key.

Config

  • API Key: optional. Blank = keyless free tier; set it to lift limits / enable realtime.
  • Base URL: optional override (defaults to https://api.keenable.ai).

Verified the node's search path against the public endpoint (keyless).

Keenable is a web search API built for AI agents. Unlike the other search
nodes, it works without an API key by default (keyless public endpoint);
providing a key uses the authenticated endpoint and lifts rate limits.

- packages/components/nodes/tools/KeenableSearch/ (custom Tool via secureFetch,
  follows the SearXNG node shape)
- realtime mode validated to require a key

Usage: drop in the Keenable Search tool; no API key required.

@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 introduces a new Keenable Search tool integration, allowing AI agents to perform web searches using the Keenable API. It includes the tool implementation, configuration options, and an SVG icon. Feedback on the implementation highlights an issue where the search results are formatted as a comma-separated list of JSON strings instead of a valid JSON array, which could cause parsing errors for LLMs. A correction was suggested to stringify the entire array of mapped results.

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.

Comment on lines +204 to +208
return results
.slice(0, this.maxResults)
.filter((r) => r && r.url)
.map((r) => JSON.stringify({ title: r.title || '', link: r.url, snippet: r.description || '' }))
.toString()

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.

high

The current implementation maps each result to a JSON string and then calls .toString() on the array. This produces a comma-separated list of JSON objects (e.g., {"title":"..."},{"title":"..."}) instead of a valid JSON array (e.g., [{"title":"..."},{"title":"..."}]). This violates the tool's description ("Output is a JSON array of results") and will cause parsing errors for LLMs or agents expecting valid JSON.

Instead, map the results to plain objects first, and then use JSON.stringify() on the entire array.

        return JSON.stringify(
            results
                .slice(0, this.maxResults)
                .filter((r) => r && r.url)
                .map((r) => ({ title: r.title || '', link: r.url, snippet: r.description || '' }))
        )

_call mapped each result to a JSON string then .toString()'d the array, which
emitted a comma-joined list rather than a JSON array. Build plain objects and
JSON.stringify the whole array, matching the tool's documented output.
@ilya-bogin-keenable

Copy link
Copy Markdown
Author

Good catch — fixed. _call now builds plain result objects and JSON.stringifys the whole array, so the output is a valid JSON array as the tool description states (the previous .map(JSON.stringify).toString() emitted a comma-joined list).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant