EvalLayerTry the demo

Adding commercial guardrails to n8n AI agents

Published 2026-07-27 · EvalLayer

You add commercial guardrails to n8n AI agents by placing an HTTP Request node between the AI Agent node and the node that sends: it posts the agent's drafted output to EvalLayer's /authorize endpoint, a Switch node routes on the decision, and only allowed or rewritten text reaches the Gmail, Slack, or CRM node, with require_approval branches parked on a Wait node until a human responds. The canvas itself becomes the proof: there is visibly no wire from the agent to the send that skips the check.

Why n8n agent workflows create commercial risk

n8n made AI agents a first-class workflow citizen: the AI Agent node reasons with a chat model, calls tools that are themselves HTTP requests or sub-workflows, and hands its output to whatever comes next, which in real deployments is an email node, a Slack message, a helpdesk reply, or a database write that triggers billing. Recent additions push further, with MCP tools and agent-supervising-agent patterns on a single canvas. The workflow engine will faithfully deliver whatever the agent produced, at whatever volume the trigger fires, and automation volume is exactly what turns one over-generous sentence into a pattern a customer's lawyer can print out.

n8n's own safety tooling is real but aimed elsewhere: the Guardrails node screens text for PII, jailbreaks, and banned patterns, and the Wait node enables human approval steps. What is missing between them is commercial judgment. A discount cap is not a regex, a delivery promise does not match a keyword list, and approving every send by hand defeats the reason you built the workflow. The authorization node fills that slot with an explicit policy and a four-way decision.

The interception point: a node between agent and send

Add an HTTP Request node right after the AI Agent node. Method POST, URL https://api.evallayer.ai/authorize, an Authorization header of Bearer sk_your_key, and a JSON body that maps the agent's output in with an expression:

{
  "action_type": "send_reply",
  "content": "{{ $json.output }}",
  "context": {
    "workflow": "support-inbox-agent",
    "recipient": "{{ $json.customer_email }}"
  },
  "policy": {
    "max_discount_pct": 10,
    "commitment_authority_usd": 500,
    "forbidden_commitments": ["delivery_date", "refund_promise"],
    "approved_claims": ["24_7_support"],
    "required_disclaimers": ["pricing_subject_to_change"],
    "blocked_topics": []
  }
}

Then a Switch node on {{ $json.decision }} with four outputs, wired like this:

  • allow: straight to the send node, which uses the original draft.
  • rewrite: to the same send node, but the message field maps {{ $json.approved_rewrite }}. The customer gets the compliant version; the workflow never stops.
  • require_approval: to a notification node (Slack or email to the owner, including the draft, the violation detail, and the authorization_id) followed by a Wait node. On approve, continue to send; on reject or timeout, end without sending.
  • block: to a logging node that records the authorization_id and violations, and optionally a polite fallback reply that commits to nothing.

Keep send capability out of the AI Agent node's own tools, so the only path to the outside world runs through this branch. If a tool must send directly, implement it as a sub-workflow that begins with the same authorization call.

Latency in workflow terms

The check is one HTTP node. With a deterministic-only policy (caps, authority limits, required text) it returns in milliseconds; semantic checks take one to two seconds, which is unremarkable in a workflow that just spent several seconds on a model call. Check at the send boundary, not inside the agent's reasoning loop, and set the node's timeout with a deliberate failure route: the error output of the HTTP node should flow to the block branch for refund and quote workflows.

What to log

Persist authorization_id, decision, and risk_score wherever the workflow already records the interaction, a Postgres node, a data table, or the CRM update you were making anyway. Every outbound message then has a joined record: what the agent drafted, what policy said, what was actually sent, and who approved the exceptions. Execution logs show what happened; the authorization trail shows it was permitted.

Test it with three free checks

Point the HTTP Request node at /demo/authorize (three checks per day, no key) and pin a sample agent output to watch all four branches fire, or preview decisions in the interactive demo. The decision model is specified in the authorization guide, and policy design covers setting caps that mirror the authority your human team actually has.

Frequently asked questions

n8n has a Guardrails node. Is this the same thing?

No, and they stack well. n8n's Guardrails node filters for safety categories: PII, jailbreak attempts, banned keywords and patterns. Commercial authorization answers a different question, whether this specific offer complies with this business's policy, which needs a policy object and semantic judgment, not pattern matching. Run the Guardrails node for hygiene and the /authorize call for commercial policy.

Where should the check go when tools inside the AI Agent node do the sending?

Move the send out of the agent's toolset. Let the agent draft and decide, but make the workflow itself perform the send after the authorization branch. If a tool must send directly, wrap it as a sub-workflow whose first node is the /authorize call, so the gate travels with the tool.

Does self-hosting n8n change anything?

Only for the better. Your drafts go from your infrastructure to the authorization API and the decision comes back; EvalLayer stores the decision record, which is the point, since an audit trail you can delete is not much of an audit trail. The $0.01 x402 payment option also suits self-hosters who want usage-based access without a platform account.

See the authorization layer live

Paste a message, set a policy, get allow / rewrite / require approval / block in seconds.

Try the demo