How I built a 4-tier approval gate for my AI companion: a heuristic that can never say no
Description and use
Implemented a four‑tier approval gate for the Ankita desktop companion to prevent silent actions, especially in Gmail, and provide audit trails for all decisions.
Problem
The original approval system allowed trusted servers to bypass prompts, letting Gmail send mail without user confirmation.
Outcome
The new gate prevents silent approvals, ensures every tier downgrade is reviewed, and provides an audit trail for all decisions.
Workflow
- 1. Replace binary rule with mcp‑tiers.mjs defining four tiers.
- 2. Resolve tier via blocklist → per‑tool rule → per‑app rule → app defaults → heuristic.
- 3. Implement lowersProtection() to flag tier downgrades as approval‑worthy.
- 4. Parse meta‑tool arguments in enclosedActions() to determine worst enclosed tier.
- 5. Record decisions with recordDecision() for audit trail.
- 6. Store pending approvals in ApprovalRegistry for UI visibility.
- 7. Run comprehensive tests (14/14) to validate tier resolution logic.
Evidence
The old rule was binary: a tool marked readOnlyHint: true skipped the gate, everything else asked — and a trusted server skipped the gate entirely.
Tier 0 — auto-allow: read-only tools. Tier 1 — ask once. Tier 2 — always ask for destructive verbs. Tier 3 — deny only via blocklist.
The heuristic can never silently deny. It can escalate a prompt, never issue a refusal.
Every decision goes through recordDecision(), which keeps per-server counters of allowed / asked / denied.
- Record date: 2026-10-11T11:56:04.279Z