There's a quiet pattern most teams have slipped into without naming it. You ask an AI coding tool for a command. It gives you one. You run it. It throws an error. You paste the error back, it corrects itself, you run it again. Three or four rounds later it works, and you move on.
It feels productive. It isn't, quite — and the reason is the part nobody notices: the error message is doing your thinking for you.
The CLI is acting as a free verifier, but it only checks a narrow band — syntax, whether a resource exists, whether a permission is spelled correctly. It says nothing about whether the design is correct, whether it follows least privilege, whether it's the idiomatic pattern, or what it costs. So without realizing it, you've set your quality bar to does not throw — the lowest bar there is.
Here's the trap in one sentence: a command that succeeds feels like a command that's correct, and those are different claims. When something goes red, you scrutinize it. When it goes green, you don't. The dangerous output isn't the one that errors — that one you catch. It's the one that runs cleanly and is quietly wrong: the over-broad role, the public bucket, the unpinned image. That output passes every test and fails the audit.
In a regulated environment, that last line isn't a turn of phrase — it's a finding. Over-provisioned IAM that "works" is exactly the class of thing that survives every check in the build and then surfaces in the post-incident review, the access recertification, or the examiner's sample. The error caught the typo. Nothing caught the design.
And the IAM grant is the visible version, because it leaves a trace in a policy file. The same failure mode lives one layer up, where it's harder to see: a Claude-drafted discharge summary that reads perfectly and quietly contradicts the chart; a contract abstraction that's fluent and misses the carve-out; a model-risk memo that cites a control that isn't actually in place. Fluent and wrong clears every spell-check and fails the only review that matters. Whether the output is a shell command or a clinical paragraph, "it ran" was never the same claim as "it's right."
A real task: grant a developer group access to BigQuery and Google's hosted MCP tooling, role-based, least privilege. Watch the same request run two ways. (The commands are illustrative and lightly edited for length.)
$ gcloud iam roles create AgenticDev --project=$PID \
--permissions="bigquery.jobs.create,run.developer,..."
ERROR: Permission run.developer is not valid. # run.developer is a ROLE, not a permission
Paste the error back. It corrects. Run again.
ERROR: Permission mcp.tools.call is not supported in custom roles.
Paste the error back. It corrects — drop the permission, use the predefined role. Run again.
$ gcloud projects add-iam-policy-binding $PID \
--member="group:agent-developers@yourdomain.com" --role="..."
ERROR: Group agent-developers@yourdomain.com does not exist.
The placeholder yourdomain.com was never substituted, and the group was never created. Three rounds in, you fix both, and it finally works.
But look at what also shipped in that session, with no error at all:
$ gcloud projects add-iam-policy-binding $PID \
--member="group:..." --role="roles/iap.egressor" # "for agent-to-agent comms"
# runs clean. green. done.
That binding executed perfectly. It's also conceptually wrong — IAP egressor governs reaching IAP-secured endpoints, not "agents talking to each other," which is an open HTTP protocol with no IAM surface of its own. It's an unjustified, over-broad grant. Nothing went red, so nobody questioned it. That's the failure that matters, and the error-driven loop is structurally blind to it.
[GROUND] reading current state before generating…
account: dev-lead@acme.com project: acme-agents-prod
checking group exists… ✗ agent-developers@acme.com NOT FOUND
→ halting: will not emit a binding to a non-existent principal.
Create the group first, or confirm the correct address.
No placeholder reaches your terminal, because the tool read the world instead of assuming it. Once the group exists:
[GENERATE] proposed: custom role (BigQuery + Cloud Run perms)
+ predefined roles/mcp.toolUser + roles/bigquery.dataViewer
[CRITIQUE] architect review:
✓ two-gate MCP pattern is idiomatic
⚠ NO justification found for roles/iap.egressor — over-broad, removing
✓ custom role scoped to least privilege
[VERIFY] deterministic gate: dry-run binding against IAM Policy Simulator… PASS
[COST] IAM bindings incur no charge — N/A
[GATE] 2 bindings ready to apply. Approve? (y/n)
Same task. The first pass is correct, the silent over-broad grant is caught and removed before it's ever applied, and you're shown exactly what's about to change before you say yes.
Five things, and none of them is "a smarter model." They're an architecture around the model:
The whole thing runs on a local install — no IDE, no internal developer platform. The grounding step is a read-only shell call. The critic is a sub-agent with its own context and rubric. The gate is a pre-execution hook that exits non-zero to block. The router is a few lines of standing instruction plus a skill keyed on the task signature. The lightweight, instruction-only version captures much of the value in an afternoon; the deterministic gates are where you spend the next day or two, and they're the part worth spending it on.
Resist the urge to measure only the average. The obvious win — fewer rounds to a working command — is real, but it's the small one. The win that matters is the variance collapsing: a pipeline whose worst case is bounded is worth more than one whose average is good and whose tail occasionally ships roles/owner to a developer group. So when you evaluate this, report the 95th-percentile outcome next to the mean, and measure the silent-defect rate — the fraction of outputs that run clean and are still wrong. That number is invisible to the tool itself, and bringing it down is the entire point.
"It ran" was never the same thing as "it's right." The fix isn't a better model — it's giving the model a world to read before it speaks, and a gate it cannot talk its way past. That is the difference between a deployment that demos well and one your risk, security, and compliance teams will actually let run.
We run this pattern ourselves. The assistant on this page answers only from an approved knowledge base, behind a gate, and routes anything consequential to a person — the same grounded-and-gated shape, pointed at a different problem.
This is the control layer we build around Claude for regulated teams — grounded, gated, and measured, so the same discipline that protects a deployment also produces the evidence your auditors accept. If "it passes every test and fails the audit" sounds familiar, that's the gap we close.