Skip to main content

n8n

The n8n provider enables testing n8n AI agents and workflows via webhook endpoints. It handles common n8n response formats and supports tool call extraction and session management.

tip

Looking to run Promptfoo from n8n? See Using Promptfoo in n8n Workflows.

Basic Usage​

providers:
- n8n:https://your-n8n-instance.com/webhook/your-workflow-id

Promptfoo sends a POST request with:

{
"prompt": "..."
}

The provider automatically extracts output from common n8n response formats including output, response, message.content, text, and array responses. To avoid exposing webhook URLs in stored results or console output, URL-backed n8n provider routes use a stable n8n:webhook:<fingerprint> display ID.

Configuration​

providers:
- id: n8n:https://n8n.example.com/webhook/agent
config:
method: POST
headers:
Authorization: 'Bearer {{env.N8N_API_KEY}}'
body:
message: '{{prompt}}'
userId: '{{userId}}'
transformResponse: 'json.agent_response'

Config Options​

OptionTypeDefaultDescription
urlstring-Webhook URL (alternative to provider path)
methodstringPOSTGET, HEAD, POST, PUT, or PATCH; GET encodes body fields as query parameters and HEAD sends no body
headersobject-Additional request headers with Nunjucks templating
bodyobject/string{prompt}Request/body-query template; object form is recommended for JSON requests
transformResponsestring-JavaScript expression to extract output
sessionHeaderstring-Request header name for the session ID
sessionParserstring-JavaScript expression to extract a session ID
sessionFieldstringsessionIdBody field name for a supplied session ID

YAML method values are case-insensitive. TypeScript configurations using N8nProviderConfig use the uppercase names above.

Response Formats​

The provider handles these n8n response patterns:

{ "output": "Response text" }
{ "response": "Agent response" }
{ "message": { "content": "Hello" } }
[{ "json": { "output": "Result" } }]

Successful HTTP responses containing a non-empty error value, including n8n item responses such as [{ "json": { "error": "Workflow failed" } }], are reported as provider errors instead of evaluation output. Empty status values such as false or null do not turn a successful response into an error.

Tool Calls​

The provider extracts tool calls from agent responses:

tests:
- vars:
prompt: "What's my order status?"
assert:
- type: javascript
value: |
const toolCalls = context.providerResponse?.metadata?.toolCalls || [];
return toolCalls.some(tc => tc.name === 'order_lookup');

Supported formats:

{ "tool_calls": [{ "name": "search", "arguments": {...} }] }
{ "actions": [{ "tool": "search", "input": {...} }] }

Session Management​

For multi-turn conversations:

providers:
- id: n8n:https://n8n.example.com/webhook/agent
config:
sessionField: conversationId
sessionParser: 'data.sessionId'

The provider returns extracted session IDs as response.sessionId. Promptfoo's multi-turn strategies scope that value to the current conversation and supply it to subsequent turns as {{sessionId}}; the provider does not share one implicit session between independent test cases. For client-generated sessions, supply sessionId in test variables or through transformVars.

warning

Webhook URLs and responses can contain sensitive workflow data. Put authentication values in templated headers rather than URL query strings or paths, and treat local eval result exports and debug logs as sensitive. The provider hides webhook URLs in its display identifier and does not cache webhook requests or responses, so tokenized URLs and session-bearing payloads do not enter Promptfoo response-cache diagnostics or storage. The shared fetch layer now strips basic-auth credentials and known sensitive query parameters (api_key, token, signature, …) before writing URLs to debug logs, but path-as-secret URLs (/webhook/<unguessable-id>) still appear in those logs by design — keep LOG_LEVEL=debug output out of shared transcripts when running against tokenized webhooks. URLs remain part of your configuration and the outbound request.

The provider disables automatic transport, response-body, and scheduler retries for every HTTP method, including GET, HEAD, and PUT. A webhook can start a workflow with side effects (sending messages, writing to a database) regardless of its HTTP method. Failures are returned without replaying the workflow; check its execution status before running the eval again. A transient HTTP 429 still informs the adaptive scheduler: its Retry-After header delays later calls to the same provider without replaying the failed request.

n8n Variable Conversion​

n8n FormatPromptfoo Format
{{ $json.query }}{{query}}
{{ $json.user.name }}{{user.name}}

See Also​