feat: n8n community node for TinyFish Web Agent#5
Conversation
- Node with 5 operations: Run SSE, Run Sync, Run Async, Get Run, List Runs - Credential with API key auth and connection test - Options: browser profile (lite/stealth), proxy, timeout - usableAsTool support for n8n AI Agent - README with configuration, usage, and contributing guide
Move node category from AI to Development so it appears in the main nodes panel search. Shorten node description and use absolute image URLs in README for npm rendering.
Remove retry logic and custom timeout in favor of n8n's built-in execution timeout. Removes timeout option from node UI.
- Remove setTimeout/clearTimeout to pass security scan - Fix credential icon format from object to string - Update repo URL to point to n8n subfolder - Remove timeout option from node UI
📝 WalkthroughWalkthroughThis pull request introduces a complete n8n integration for the TinyFish Web Agent service. It adds a new n8n node that exposes five operations: runSse, runSync, runAsync, getRun, and listRuns. The implementation includes a credential type for API authentication, HTTP request utilities with error handling, SSE stream consumption for real-time event processing, and comprehensive node configuration with UI field definitions. Supporting files include package metadata, TypeScript configuration, documentation, and standard project files. Sequence Diagram(s)sequenceDiagram
participant N8N as n8n Workflow
participant Node as Tinyfish Node
participant Creds as Credential Manager
participant API as TinyFish API
participant SSE as SSE Stream
N8N->>Node: Execute with parameters
Node->>Node: Build automation payload
Node->>Creds: Get API credentials
Creds-->>Node: Return API Key
Node->>API: POST /v1/runs (with auth header)
API-->>Node: Return run_id
alt SSE Operation
Node->>API: GET /v1/runs/{id}/sse
API-->>SSE: Stream connection
loop Event Stream
SSE-->>Node: Event (STARTED/STREAMING_URL/PROGRESS/COMPLETE)
Node->>Node: Parse and track run state
end
Node->>Node: Assemble final result
else Sync/Async Operation
Node->>API: Poll/callback handling
API-->>Node: Run result
end
Node-->>N8N: Return execution output
Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 2✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (2)
n8n/nodes/Tinyfish/GenericFunctions.ts (2)
223-225: Remove redundant catch-rethrow block.The
catch (error) { throw error; }block adds no value—the error would propagate identically without it.♻️ Proposed fix
return finalResult; - } catch (error) { - throw error; - } + } }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@n8n/nodes/Tinyfish/GenericFunctions.ts` around lines 223 - 225, Remove the redundant catch-rethrow block (the "catch (error) { throw error; }") in GenericFunctions.ts so the original error can naturally propagate; delete the catch clause and close the try block directly, leaving any surrounding logic intact and ensuring the function's return/throw behavior remains unchanged.
137-145: PassAbortSignalfromthis.getExecutionCancelSignal()to the fetch call.The
fetch()call can accept an abort signal to support graceful cancellation when a workflow is stopped mid-execution. Callthis.getExecutionCancelSignal()to retrieve the execution's cancel signal, then pass it as{ signal }in the fetch options. This aligns with n8n's execution cancellation patterns and allows the SSE stream to be properly closed when the workflow is terminated.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@n8n/nodes/Tinyfish/GenericFunctions.ts` around lines 137 - 145, The fetch call that posts to `${API_BASE_URL}/v1/automation/run-sse` must accept the workflow abort signal so the SSE stream is closed when execution is cancelled; update the fetch options in the try block (the call in GenericFunctions where response is awaited) to include signal: this.getExecutionCancelSignal() (e.g., const signal = this.getExecutionCancelSignal(); then pass signal in the options). Ensure the header/body remain unchanged and only add the signal property to the fetch options to integrate with n8n's execution cancellation.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@n8n/nodes/Tinyfish/GenericFunctions.ts`:
- Around line 53-56: The JSDoc above the TinyFish API request function in
GenericFunctions.ts is inaccurate: either implement retry logic or remove the
claim; to fix quickly, update the comment for the function (the "Make an
authenticated request to the TinyFish API." block that documents
makeTinyFishRequest / tinyfishRequest) to remove the line "Retries on 429/5xx
with exponential backoff (max 3 retries)" and replace it with a statement that
no automatic retries are performed, or alternatively implement retry behavior
inside makeTinyFishRequest: catch responses with status 429 or 5xx, perform
exponential backoff (e.g., delay = baseDelay * 2^attempt), retry up to 3
attempts, and surface the final error if all retries fail.
In `@n8n/package.json`:
- Around line 25-33: The build script currently copies tinyfish.svg but omits
the Tinyfish.node.json codex file; update the "build" script in package.json
(the scripts -> "build" entry) to also copy Tinyfish.node.json into the dist
output alongside the SVG (i.e. add a cp step for Tinyfish.node.json to
dist/nodes/Tinyfish/), so the community node metadata is included in the
published package.
In `@n8n/README.md`:
- Around line 91-101: The README's Options table documents a "Timeout" option
that no longer exists in the node UI; update the docs for consistency by
removing the "Timeout" row and any references to it in the "Options" section of
n8n/README.md (search for the "Timeout" table row and the "Maximum time to wait
for the automation to complete" description) OR if you prefer to keep the
feature, reintroduce the option in the node UI by adding a configurable
"timeout" option (labelled "Timeout", default 300s, 30–600s constraints)
wherever node options are defined and wired into the run logic; choose one
approach and make the corresponding change so the README and node UI match.
---
Nitpick comments:
In `@n8n/nodes/Tinyfish/GenericFunctions.ts`:
- Around line 223-225: Remove the redundant catch-rethrow block (the "catch
(error) { throw error; }") in GenericFunctions.ts so the original error can
naturally propagate; delete the catch clause and close the try block directly,
leaving any surrounding logic intact and ensuring the function's return/throw
behavior remains unchanged.
- Around line 137-145: The fetch call that posts to
`${API_BASE_URL}/v1/automation/run-sse` must accept the workflow abort signal so
the SSE stream is closed when execution is cancelled; update the fetch options
in the try block (the call in GenericFunctions where response is awaited) to
include signal: this.getExecutionCancelSignal() (e.g., const signal =
this.getExecutionCancelSignal(); then pass signal in the options). Ensure the
header/body remain unchanged and only add the signal property to the fetch
options to integrate with n8n's execution cancellation.
| /** | ||
| * Make an authenticated request to the TinyFish API. | ||
| * Retries on 429/5xx with exponential backoff (max 3 retries). | ||
| */ |
There was a problem hiding this comment.
Misleading JSDoc: retry logic is not implemented.
The comment states "Retries on 429/5xx with exponential backoff (max 3 retries)" but the function contains no retry logic. Either implement the retry mechanism or remove the inaccurate documentation.
📝 Proposed fix to correct the JSDoc
/**
* Make an authenticated request to the TinyFish API.
- * Retries on 429/5xx with exponential backoff (max 3 retries).
*/
export async function tinyfishApiRequest(📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| /** | |
| * Make an authenticated request to the TinyFish API. | |
| * Retries on 429/5xx with exponential backoff (max 3 retries). | |
| */ | |
| /** | |
| * Make an authenticated request to the TinyFish API. | |
| */ | |
| export async function tinyfishApiRequest( |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@n8n/nodes/Tinyfish/GenericFunctions.ts` around lines 53 - 56, The JSDoc above
the TinyFish API request function in GenericFunctions.ts is inaccurate: either
implement retry logic or remove the claim; to fix quickly, update the comment
for the function (the "Make an authenticated request to the TinyFish API." block
that documents makeTinyFishRequest / tinyfishRequest) to remove the line
"Retries on 429/5xx with exponential backoff (max 3 retries)" and replace it
with a statement that no automatic retries are performed, or alternatively
implement retry behavior inside makeTinyFishRequest: catch responses with status
429 or 5xx, perform exponential backoff (e.g., delay = baseDelay * 2^attempt),
retry up to 3 attempts, and surface the final error if all retries fail.
| "scripts": { | ||
| "build": "tsc && cp nodes/Tinyfish/tinyfish.svg dist/nodes/Tinyfish/tinyfish.svg && cp credentials/tinyfish.svg dist/credentials/tinyfish.svg", | ||
| "build:watch": "tsc --watch", | ||
| "lint": "tsc --noEmit", | ||
| "prepublishOnly": "npm run build" | ||
| }, | ||
| "files": [ | ||
| "dist" | ||
| ], |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check if Tinyfish.node.json exists
find . -name "*.node.json" -o -name "Tinyfish*" | head -20Repository: tinyfish-io/tinyfish-web-agent-integrations
Length of output: 274
🏁 Script executed:
#!/bin/bash
# Check the nodes directory structure
find . -path "*/nodes/Tinyfish*" -type f 2>/dev/null | head -20Repository: tinyfish-io/tinyfish-web-agent-integrations
Length of output: 283
🏁 Script executed:
#!/bin/bash
# Look at package.json to understand the package structure
cat -n package.json | head -50Repository: tinyfish-io/tinyfish-web-agent-integrations
Length of output: 131
🌐 Web query:
n8n community node package requirements codex json node.json dist
💡 Result:
Key n8n community node package requirements (esp. around codex JSON, node.json, and dist) are:
- Publish as an npm package whose name starts with
n8n-nodes-(or@scope/n8n-nodes-) and includes the keywordn8n-community-node-package. [1] - In
package.json, include ann8nsection that lists your compiled node and credential entrypoints (typically underdist/...) and usually only publish the build output via"files": ["dist"]. Example structure:n8n.credentials:dist/credentials/*.credentials.jsn8n.nodes:dist/nodes/**/**/*.node.js[2]
- In source, use the expected folder structure:
nodes/containing<NodeName>.node.tscredentials/containing<NodeName>.credentials.ts[3]
- Codex file (“node.json”): add a
<NodeName>.node.jsonmetadata file (the “codex file”) whose filename matches the node base file (forMyNode.node.ts→MyNode.node.json). It includes fields likenode,nodeVersion,codexVersion,categories, andresources. [4] - If you’re targeting verified community nodes: no run-time dependencies; also note n8n’s announced change that from May 1, 2026 all community nodes must be published via a GitHub Action and include an npm provenance statement. [1]
🏁 Script executed:
#!/bin/bash
# Read the n8n package.json
cat -n n8n/package.jsonRepository: tinyfish-io/tinyfish-web-agent-integrations
Length of output: 1663
🏁 Script executed:
#!/bin/bash
# Check the structure of dist after build to see what gets copied
ls -la n8n/dist/nodes/Tinyfish/ 2>/dev/null || echo "dist directory not found"Repository: tinyfish-io/tinyfish-web-agent-integrations
Length of output: 111
🏁 Script executed:
#!/bin/bash
# Check tsconfig.json to see if it copies JSON files
cat -n n8n/tsconfig.jsonRepository: tinyfish-io/tinyfish-web-agent-integrations
Length of output: 1002
Add Tinyfish.node.json to the build script.
The codex file won't be copied to dist by TypeScript compilation alone. Since n8n requires codex metadata files in community node packages, add an explicit copy step:
- "build": "tsc && cp nodes/Tinyfish/tinyfish.svg dist/nodes/Tinyfish/tinyfish.svg && cp credentials/tinyfish.svg dist/credentials/tinyfish.svg",
+ "build": "tsc && cp nodes/Tinyfish/tinyfish.svg dist/nodes/Tinyfish/tinyfish.svg && cp nodes/Tinyfish/Tinyfish.node.json dist/nodes/Tinyfish/Tinyfish.node.json && cp credentials/tinyfish.svg dist/credentials/tinyfish.svg",🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@n8n/package.json` around lines 25 - 33, The build script currently copies
tinyfish.svg but omits the Tinyfish.node.json codex file; update the "build"
script in package.json (the scripts -> "build" entry) to also copy
Tinyfish.node.json into the dist output alongside the SVG (i.e. add a cp step
for Tinyfish.node.json to dist/nodes/Tinyfish/), so the community node metadata
is included in the published package.
| ## Options | ||
|
|
||
| All run operations support the following optional settings under **Add Option**: | ||
|
|
||
| | Option | Default | Description | | ||
| |---|---|---| | ||
| | **Browser Profile** | `Lite` | Choose between `Lite` (fast, for standard sites) and `Stealth` (anti-detection mode for sites protected by Cloudflare, DataDome, CAPTCHAs, etc.). Start with Lite and switch to Stealth if you get blocked or see access denied errors. | | ||
| | **Enable Proxy** | Off | Route the browser through a geographic proxy. Recommended when using Stealth mode on geo-restricted or bot-protected sites. Available countries: US, GB, CA, DE, FR, JP, AU. | | ||
| | **Proxy Country** | US | Select the geographic location for the proxy. Only shown when Enable Proxy is turned on. Choose the country closest to the target site's expected region for best results. | | ||
| | **Timeout** | 300s | Maximum time to wait for the automation to complete (30–600 seconds). Most tasks complete within 60–120 seconds. Increase for complex multi-step workflows like pagination or form filling. | | ||
|
|
There was a problem hiding this comment.
Docs mismatch: Timeout option isn’t present in the node UI.
The README still documents a Timeout option, but the node’s options no longer include it. Please remove or reintroduce the option for consistency.
📝 Suggested doc update
-| **Timeout** | 300s | Maximum time to wait for the automation to complete (30–600 seconds). Most tasks complete within 60–120 seconds. Increase for complex multi-step workflows like pagination or form filling. |📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| ## Options | |
| All run operations support the following optional settings under **Add Option**: | |
| | Option | Default | Description | | |
| |---|---|---| | |
| | **Browser Profile** | `Lite` | Choose between `Lite` (fast, for standard sites) and `Stealth` (anti-detection mode for sites protected by Cloudflare, DataDome, CAPTCHAs, etc.). Start with Lite and switch to Stealth if you get blocked or see access denied errors. | | |
| | **Enable Proxy** | Off | Route the browser through a geographic proxy. Recommended when using Stealth mode on geo-restricted or bot-protected sites. Available countries: US, GB, CA, DE, FR, JP, AU. | | |
| | **Proxy Country** | US | Select the geographic location for the proxy. Only shown when Enable Proxy is turned on. Choose the country closest to the target site's expected region for best results. | | |
| | **Timeout** | 300s | Maximum time to wait for the automation to complete (30–600 seconds). Most tasks complete within 60–120 seconds. Increase for complex multi-step workflows like pagination or form filling. | | |
| ## Options | |
| All run operations support the following optional settings under **Add Option**: | |
| | Option | Default | Description | | |
| |---|---|---| | |
| | **Browser Profile** | `Lite` | Choose between `Lite` (fast, for standard sites) and `Stealth` (anti-detection mode for sites protected by Cloudflare, DataDome, CAPTCHAs, etc.). Start with Lite and switch to Stealth if you get blocked or see access denied errors. | | |
| | **Enable Proxy** | Off | Route the browser through a geographic proxy. Recommended when using Stealth mode on geo-restricted or bot-protected sites. Available countries: US, GB, CA, DE, FR, JP, AU. | | |
| | **Proxy Country** | US | Select the geographic location for the proxy. Only shown when Enable Proxy is turned on. Choose the country closest to the target site's expected region for best results. | |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@n8n/README.md` around lines 91 - 101, The README's Options table documents a
"Timeout" option that no longer exists in the node UI; update the docs for
consistency by removing the "Timeout" row and any references to it in the
"Options" section of n8n/README.md (search for the "Timeout" table row and the
"Maximum time to wait for the automation to complete" description) OR if you
prefer to keep the feature, reintroduce the option in the node UI by adding a
configurable "timeout" option (labelled "Timeout", default 300s, 30–600s
constraints) wherever node options are defined and wired into the run logic;
choose one approach and make the corresponding change so the README and node UI
match.
Summary