Human-In-The-Loop Ai Gates: Dual Control for Prod-Touching Agent Tools

Human-in-the-Loop Gates: Dual Control for Prod-Touching Agent Tools
10 views

This guide covers human-in-the-loop AI gates with production-focused examples and trade-offs.

A single engineer approving their own agent’s prod.dynamodb.DeleteItem is not a control — it is theater. Dual control means two distinct humans, a change ID, and an explicit blast radius before any prod-touching tool returns credentials or executes. Accountability stays human; the agent only proposes.
⚡ TL;DR: Classify tools read / write-nonprod / write-prod. write-prod requires Slack dual-ack from different users + Change Management ID + TTL’d capability token. Log every decision. Pair with Agent Tool Allowlists and Step Functions multi-agent approval gates.

Tool risk classes — human-in-the-loop AI gates

typescript
// policy/tool-class.ts
export type ToolClass = "read" | "write_nonprod" | "write_prod";

export const TOOLS: Record<string, ToolClass> = {
  "repo.search": "read",
  "db.query.staging": "read",
  "db.mutate.staging": "write_nonprod",
  "db.mutate.prod": "write_prod",
  "iam.putRolePolicy": "write_prod",
};
typescript
// gate/dual-control.ts
export type Approval = {
  changeId: string;          // CHG######
  blastRadius: string;       // free text, required min length
  approverA: string;
  approverB: string;
  expiresAt: number;         // epoch ms
};

export function assertDual(a: Approval) {
  if (a.approverA === a.approverB) throw new Error("same_human");
  if (!/^CHG\d{6,}$/.test(a.changeId)) throw new Error("bad_change_id");
  if (a.blastRadius.trim().length < 40) throw new Error("blast_radius_too_thin");
  if (Date.now() > a.expiresAt) throw new Error("approval_expired");
}
❌ Single emoji reaction from the requester as “approval.”

Slack dual-ack flow

text
1. Agent requests write_prod tool with plan + blast radius draft
2. Bot posts message to #agent-prod-gates with buttons Approve/Deny
3. Approver A (not requester) Approve
4. Approver B (not A, not requester) Approve
5. Gate mints TTL capability token (5–15 min) bound to tool+args hash
6. Agent invokes tool with token; executor verifies signature + expiry
python
# executor/verify_token.py
def verify(token: str, tool: str, args_hash: str) -> None:
    payload = jwt.decode(token, PUB, algorithms=["RS256"])
    assert payload["tool"] == tool
    assert payload["args_hash"] == args_hash
    assert payload["class"] == "write_prod"
    # ✅ requester not in approver set
    assert payload["requester"] not in payload["approvers"]

Blast radius template agents must fill

Field Example
Target prod payments table pk=order#*
Rows estimate < 20
Reversible yes — PITR restore
Customers segment: canary-eu
Rollback replay undo stream
Same interruptibility as Secure AI Sandboxes on ECS — short-lived creds, no standing prod roles for agents.

Closing checklist

✅ Dos – ✅ Classify every tool; default deny prod writes – ✅ Dual distinct humans + change ID + blast radius – ✅ TTL capability tokens bound to args hash – ✅ Audit log requester, approvers, tool, args hash – ✅ Expire unused approvals automatically ❌ Don’ts – ❌ Don’t accept self-approval – ❌ Don’t reuse tokens across tools – ❌ Don’t grant standing prod IAM to the agent role – ❌ Don’t allow empty blast radius – ❌ Don’t skip deny-path testing in staging

Related reading

Last updated on September 11, 2026

Related: Day 54: Specialist Tools per Agent · Day 17: Human-in-the-Loop Gates That Don't Stall · Cursor Agent Mode: Multi-File Refactors That Survive CI Gates

Watch: 100 Days of AI on YouTube

Short videos from CheatCoders, one AI engineering topic per day.

Open the playlist on YouTube · CheatCoders on YouTube

Deep-dive PDF

Get the expanded guide for this post — extra diagrams-style checklists, failure modes, and a production walkthrough. Free when you subscribe to CheatCoders.

Already subscribed? or open the subscribe page.


Discover more from CheatCoders

Subscribe to get the latest posts sent to your email.

Comments

No comments yet. Why don’t you start the discussion?

Leave a comment

No account needed. Name and email are optional.