feat: add PerplexitySearch tool node#6314
Conversation
Adds a new PerplexitySearch tool node to the Tools category, mirroring the existing ExaSearch and TavilyAPI tool nodes. The node wraps Perplexity's Search API (POST https://api.perplexity.ai/search) and exposes query, max results, search domain filter, and search recency filter inputs to the LLM. Reuses the existing perplexityApi credential type already used by the ChatPerplexity chat model. Refs FlowiseAI#1860
There was a problem hiding this comment.
Code Review
This pull request introduces a new Perplexity Search tool, consisting of a UI node component, core logic for API interaction, and an associated icon. The reviewer suggested several improvements to align with project standards and security practices, specifically recommending the use of secureFetch to mitigate SSRF risks and refactoring the PerplexitySearchTool class to extend StructuredTool instead of DynamicStructuredTool to avoid unnecessary complexity.
| import fetch from 'node-fetch' | ||
| import { DynamicStructuredTool } from '../OpenAPIToolkit/core' |
There was a problem hiding this comment.
Use secureFetch from the project's utilities instead of node-fetch directly. This ensures that the outgoing request adheres to the project's security policies, such as SSRF protection. Additionally, the tool should extend StructuredTool from @langchain/core/tools rather than DynamicStructuredTool from the OpenAPIToolkit. DynamicStructuredTool is a specialized class for the OpenAPI toolkit that includes complex logic for sandboxing and custom code execution which is not required for this implementation.
| import fetch from 'node-fetch' | |
| import { DynamicStructuredTool } from '../OpenAPIToolkit/core' | |
| import { secureFetch } from '../../../src/utils' | |
| import { StructuredTool } from '@langchain/core/tools' |
| export class PerplexitySearchTool extends DynamicStructuredTool { | ||
| apiKey: string | ||
| maxResults: number | ||
| searchDomainFilter?: string[] | ||
| searchRecencyFilter?: 'hour' | 'day' | 'week' | 'month' | 'year' | ||
|
|
||
| constructor(args: PerplexitySearchParameters) { | ||
| const schema = createPerplexitySearchSchema() | ||
|
|
||
| const toolInput = { | ||
| name: args.name || 'perplexity_search', | ||
| description: args.description || desc, | ||
| schema: schema, | ||
| baseUrl: '', | ||
| method: 'POST', | ||
| headers: {} | ||
| } | ||
| super(toolInput) | ||
| this.apiKey = args.apiKey | ||
| this.maxResults = args.maxResults ?? 5 | ||
| this.searchDomainFilter = args.searchDomainFilter | ||
| this.searchRecencyFilter = args.searchRecencyFilter | ||
| } |
There was a problem hiding this comment.
Refactor PerplexitySearchTool to extend StructuredTool and simplify the constructor. This avoids inheriting unused properties and methods from DynamicStructuredTool and aligns with standard tool implementations in the repository. The schema should be defined as a class property.
export class PerplexitySearchTool extends StructuredTool {
apiKey: string
maxResults: number
searchDomainFilter?: string[]
searchRecencyFilter?: 'hour' | 'day' | 'week' | 'month' | 'year'
schema = createPerplexitySearchSchema()
constructor(args: PerplexitySearchParameters) {
super({
name: args.name || 'perplexity_search',
description: args.description || desc
})
this.apiKey = args.apiKey
this.maxResults = args.maxResults ?? 5
this.searchDomainFilter = args.searchDomainFilter
this.searchRecencyFilter = args.searchRecencyFilter
}| throw new Error('Perplexity API Key is required') | ||
| } | ||
|
|
||
| const response = await fetch('https://api.perplexity.ai/search', { |
There was a problem hiding this comment.
Summary
Adds a new Perplexity Search tool node under
packages/components/nodes/tools/PerplexitySearch/, mirroring the existingExaSearchandTavilyAPItool nodes.The node wraps Perplexity's Search API (
POST https://api.perplexity.ai/search) and exposes aqueryinput plus optional configuration:Max Results— number of results to return (default5)Search Domain Filter— comma-separated allow/deny list, supports-domain.comfor negationSearch Recency Filter—hour/day/week/month/yearTool Description— overridable description fed to the LLMResults are formatted as numbered text (title, URL, optional date, snippet), matching the agent-friendly output style of
ExaSearch.The node reuses the existing
perplexityApicredential type already used by theChatPerplexitychat model — no new credential file is required. Auth is sent asAuthorization: Bearer <key>.Refs #1860.
What was added
packages/components/nodes/tools/PerplexitySearch/PerplexitySearch.ts— node definition (label, inputs, credential,init).packages/components/nodes/tools/PerplexitySearch/core.ts—PerplexitySearchToolextending the project'sDynamicStructuredTool, performing thefetchcall.packages/components/nodes/tools/PerplexitySearch/perplexity.svg— Perplexity brand mark (copied from the existingChatPerplexitychat model node so the tool catalog stays visually consistent; design team can swap it later if desired).How to use
Test plan
pnpm install && pnpm buildfrom the repo root completes without errors.perplexityApicredential, calling the tool from an agent returns ranked results fromhttps://api.perplexity.ai/search.Search Domain Filterto e.g.nytimes.com,-pinterest.comandSearch Recency Filter=weekis reflected in the request body (search_domain_filter,search_recency_filter).