n8n → Hermes: choose an API call or an event webhook
Intermediate10 min readAutomations

n8n → Hermes: choose an API call or an event webhook

Keep deterministic state in n8n and choose the Hermes API when n8n needs an agent result, or the webhook adapter when an event should trigger a configured Hermes delivery.

What you should be able to do

Use Hermes’s bearer-authenticated API server when n8n needs the agent result. Use the separately configured webhook adapter for authenticated event ingress and a Hermes-managed delivery target. Neither bounded cache replaces durable application idempotency in n8n.

Saved only in this browser.
In this article

n8n is strong at predictable automation: receive an event, validate fields, call APIs, wait for humans, and write results. Hermes Agent is useful when the next step needs interpretation, such as triaging language, drafting a reply, investigating with tools, or deciding what “urgent” means in context.

There are two clean patterns, and they have different contracts. If n8n needs the agent’s result so it can validate, store, approve, or send it, call the Hermes API server. If n8n is emitting an event and Hermes should deliver the result to a configured Slack, Telegram, GitHub, email, or other supported target, call the webhook adapter.

Use the official Hermes API server documentation, official webhook documentation, and NousResearch repository. There is no first-party Hermes-specific n8n node documented here; n8n uses its generic HTTP Request node.

A generic n8n sender should use the Hermes V2 HMAC contract. Other providers can have adapter-specific authentication, such as GitHub’s signature or GitLab’s token. Every route needs its documented secret. INSECURE_NO_AUTH is for loopback testing only; current Hermes refuses to start it on a non-loopback bind.

When to hand off (and when not to)

Keep in n8n

  • Schema validation and redaction
  • Idempotency keys and dedupe (idempotency and human gates)
  • CRM/email/Slack connectors with explicit credentials
  • Human approval queues before external send
  • Cron and webhook triggers

Hand to Hermes

  • Ambiguous classification that needs document or repo context
  • Multi-step investigation with tools under Hermes’s runtime and accepted capability policy
  • Drafting that should use persistent memory or skills
  • Research over private corpora the agent already can reach

Do not hand off

  • Pure if/then routing you can express in Switch nodes
  • High-volume generation loops that belong behind a cheaper classifier first
  • Secrets n8n should never forward (paste tokens into Hermes “for convenience”)

If the whole job is agent-shaped and chat-triggered, you may want a gateway UX instead. See OpenClaw vs Hermes by job. For first n8n agents without Hermes, see first AI agent in n8n.

Choose the contract before you build

Result needed by n8n:
Event → n8n validate + durable key claim
      → HTTP Request (Bearer) → Hermes :8642/v1/responses or /v1/runs
      → n8n validates result → human gate → connector

Event delivered by Hermes:
Event → n8n validate + durable key claim
      → HTTP Request (V2 HMAC) → Hermes :8644/webhooks/<name>
      → Hermes agent run → configured Hermes delivery target

The API server defaults to 127.0.0.1:8642, requires API_SERVER_KEY, and exposes OpenAI-compatible /v1/chat/completions, /v1/responses, and the Runs API. Its key grants access to Hermes’s full agent toolset, including terminal and file operations, so keep the bind private and the caller narrowly controlled.

The webhook adapter defaults to port 8644; its health check is http://localhost:8644/health, and routes live under /webhooks/<name>. A webhook run sends its result to the route’s configured deliver target. The documented target list includes chat platforms, GitHub comments, email, Home Assistant, and log. It does not define a generic HTTP callback target.

n8n remains the durable state owner for SaaS connectors and human gates. Hermes remains the bounded reasoning step.

Webhook event contract: small and explicit

Avoid dumping the entire n8n item tree. Send a task object the agent can act on without guessing.

Illustrative contract:

{
  "application_key": "ticket-18422",
  "task": "Classify severity and draft a support reply. Do not send email.",
  "customer": {
    "name": "Example GmbH",
    "plan": "business"
  },
  "message": "VPN drops every morning around 09:00.",
  "constraints": {
    "output": "json",
    "fields": ["severity", "rationale", "draft_reply"],
    "language": "en"
  }
}

Rules:

  1. One expected outcome per route, or one clear enum of outcomes.
  2. Keep the durable application key in n8n or the business system. A body field can correlate logs, but Hermes does not treat it as its webhook dedupe key.
  3. Send a stable X-Request-ID for retries of the same handoff. Hermes caches webhook delivery IDs for one hour and skips a duplicate run or delivery within that window.
  4. Say what the agent must not do, such as send, refund, or delete.
  5. Prefer excerpts over full attachments. Store blobs elsewhere and pass only references Hermes is authorised to fetch.

Create a dedicated Hermes webhook route per workflow family (support-triage, ops-alert) with its own prompt, filters, secret, skills, and delivery configuration. Treat every payload field as untrusted content. Sandbox the runtime, narrow the prompt template, remove unnecessary tools, and keep approvals on for destructive or outbound actions.

Exact Hermes V2 HMAC contract

For a generic n8n sender, current Hermes docs specify V2:

  • header X-Webhook-Timestamp: Unix seconds;
  • header X-Webhook-Signature-V2: lowercase hexadecimal HMAC-SHA256;
  • signed bytes: <timestamp>.<raw-request-body>;
  • replay window: the timestamp must be within ±300 seconds of Hermes’s clock.

The V1 X-Webhook-Signature body-only form remains compatible but has no replay protection. Do not use it for new workflows. See the upstream security contract.

Self-hosted n8n signing node

Store HERMES_WEBHOOK_SECRET only in the n8n process secret/environment mechanism. Do not put it in a Set node or committed workflow JSON. In a Code node, use the built-in Node crypto module only if your n8n configuration permits that module and node access to the environment:

const { createHmac } = require('crypto');

const timestamp = Math.floor(Date.now() / 1000).toString();
const body = JSON.stringify($json.hermes_payload);
const secret = $env.HERMES_WEBHOOK_SECRET;

if (!secret) throw new Error('HERMES_WEBHOOK_SECRET is not configured');

const signature = createHmac('sha256', secret)
  .update(`${timestamp}.${body}`, 'utf8')
  .digest('hex');

return [{ json: { body, timestamp, signature } }];

For self-hosted n8n, allow only the required built-in module according to the current Code-node module configuration; do not enable arbitrary external modules. With external Task Runners, configure NODE_FUNCTION_ALLOW_BUILTIN=crypto as an env-override in /etc/n8n-task-runners.json, not only on the main n8n container. $env access also depends on N8N_BLOCK_ENV_ACCESS_IN_NODE. If your security policy blocks it, use an organisation-approved signing service or secret-backed custom node. Do not paste the secret into the workflow.

Configure the following HTTP Request node:

FieldValue
MethodPOST
URLhttps://<hermes-host>/webhooks/support-triage
Body content typeRaw / application/json
Body{{ $json.body }} (send the string unchanged)
HeaderX-Webhook-Timestamp: {{ $json.timestamp }}
HeaderX-Webhook-Signature-V2: {{ $json.signature }}
HeaderX-Request-ID: ticket-18422:handoff-v1 (stable for retries of this handoff)
Timeout/retryBounded; retry the handoff only under the durable key policy

Do not choose the HTTP node’s structured JSON editor after signing; reserialisation could change the bytes. Fail closed on non-2xx. A 200 response can mean delivered or duplicate, depending on the route and delivery ID; it is not a structured agent result for n8n. Do not mark the durable n8n key completed merely because Hermes accepted or delivered the event.

For LAN-only Hermes webhooks, still use the documented authentication. Network locality is not authentication. Current defaults also limit each webhook route to 30 requests per minute, reject bodies over 1 MB, and cache X-Request-ID or X-GitHub-Delivery values for one hour. Those are bounded transport controls, not durable business guarantees.

The webhook body often contains customer messages. Keep Hermes and n8n on private networks or a controlled encrypted overlay. Prefer a local OpenAI-compatible model base URL for Hermes when the content must stay inside your approved boundary; see local endpoints from n8n. HMAC authenticates the sender, not the people who authored business fields inside the payload.

What returns, and who sends

The surface determines who receives the result.

A. Webhook event with Hermes-managed delivery

The route runs the agent and sends its response to the configured Hermes delivery target. n8n receives an adapter status, not the agent’s structured answer. Use this when a Slack, Telegram, GitHub, email, or other documented target is the destination and no later n8n step needs the content.

B. API result returned to n8n

Call POST http://127.0.0.1:8642/v1/responses with Authorization: Bearer <API_SERVER_KEY> when n8n must receive the answer. Use /v1/runs when the agent step should be submitted and observed as a run rather than held as one synchronous HTTP request. The API defaults to loopback, and its bearer key is required even there.

{
  "model": "hermes-agent",
  "input": "Classify severity and draft a reply. Return the agreed JSON fields."
}

After the call, n8n validates the response schema, attaches it to the durable application key, and opens the human gate. A five-minute Idempotency-Key response cache on the Hermes API can make immediate retries safer. It does not replace n8n’s durable claim, uniqueness constraint, or business-state transition.

Failure modes

FailureMitigation
Hermes API or webhook downRetry only under the durable n8n key; park the item in awaiting_agent; alert the owner
API bearer rejectedFix the profile-specific key or routing; never bypass authentication
Webhook signature mismatchFix the secret, timestamp, or exact-byte encoding; never switch to INSECURE_NO_AUTH on a network bind
Oversized webhook payloadStore the document and pass an authorised reference; preserve required context and record truncation
Duplicate webhook deliveryReuse the same X-Request-ID for the same retry within the one-hour cache and keep the durable key in n8n
Duplicate API requestReuse Idempotency-Key only for an immediate retry within its five-minute cache and keep the durable key in n8n
Agent over-actsSandbox the runtime; narrow tools and prompt fields; require approvals for destructive or outbound actions
Gateway environment driftCheck the gateway profile and service environment rather than assuming an interactive shell proves runtime configuration

Use Hermes MCP only when Hermes genuinely needs to inspect or operate an n8n surface. An HTTP API call or event webhook is simpler when that is the actual contract.

Example: support form → Hermes API → human gate

Illustrative happy path, with no deployment or performance claim:

  1. Website form POSTs to n8n webhook /support-intake.
  2. n8n validates email, message length, and source enum, then claims ticket-<uuid> durably.
  3. n8n redacts fields if policy requires and builds the bounded task.
  4. HTTP Request calls Hermes /v1/responses on port 8642 with the bearer credential and a short-lived Idempotency-Key.
  5. Hermes returns the agent result to n8n.
  6. n8n validates the required fields and stores the draft under the durable ticket key.
  7. An approver accepts or rejects the stored draft.
  8. Only an accepted draft reaches n8n’s email or CRM connector.

Hermes should not receive send-capable tools for this path. The prompt can state “do not send,” but capability removal and n8n’s gated connector are the controls that hold if untrusted content tries to redirect the agent.

For an internal Slack summary that does not return to n8n, use the webhook surface instead: configure deliver: slack, sign the event, send a stable X-Request-ID, and treat the adapter response only as delivery status.

Signing and clock skew

For the webhook path:

  • Serialise JSON once, sign those exact bytes, and send those exact bytes.
  • Keep n8n and Hermes clocks synchronized; an otherwise valid V2 signature outside the 300-second window is rejected.
  • Current first-party docs do not define simultaneous current and previous webhook secrets. Use a controlled cutover or a documented rotation procedure for your deployed version.
  • Log signature failures with route name and a non-secret correlation identifier. Never log the secret.

If n8n runs in Docker and Hermes runs on the host, use a stable address routable from the n8n process network namespace. localhost refers to different namespaces in that topology.

Custom callbacks are a separate integration

Current Hermes webhook documentation does not list a generic HTTP callback delivery target. If your deployment adds one through custom code or a tool, describe it as a separate integration and give it its own fixed destination allowlist, authentication, schema validation, SSRF boundary, durable idempotency, and acceptance tests. Do not imply that a callback field in the incoming webhook body activates a built-in Hermes feature.

Decision cheat sheet

QuestionPrefer
Is the step a fixed integration sequence?n8n only
Does n8n need the agent’s returned content?Hermes API on :8642
Should Hermes process an event and deliver elsewhere?Hermes webhook on :8644
Must outbound email stay behind one approval queue?API result → n8n validation → human gate → n8n send
Is the user already in a supported Hermes chat channel?Consider direct Hermes channel interaction instead of an n8n round trip

Minimal build order

For an API result path:

  1. Enable the API server on loopback or a private interface and set API_SERVER_KEY.
  2. Verify authenticated /v1/models and one toy /v1/responses call from the n8n runtime network.
  3. Add response-schema validation and a durable n8n application key.
  4. Add the human gate before any customer-visible connector.
  5. Test retries inside and outside the five-minute API cache.

For an event webhook path:

  1. Enable the webhook adapter and configure one route, secret, narrow prompt, scoped capabilities, and delivery target.
  2. Verify /health and one V2-signed toy event from the n8n runtime network.
  3. Send a stable X-Request-ID and inspect delivered versus duplicate adapter statuses.
  4. Replace the toy trigger with the real validated event and durable n8n key.
  5. Test rate, body-size, signature, clock, delivery, and stopped-service failures.

Acceptance tests before production traffic

For the API surface, retain evidence that a missing or wrong bearer key is rejected; a toy request returns the expected schema; immediate retry with the same Idempotency-Key does not create a second agent execution; retry after the five-minute cache is still blocked or reconciled by the durable application key; Hermes stopped causes a visible parked state; and a rejected draft never reaches a send connector.

For the webhook surface, retain evidence that an unsigned request, an altered signed body, and a timestamp outside the 300-second window are rejected. Confirm a signed toy event reaches the configured delivery target. Repeat it with the same X-Request-ID inside one hour and verify a duplicate status with no second agent run or delivery. Then confirm that rate-limit, oversized-body, unavailable-target, and stopped-Hermes failures are visible to n8n.

The integration is ready for a pilot only when the relevant surface passes its acceptance tests and ownership is explicit. Bearer authentication and HMAC establish caller identity only within their documented contracts. The five-minute API cache and one-hour webhook delivery-ID cache are bounded retry aids. Durable application idempotency, authorisation, approval state, and business recovery remain n8n or business-system responsibilities.

Read next

Continue through the same learning path with the next practical articles.