Approval Gate Design: The Decision That Made Our Agent Safe
Approval Gate Design: The Decision That Made Our Agent Safe
Early in building the ABT content pipeline, our agent could publish directly. One command, content live. Fast. Clean. And exactly the kind of design that keeps me up at night when I see it in enterprise systems.
The approval gate we added — a single architectural decision — is the thing that made the whole pipeline trustworthy. Not smarter prompts. Not better guardrails on the LLM output. A hard stop between generation and action. That decision is worth unpacking, because it applies to almost every AI agent architecture I’ve seen teams build, and most of them skip it.
What We Built and Why It Needed a Gate
The content pipeline works like this: a Telegram command triggers the agent, the agent pulls a topic, drafts a post using the Content Writer system prompt, commits the draft to GitHub with published: false, and notifies me for review. Simple enough.
The original version had a /publish command that would flip the frontmatter field, push the change, and deploy. The agent had write access to the repo and the ability to trigger the deployment workflow. No intermediate state. No confirmation step.
That design passed a quick mental test: the agent is only publishing content I asked it to draft. What’s the risk?
Twenty-five years of watching systems fail taught me that question is always wrong. The right question is: what happens when the agent does exactly what it’s designed to do at exactly the wrong moment, in the wrong context, with subtly wrong inputs?
The answer, in our case: a post goes live that I haven’t reviewed, potentially with fabricated stats or content that just isn’t ready. The agent doesn’t know what I know. It executes.
That’s the gap the approval gate closes.
How the Approval Gate Actually Works
The implementation is straightforward. The agent operates in two distinct phases with a human checkpoint between them:
Phase 1 — Generate and Stage
The agent drafts content, commits it to the repository with published: false hardcoded in the frontmatter, and sends me a Telegram notification with a summary and a review link. The agent’s job ends here. It has no further authority over this content.
Phase 2 — Review and Release
I read the draft. If it’s ready, I issue a /publish [slug] command. The agent validates the slug exists, confirms published: false is still set (a sanity check against race conditions or manual edits), flips the field, commits the change with a clear message, and triggers the deployment workflow. If I don’t send that command, nothing happens. The draft sits indefinitely.
The critical detail: the agent cannot initiate Phase 2 on its own. There is no timeout, no retry, no fallback path that bypasses the human step. Automation that can self-approve is not an approval gate — it’s a delay.
The Security Pattern Behind the Decision
In IAM, we call this separation of duties. The entity that creates a resource should not be the entity that approves or activates it. You see it in change management workflows, in financial transaction controls, in privileged access governance. It is one of the oldest and most reliable controls in the security playbook.
AI agents violate this pattern constantly, because the people building them are optimizing for speed and autonomy. The agent drafts and publishes. The agent generates and executes. The agent flags and remediates. Each of those collapses a control boundary that exists for a reason.
The moment an agent can complete a consequential action without human confirmation, you have a single point of failure dressed up as a feature. A misbehaving agent, a poisoned prompt, a malformed input, a context window that dropped a critical constraint — any of these can push the agent across the line. If there’s no gate, there’s no recovery point.
For content, the blast radius is limited. An accidental publish is embarrassing and fixable. But the same architectural pattern — agent generates, agent executes, no gate — applied to infrastructure changes, access grants, financial transactions, or customer communications is a different problem entirely.
The habit of building gates should form at low stakes. It transfers directly to high stakes.
What the Gate Caught in Practice
In the first two months of running this pipeline, the approval gate stopped two things that would have been problems:
1. A stat I couldn’t verify. The draft cited a specific percentage from what the agent apparently hallucinated as an industry report. Marked [CITATION NEEDED] per our guidelines, but it was buried in paragraph four. Without the review step, that number would have shipped as fact.
2. A timing conflict. I’d already manually published something that morning on a related topic. The agent’s draft would have created a same-day duplicate post that signals low editorial quality to both readers and search engines. The gate gave me visibility before that happened.
None of these are catastrophic. All of them are exactly the kind of thing an automated system cannot evaluate without human context. The gate is where that context gets applied.
Building the Gate: Technical Notes
The /publish command handler does the following in sequence:
- Accepts a slug as input
- Fetches the file from the repository via GitHub API
- Parses the frontmatter to confirm
published: false - If confirmed, patches the field to
published: true - Commits with message:
publish: [slug] via /publish command - Triggers the deployment workflow
- Returns a confirmation to Telegram with the live URL
If step 3 fails — meaning the file already has published: true or the slug doesn’t exist — the command errors out and tells me why. No silent failures.
The published: false default is enforced in the Content Writer system prompt itself. Not just as a guideline — the instruction is explicit: “Never set published: true in output.” That makes it a two-layer control: the prompt constrains the agent, and the validation step in the publish handler catches anything that slips through.
Defense in depth applies to agent pipelines exactly as it applies to network architecture.
Key Takeaways
Approval gate design is a security control, not a convenience toggle. The decision to require human confirmation before consequential action is the same decision that underlies separation of duties, change management workflows, and privileged access governance. Apply it to AI agents.
Automation that can self-approve is not a gate. If the agent can bypass the checkpoint under any condition — timeout, retry, fallback path — you do not have an approval gate. You have a delay.
The gate catches what the prompt can’t. Business-layer rules, timing conflicts, unverifiable claims, context that exists outside the agent’s window — these are human-review problems, not prompt-engineering problems. Design for that.
Build the habit at low stakes. A content pipeline is a forgiving place to learn that gates matter. Infrastructure automation is not. The pattern transfers. Start now.
Default to published: false at the generation layer, enforce it at the execution layer. Two checkpoints on the same constraint is not redundant. It’s defense in depth.
The approval gate wasn’t the most technically interesting decision we made building this pipeline. It was a deliberate friction point added to a system that could have run faster without it. That friction is the point. Speed without a checkpoint is just a faster way to make a mistake at scale.
Comments