Every agent story that ends badly has the same shape: “it was working fine for weeks, and then…” — and then it emailed a client something bizarre, or looped all night, or confidently performed the wrong action because the world changed around it. The agents that don’t end badly are not the smartest ones; they’re the ones with guardrails. This guide is the checklist we run through before any agent gets real responsibilities.
Guardrails are not pessimism about AI. They’re the same engineering we apply to every powerful system: circuit breakers exist because electricity is useful, fuses exist because appliances are useful. The five below cover every agent failure we’ve seen in two years of running them in production.
Guardrail 1: The iteration cap
The agent loop — think, call tool, think again — needs a hard ceiling on how many times it can go around. A confused agent doesn’t stop itself; it gets more determined. We’ve watched a research agent loop 40+ times on an unreachable URL, certain the next fetch would work.
Setting it: every agent framework has this (n8n’s AI Agent node: max iterations; Make’s agent module: cycle limits). Our defaults: 6-8 iterations for research agents, 3-4 for action agents. If a legitimate task genuinely needs more, that’s a signal to decompose the task, not raise the cap.
When it triggers: the run should fail loudly — error notification to you, with the last few steps of context, not a quiet partial completion. A cap that triggers silently just moves the failure downstream.
Guardrail 2: Rate and spending limits
Three layers, from outside in:
- Provider-side caps — a monthly spending limit on your model API account, so a runaway loop has a ceiling defined by math, not by your next invoice review. Set this the day you create the account.
- Per-run token budgets — most agent nodes let you cap tokens per run; set generously above your observed normal (we use 2-3x median) so legitimate work never bounces but pathological runs die young.
- Per-tool rate limits — especially for tools with external blast radius: “max 10 emails per run,” “max 100 API calls per day.” A confused agent hammering a vendor’s API doesn’t just cost you money; it can get your keys revoked.
The pattern to notice: each layer assumes the inner layer might fail. That’s not distrust of the model specifically — it’s how every reliable system is built, all the way down.
Guardrail 3: The approval gate on irreversible actions
From our tools guide: agents should start read-only, earn reversible writes, and face a human approval gate on anything irreversible — outbound emails, payments, deletions, publishing.
The practical implementation is simpler than it sounds: the agent completes its work up to the irreversible action and parks it. Draft email sitting in a queue. Invoice marked “ready to send.” A Slack message to you: “Draft ready — approve?” with the content and a one-tap link.
The cost is a minute of your day. The benefit is that every irreversible thing your agent ever does carries your explicit signature — which, if something goes wrong, is also the difference between “the automation failed” (your fault, containable) and “the AI did it” (unfalsifiable, and the kind of story clients tell other clients).
Wiring the approval gate in n8n
The concrete version, since “park it and ask” is easier said than wired. The pattern is a split into two branches at the irreversible step, with the action branch gated on a database flag:
-
The park. The agent finishes its work and writes the draft (email content, invoice update, post text) to an
approvalstable:id, agent_run_id, type, payload (JSON), status ('pending'), created_at. A single Postgres node — the draft is now data, not an in-flight workflow. -
The ask. A Slack node posts to your approvals channel (or DM): the draft content in a code block, what it’s for, and a message like
Approval #A-1042 pending — reply in thread with "approved" or "rejected". Keep the ID visible; the reply is what closes the loop. -
The release. A second, tiny workflow: Slack trigger on a reply in the approvals channel → if the reply matches “approved” for a given ID → update the row to
status='approved'→ execute the parked action from the stored payload. Rejected → markstatus='rejected', no action. The second workflow is 4 nodes and takes 20 minutes to build once, and it’s reusable for every future approval-gated agent you’ll ever run. -
The expiry (the part people forget). Pending approvals older than 48 hours auto-expire to
status='expired', via a scheduled check. Without this, an unread approval from your vacation quietly becomes a surprise two weeks later, or the queue grows until nobody reviews it. Expiry keeps the gate honest.
In Make, the same pattern maps to a Data Store for the queue and a custom webhook module for the Slack reply trigger. The principle transfers regardless of tool: the irreversible action is never executed by the run that created it — there’s always a separate, human-triggered execution between draft and effect.
A worked example: the client-report agent that earned its send button
The most instructive deployment of these guardrails we’ve run: a services company wanted an agent to draft and send their weekly client reports — assemble the week’s data, write a summary, email each client. The ROI was obvious (about 3 hours a week of account-manager time), and the danger was equally obvious: these emails go to paying clients, in the account manager’s name.
Week 1-2: read-only, earning trust. The agent ran daily, assembling the report data and drafting summaries — but its only output was rows in the approvals sheet. Nobody acted on them; we just read the drafts and compared them against the reports the account manager actually sent. This was the calibration period: two drafts confused two clients with similar names (fixed by putting the client ID in every prompt, not just the name — names are ambiguous, IDs aren’t), and one draft described a “completed” milestone that was actually paused (fixed by adding the project-status field to the input data).
Week 3-4: the gate in practice. We turned on the Slack approval flow: agent drafts → approval message to the account manager → reply “approved” → email sends. First week: 11 approvals, 9 approved as-is, 2 edited (the account manager rewrote one opening line on each — which became prompt guidance: “open with the week’s biggest number, not a greeting”). Average human time: about 40 seconds per approval.
The incident that proved the design. Week 6: a data-source hiccup fed the agent stale numbers, and the drafted report showed last month’s milestones as this week’s. The account manager — reading the draft in Slack, not the client reading an email — caught it in ten seconds, replied “rejected,” and the wrong report never left the building. Without the gate, that’s an email to a client with fabricated progress, followed by the apology tour. With the gate, it was a non-event: fix the data source, regenerate, approve.
Month 4: partial graduation. After 14 weeks and roughly 60 flawless approved sends, the client asked to auto-send the low-risk reports — internal-only copies and one client who “just wants the numbers.” We let the agent auto-send exactly those two, keeping the gate on all client-facing sends. That’s the model working as intended: autonomy expands with demonstrated reliability, per action type — not as a single global switch from “supervised” to “free.”
The whole arc took about six weeks of human attention that totaled maybe three hours, and it ended with an agent that saves the account manager three hours every week with a blast radius of exactly zero. That’s the guardrails earning their keep — not by preventing disasters dramatically, but by making the disasters into non-events and the trust-building visible.
Guardrail 4: The kill switch
When an agent misbehaves at 2pm on a Tuesday, the question is not “how do I fix the prompt” — it’s “how do I stop it right now.” You need, in order:
- A disable switch you can reach in under a minute — know exactly where the toggle is in your tool. Better: a bookmark on your phone labeled “emergency stop.”
- Error notifications that work — the day-one guardrail: an error workflow that pings you when runs fail. An agent that dies silently is worse than one that fails loudly, because you don’t know it’s dead.
- A “what was it doing?” log — recent execution history you can read. n8n’s execution log and Make’s scenario history both give you this; make sure yours is retained long enough to be useful (30 days minimum).
Test your kill switch once, the way you’d test a fire alarm: disable the agent, confirm the scheduled run doesn’t fire, re-enable. The drill takes five minutes and eliminates the “I think I stopped it?” state that turns incidents into adventures.
Guardrail 5: The golden output test
The subtle failure: nothing crashes, the agent keeps producing, but quality drifts — summaries get vaguer, tone wanders, structure loosens. You notice it weeks later when you realize you’ve been skimming the digest instead of reading it.
The fix is boring quality assurance, borrowed from manufacturing: keep a golden output — a known-good result from a week when the agent was excellent — and once a month, run the same input and compare. Drift announces itself immediately in that comparison: vague where it was specific, padded where it was tight.
This guardrail also catches the other quiet killer: model version changes underneath you. Providers update models silently, and an agent that was tuned on last year’s model behavior can shift with nothing changing in your code. The golden test makes the invisible visible.
The pre-production checklist
Before any agent earns real responsibility, we require:
- Iteration cap set (and triggers loud failure)
- Provider spending cap set on the API account
- Per-run token budget at 2-3x observed median
- Rate limits on every external-facing tool
- Approval gate on every irreversible action
- Kill switch located and drill-tested once
- Error notifications confirmed working (deliberately break it once)
- Execution history retained 30+ days
- Golden output saved, monthly comparison on the calendar
- Two weeks of watched behavior on read-only tools before write access
Ten items, an afternoon to set up, and it’s the entire difference between “we run agents in production” and “we tried agents once.” Every story about agents doing something stupid maps to a skipped line on this list — and the embarrassing ones map to several.
The philosophy, in one paragraph
Guardrails are not about limiting what agents can do; they’re about making what they already do trustworthy enough to actually deploy. The uncapped, ungated, unmonitored agent isn’t more capable — it’s the same intelligence with more ways to fail. Every guardrail you add converts a failure mode into a non-event: the loop dies at 8 iterations instead of 40, the weird email waits for your approval instead of sending, the drift gets caught in month one instead of month six. Build agents that are bounded, watched, and reversible, and you get to keep the upsides — the compounding hours saved, the overnight research, the inbox that manages itself — without financing those upsides with eventual disaster. That’s the trade, and it’s a very good one.