Inspiration
The first time I gave an AI agent full access to a real workspace and watched it start executing commands on its own, I had a small moment of "wait — what if it just... does something I didn't actually want?" Nobody was standing between the agent's decision and the action itself. That gap felt genuinely unsettling once I noticed it, and I couldn't stop thinking about it: these agents are getting real power fast, but the guardrails around that power are still an afterthought.
I wanted to build the thing that was missing — a checkpoint that actually stops and asks "are you sure?" before something destructive happens, and keeps a record afterward so nothing is invisible. Building it solo meant I got to be my own adversary too: I spent real hours trying to trick my own system into letting something slip through, and every time I found a bypass, it was a genuine "oh no" moment followed by "okay, now I actually understand this problem better." That process — building something, then trying honestly to break it — ended up teaching me more than building it cleanly ever would have.
What it does
Approval Gate is a middleware layer for the Agent Launchpad platform that:
- Inspects every prompt sent to an agent for risky patterns (destructive commands, secrets access, database drops) before execution
- Holds risky actions for human approval or denial, recording the operator's name
- Watches the agent's actual shell commands in real time as a second line of defense, terminating the process mid-execution if something dangerous slips through the first check
- Records every decision as a structured, redacted audit trail — policy decisions, human approvals, tool calls, and model usage — viewable per-agent in a live Audit Log
- Enforces ownership isolation so one user's agents are completely invisible and inaccessible to another user, verified at the API level
How we built it
We extended the starter kit's AgentService with a risk-check step before every run, using pattern matching against known-destructive commands. We then went further and hooked into the Codex CLI's event stream inside the Runtime layer to monitor actual shell commands as they execute, sending a termination signal if a risky command is detected mid-run. Every decision point — policy checks, human approvals, tool calls, model calls — is captured as a structured "span" attached to the run, with a redaction pass scrubbing anything that looks like a secret before storage. We added a lightweight ownership model on top, tagging every agent with an owner and enforcing that server-side across every state-changing endpoint.
Challenges we ran into
Our biggest challenge was discovering that keyword-based detection is fundamentally incomplete. We built a denylist starting with "rm -rf," then through actual adversarial testing found the agent could accomplish the same destructive outcome via at least three other techniques: find -delete, unlink, and a shell truncation idiom (: > file). Each fix closed one path while leaving the underlying bypass capability intact — a genuinely humbling, real finding rather than a hypothetical one.
We also discovered a timing race in our mid-execution kill-switch: SIGTERM isn't instantaneous, so a very fast single-file operation could sometimes complete before our signal landed, while slower or multi-step commands were reliably interrupted. This shaped our final design as two deliberate layers rather than one.
Accomplishments that we're proud of
We didn't just build a feature and assume it worked — we adversarially tested our own system and found real bypasses, then honestly documented them instead of hiding them. We also verified our ownership isolation isn't just a UI illusion: we confirmed a direct API call from an unauthorized user is genuinely rejected with a 403 at the server level. Every piece — the approval gate, the kill-switch, the audit trail, the ownership check — is backed by both a live demo and automated tests.
What we learned
Denylist-based security is inherently reactive — every pattern you block is a hint about what you haven't blocked yet. A more robust production system would need either an allowlist (deny by default, approve known-safe operations) or outcome-based monitoring (did something unexpected change?), rather than an ever-growing list of forbidden commands. We also learned that defense-in-depth isn't just a buzzword — our two independent layers each covered gaps the other one had.
What's next for Approval Gate: Middleware for Agentic AI Platforms
Migrating from codex exec to codex app-server mode to support true pause-and-resume approval (rather than kill-and-restart) mid-execution. Moving from keyword-based detection toward an allowlist model or outcome-based file-integrity monitoring. Extending the ownership model into real authentication rather than a demo-only named identity.
Built With
- agentic-ai
- byteplus-ark
- codex-cli
- docker
- fastify
- json
- middleware
- node.js
- react
- rest-api
- sandboxing
- typescript
- vitest
- zod
Log in or sign up for Devpost to join the conversation.