Skip to content
Sponsor

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.

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.

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 other
Urgency: low, normal or high
Summary: one sentence
{message}

The Entry text, with a blank line at the end so entries stay apart:

## {time}
{triage}
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 first half of the downloaded webhook graph: the Webhook named Message feeds the Prompt, and the Prompt feeds the LLM
  1. 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 second half of the webhook graph after a contact-form message about a double charge: the Triage shows the model's category, urgency and summary, and a Time node and the Triage feed the Entry, which feeds Save
  1. The Triage shows the reply (the category, the urgency and one sentence) and passes it on with one trigger.
  2. The Entry puts the time and the triage together.
  3. 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.

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:

Terminal window
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.

  • JSON in. Send Content-Type: application/json and the parsed body arrives on the Message node’s json output; 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.