DEV Community

Robert Breen
Robert Breen

Posted on Originally published at learn.ynteractive.com

n8n: Guard Rails for an AI Agent That Touches Client Data (Draft Alone, Send Only With a Yes)

Disclosure: Guardian is a third-party product from guardian-safety-gate.com. I built a free lesson around it in my own account. There is no affiliate link and Guardian doesn't pay me. This is not an official Guardian course.

Here's the moment that keeps small-office owners from letting an AI agent loose on client work. The agent reads the overdue invoices sheet, drafts a reminder for each client, and sends one with the wrong amount. You can't unsend an email.

So what happens in practice is that the owner checks every single draft by hand, and the automation saves a lot less time than it promised.

I think the better answer is a rule the workflow can't skip. Let the agent read, sort and draft on its own. Make anything that goes to a customer wait for a person. Never let it delete anything.

Price the checking first

In my lesson the example is Maya Chen, who runs a made-up firm called Harbor Line Bookkeeping. Her n8n agent drafts about 60 reminder emails a month. She checks each one for about 3 minutes. That's roughly 3 hours a month of reading drafts that are almost always fine.

These are example numbers, so use your own. The point is that you don't want to stop checking the risky ones. You want to stop checking the safe ones.

The three lines most offices already agree on

When I ask owners where the line is, they usually say the same thing:

  1. Team emails can go out on their own.
  2. Client emails wait for a person to approve.
  3. Deletes are never allowed.

Guardian turns those three lines into policy. It sits in front of the step that can't be undone, and answers Allowed, Needs approval or Denied before your workflow acts. It doesn't send anything itself. Your n8n workflow still does the sending, and only its approved paths should reach the send step.

Step 1: a policy for email.send

In Guardian, open Policies, click New Policy and choose Manual (Build rules from scratch). (The AI Wizard needs a paid plan.)

  • Name it Customer emails need approval.
  • Under What action does this policy apply to? type email.send. Guardian uses lowercase dot notation, and your workflow will send the same action type before every email.
  • Under Apply to Projects, tick Default. Guardian won't save a policy without a project.

Step 2: allow only your own addresses

Under Rules, pick Only allow specific values. Listed values are allowed automatically, and anything else needs a human.

  • What should Guardian check? recipient. This must match the field name your workflow sends, exactly.
  • List your team inboxes, such as team@ and billing@ on your own domain.
  • If the value is not in this list, then: Require Approval, with a reason like Emails to customers wait for a person to approve.
  • Approvals Required: 1.

The This rule will box reads it back to you: allow when recipient is a team address, require approval for anything else.

Step 3: the payload your workflow sends

This is the part people get wrong, so I'll be concrete. The Guardian node in n8n takes an Action Type and a Payload. The payload's field names must be the same names the policy checks.

For this policy, the payload is a small JSON object:

{
  "recipient": "dana@brightpathdental.example",
  "subject": "Invoice 1042 is 14 days past due",
  "body": "Hi Dana, a quick reminder that invoice 1042 for $1,280.00 was due on October 6..."
}
Enter fullscreen mode Exit fullscreen mode

If your agent's output uses different names (say to and message), I'd normalize them in a Code node right before the Guardian node, so the policy only ever sees one shape:

// Code node, "Run Once for Each Item": build the payload Guardian checks
const draft = $json;

const recipient = String(draft.to || draft.recipient || '').trim().toLowerCase();
if (!recipient.includes('@')) {
  throw new Error(`No valid recipient on draft: ${JSON.stringify(draft)}`);
}

return {
  json: {
    recipient,
    subject: String(draft.subject || '').trim(),
    body: String(draft.body || draft.message || '').trim(),
  },
};
Enter fullscreen mode Exit fullscreen mode

I lowercase the address because I don't want to depend on how the comparison treats case. If Billing@YourFirm.com ever failed to match billing@yourfirm.com, a team email would just land in the approval queue. That's safe, but it's noise.

In the Guardian node, set Action Type to email.send and set Payload to that object. If the field takes JSON text, this expression builds it from the Code node's output:

{{ JSON.stringify({ recipient: $json.recipient, subject: $json.subject, body: $json.body }) }}
Enter fullscreen mode Exit fullscreen mode

Step 4: test before you save

Open Test This Policy. Guardian pre-fills a Custom Test Payload from your rules.

  • Run it with a team address: it returns ALLOW.
  • Paste the client payload above: it returns REQUIRE APPROVAL, with your reason underneath.

Both are sandbox tests. No intent is created and nothing is logged. Then click Create.

After saving, the flask icon in the policy list opens Test Policy for the saved version. Guardian's own guide says to run every policy through the tester with the real payload before you rely on it, because a rule whose field name differs from the payload, even by a typo, silently never fires. That one sentence is why I normalize in a Code node.

Step 5: deletes are already denied

You don't write a rule for "never delete." Under Settings > Organization, Default Policy Behavior has Deny unmatched actions selected and marked Recommended. Any action type without an explicit policy is blocked. So if the agent ever asks for record.delete, Guardian answers Denied. Just never write an allow policy for it.

Step 6: wire the three outputs

From Guardian's n8n guide: the Guardian node goes right before the action node, after the step that writes the email. It has three outputs.

[AI Agent drafts] -> [Code: build payload] -> [Guardian: email.send]
                                                 |-- Allowed --------> [Gmail: Send]
                                                 |-- Needs Approval -> [Note / Slack: "waiting"]
                                                 '-- Denied ---------> [Note / Slack: "blocked"]
Enter fullscreen mode Exit fullscreen mode

Connect Allowed to the send. Point Denied and Needs Approval at a note. Never connect all three to the action. I've seen that mistake on a canvas, and it turns the gate into decoration.

The node needs a Guardian API credential: an API key from Guardian's Settings > API Keys (verify your email first), the signing secret and the base URL it asks for.

For the approval path, build a second flow: a Guardian Approval Trigger, then a Guardian node set to Enforce, then the send, reading the approved payload. Keep only one active workflow listening for the same action type, or an approved email can go out twice.

Step 7: approve, or fix it first

Waiting requests land in Guardian's Approval Inbox with the action type and why approval was needed, shown as Blocked, awaiting human approval, with an expiry time.

Edit Payload & Approve shows the original payload next to the approved one, so you can fix a wrong amount before it goes. The original stays in the audit log, and the edited version is checked against your policy again. For client data, that audit trail is half the value.

Mistakes to avoid

  • Connecting all three Guardian outputs to the send.
  • A field name in the rule that doesn't match the payload.
  • Writing an allow policy for deletes.
  • Running a first test against a live send step. Disable the send (select it and press D), or use Listen Mode, which records what Guardian would have decided without blocking.
  • Two active workflows listening for the same action type.
  • Pasting your API key into a chat, a screenshot or a shared workflow.

What it costs

Guardian's site, read October 19, 2026, says it's free to start with no credit card. In the app, the AI Wizard needs a paid plan and Allow unmatched actions is Starter+ only. Check the Pricing page in the app for current plans.

Try it free

The lesson, Guardian: Make Your n8n AI Agent Ask Before It Emails a Customer, walks you through the policy, both tests and the n8n wiring in 33 steps. The Guardian screens are real captures from building this exact policy.

Practice it step by step, free: https://learn.ynteractive.com/content/guardian-n8n-ai-agent-approval-before-sending-email

Top comments (0)