Skip to content

feat/389-Webhooks-Headers-Query-params-Methods-validation#6217

Merged
jchui-wd merged 6 commits intofeat/344-ambient-agents-webhooksfrom
feat/389-Headers-Query-Params-Methods-Validation-Etc
Apr 17, 2026
Merged

feat/389-Webhooks-Headers-Query-params-Methods-validation#6217
jchui-wd merged 6 commits intofeat/344-ambient-agents-webhooksfrom
feat/389-Headers-Query-Params-Methods-Validation-Etc

Conversation

@jchui-wd
Copy link
Copy Markdown
Contributor

@jchui-wd jchui-wd commented Apr 14, 2026

  • Added support for custom methods for webhook: GET POST PUT PATCH DELETE
  • Added support for header and query parameters
  • Added required support and validation for content type to be accessible even via payload
  • Added support for header, query to be auto filled when using '{{'
Test Videos Demo

query-params-and-auto-complete.mp4

query-params-and-auto-complete.mp4

body-headers-params-work-and-auto-complete.mp4

body-headers-params-work-and-auto-complete.mp4

method-validation-return-405-if-not-matched.mp4

method-validation-return-405-if-not-matched.mp4

headers-required-not-included-will-400.mp4

headers-required-not-included-will-400.mp4

content-type-validation.mp4

content-type-validation.mp4

Screenshots

HTTP Methods
Screenshot 2026-04-14 at 5 09 56 PM

Content Type
Only included these two to keep it simple for now. Can add further multipart/form-data and text/plain in the future
Screenshot 2026-04-14 at 5 10 00 PM

Expected Headers
Screenshot 2026-04-14 at 5 10 14 PM

Expected Query Params
Screenshot 2026-04-14 at 5 10 19 PM

Test Passes
Screenshot 2026-04-14 at 5 06 29 PM

…n both canvas, agentflow is out of scope but shows temporary ui
useParams() does not update when window.history.replaceState() is used
on first save (bypasses React Router). Fall back to Redux canvas.chatflow.id
so NodeInputHandler re-renders reactively when SET_CHATFLOW is dispatched.
Copy link
Copy Markdown
Contributor

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

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 webhookTrigger start type for Agent Flows, enabling workflows to be triggered via external HTTP requests with configurable validation for methods, headers, and parameters. It also adds support for $webhook.* variables and provides a UI for webhook URL management. Review feedback identifies the need for case-insensitive header handling in both validation and variable resolution to align with Express, and recommends passing the webhook payload as an object to maintain property accessibility in downstream nodes.

// Required header validation
const rawHeaderParams = startNode?.data?.inputs?.webhookHeaderParams
const webhookHeaderParams: Array<{ name: string; required: boolean }> = Array.isArray(rawHeaderParams) ? rawHeaderParams : []
const missingHeaders = webhookHeaderParams.filter((p) => p.required && headers?.[p.name] == null).map((p) => p.name)
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

HTTP header names are case-insensitive. Express automatically lowercases all header keys in req.headers. If a user configures a required header with mixed casing (e.g., X-API-Key), this check will fail because it looks for the exact casing in the headers object. You should lowercase the configured header name before checking its presence.

Suggested change
const missingHeaders = webhookHeaderParams.filter((p) => p.required && headers?.[p.name] == null).map((p) => p.name)
const missingHeaders = webhookHeaderParams.filter((p) => p.required && headers?.[p.name.toLowerCase()] == null).map((p) => p.name)

.map(([key, value]) => `${key}: ${value}`)
.join('\n')
} else if (incomingInput.webhook) {
finalInput = JSON.stringify(incomingInput.webhook)
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

Stringifying the webhook payload here causes the Start node to receive a string instead of an object. This prevents subsequent nodes from accessing nested properties via the start node's output (e.g., {{startAgentflow_0.output.webhook.body.foo}}). Since the run method of nodes can handle objects, it's better to pass the webhook object directly.

            finalInput = incomingInput.webhook

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

nice catch but the fix was in a different location.

Doing as gemini told to pass webhook object directly broke downstream nodes because it was expected to be string

Instead, the fix belongs in the Start node's run(), parse the JSON string back into an object before setting outputData.webhook, so nested path access like {{startAgentflow_0.output.webhook.body.action}} works without affecting the rest of the pipeline.

@jchui-wd jchui-wd changed the base branch from main to feat/344-ambient-agents-webhooks April 14, 2026 22:32
@jchui-wd jchui-wd changed the title feat/389-Webhooks-Headers-Query-paramsj-Methods-validation feat/389-Webhooks-Headers-Query-params-Methods-validation Apr 14, 2026
…k trigger

- Add webhookTrigger input type to Start node with HTTP method, content
  type, and expected headers/query/body param configuration
- New /api/v1/webhook/:id route with method, content-type, header, body,
  and query param validation (400/405/415 on mismatch)
- Namespace webhook payload as $webhook.body.*, $webhook.headers.*,
  $webhook.query.* in the flow runtime
- Resolve $webhook.* variables in downstream nodes via buildAgentflow.ts
- Auto-unwrap form-encoded `payload` JSON strings (e.g. GitHub webhooks)
  so $webhook.body.* paths work regardless of content type
- Expose webhook variable suggestions in the node variable picker
- Show copyable webhook URL in the Start node canvas UI
@jchui-wd jchui-wd force-pushed the feat/389-Headers-Query-Params-Methods-Validation-Etc branch from c43b746 to 58f4676 Compare April 14, 2026 22:45
@FlowiseAI FlowiseAI deleted a comment from gemini-code-assist bot Apr 14, 2026
@jchui-wd
Copy link
Copy Markdown
Contributor Author

/gemini review

Copy link
Copy Markdown
Contributor

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

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 enhances the Agentflow Webhook trigger by adding configuration for HTTP methods, Content-Type, and validation for headers, query parameters, and body parameters. It also introduces automatic JSON parsing for form-encoded payloads and namespaces webhook data for better accessibility. Feedback highlights the need for case-insensitive Content-Type validation and more flexible type checking for form-encoded data.


// Content-Type validation (startsWith handles "application/json; charset=utf-8" variants)
const webhookContentType = startNode?.data?.inputs?.webhookContentType
if (webhookContentType && !headers?.['content-type']?.startsWith(webhookContentType)) {
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 Content-Type validation is case-sensitive, which can lead to unexpected failures if a client sends the header with different casing (e.g., Application/JSON). Since HTTP headers are case-insensitive, the incoming header value should be normalized to lowercase before comparison.

        const incomingContentType = (headers?.['content-type'] ?? '').toLowerCase()
        if (webhookContentType && !incomingContentType.startsWith(webhookContentType.toLowerCase())) {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

webhookContentType will be lowercase since its hardcoded in the dropdown


// Body type validation (only for params that have an explicit type declared)
const typeMismatch = webhookBodyParams
.filter((p) => p.type != null && body?.[p.name] != null && typeof body[p.name] !== p.type)
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

The type validation using typeof may be too restrictive for application/x-www-form-urlencoded requests where numeric or boolean values are transmitted as strings. If the webhook is intended to support standard form-encoded data (outside of the payload JSON wrapper), consider allowing string-to-number or string-to-boolean conversions or loosening this check.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

this is fine since controller already unwraps JSON payload field before validation runs, preserving proper types.
This is done in src/controllers/webhook/index.ts line 22

@jchui-wd jchui-wd force-pushed the feat/389-Headers-Query-Params-Methods-Validation-Etc branch from 70ef829 to 847d803 Compare April 15, 2026 00:28
@jchui-wd jchui-wd marked this pull request as ready for review April 15, 2026 00:30
}
]
},
{
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.

might need to add client type to avoid showing this in internal app

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I think it should be fine since these fields will only show if webhooks get selected, but webhooks cannot be selected because it's hidden from the options on the dropdown

Image

@jchui-wd jchui-wd merged commit bbb7161 into feat/344-ambient-agents-webhooks Apr 17, 2026
1 check passed
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.

2 participants