Webhook to LLM
A small online shop gets messages through the contact form on its website: refund questions, delivery worries, questions about a phone. Here the form posts each message to an endpoint on your machine, the model sorts it into a category and an urgency with a one-sentence summary, and the result is added to an inbox file, newest at the bottom, so the team reads the urgent ones first. Anything else that can send an HTTP request (a script, another service) can post to it the same way.
Download the graph and save it in user/graphs/, or build it below. The graph is MIT-0: copy it and license what you build from it however you like. It has no model picked: pick one on the LLM node, or the LLM writes a mock reply instead of a triage.
1. Add the secret
Section titled “1. Add the secret”A webhook is reachable by anything that can reach the port, so give it a secret. In Settings › Secrets, add HOOK_SECRET with a long random value. The graph uses it as {{secret.HOOK_SECRET}}, and it will not turn On until the secret exists.
2. The nodes
Section titled “2. The nodes”| Node | Settings |
|---|---|
| Webhook, named Message | path contact, method POST, secret {{secret.HOOK_SECRET}} |
| Template, named Prompt | the first text below |
| LLM | model: pick Gemma 4 12b (Ollama), or the model you pulled |
| Preview, named Triage | none |
| Time, named Time | format 2026-06-08 14:30 |
| Template, named Entry | the text below |
| Append File, named Save | path inbox.md |
The Prompt’s text. Three fixed lines make every entry look the same, so the inbox is easy to scan:
A customer wrote through the contact form. Answer in three lines:Category: billing, order, product or otherUrgency: low, normal or highSummary: one sentence
{message}The Entry text, with a blank line at the end so entries stay apart:
## {time}
{triage}3. The wires
Section titled “3. The wires”| From | To |
|---|---|
Message trigger |
Prompt trigger |
Message body |
Prompt message |
Prompt trigger |
LLM trigger |
Prompt out |
LLM prompt |
LLM trigger |
Triage trigger |
LLM response |
Triage in |
Triage trigger |
Entry trigger |
Triage out |
Entry triage |
Time out |
Entry time |
Entry trigger |
Save trigger |
Entry out |
Save content |
The trigger runs down the line: the call fires the Prompt, the Prompt fires the LLM, and the Triage shows the reply and passes it on with one trigger, which fires the Entry and then Save. One message runs the model once and adds one entry. Each tag is named after the node its wire comes from: Message body becomes {message}, Triage out becomes {triage}, Time out becomes {time}.
The graph is one line of six nodes and a Time node, shown here in two halves. The first half takes the call and asks the model:

- The Webhook, named Message: its path, method and secret.
The second half takes the LLM’s trigger and response on the Triage and writes the entry. Here it is after one message from the contact form, with Gemma 4 12b picked:

- The Triage shows the reply (the category, the urgency and one sentence) and passes it on with one trigger.
- The Entry puts the time and the triage together.
- Save adds the entry to
inbox.md.
The Time wire crosses the Triage’s on its way into the Entry, because the Entry takes time between its trigger and triage.
4. Call it
Section titled “4. Call it”Save the graph as webhook-to-llm (the name is part of the URL), press On, and post a message the way the contact form would:
curl -X POST http://127.0.0.1:8770/hook/webhook-to-llm/contact \ -H "X-Webhook-Secret: <your HOOK_SECRET>" \ -H "Content-Type: text/plain" \ --data "Hi, I was charged twice for order #1042 (two payments of 389 euros on my card statement). Can you refund one of them? Thanks, Alice"The call answers {"ok": true} right away; the webhook does not wait for the model. A moment later the triage shows in the Triage node, and user/data/files/inbox.md has a new entry with the time on top. A wrong or missing secret gets a 401, and a call while the graph is Off gets a 404.
Change it
Section titled “Change it”- JSON in. Send
Content-Type: application/jsonand the parsed body arrives on the Message node’sjsonoutput; a Get node picks one field out of it. - Post the triage on. Swap the Append File for an HTTP Request to a chat service’s incoming webhook, so the team sees each message as it arrives. To send JSON safely, build it with Build JSON, turn it into text with Stringify, and use that as the body, so quotes and new lines in the triage are escaped.
- Reach it from outside. Only
/hook/*should ever face the internet, behind a proxy with TLS. Security explains how.