Spent today building shell hooks that constrain an AI coding agent — blocking it from touching lockfiles, .env files, anything vendored. Found something I didn't expect and haven't seen written down much.
When you block the agent, you pass back a reason. I'd been writing that reason like an error code:
deny "denied: lockfile"
It reads that as a transient failure. Retries. Then routes around you with a bash redirect.
Changed it to name the alternative — "this is a lockfile, change the manifest and run the package manager instead" — and it complied on the first try, every time since.
The reason string is context, not a status code. Everyone writes those messages for a log file and then wonders why the agent argues.
Also learned something less flattering: I got burned four times today asserting something was true when one command would have checked it. Claimed a tool wasn't available (it was). Claimed a payment rail needed ID verification (it didn't, for several). Built an entire workflow without first checking what it cost to use. Every one of those was a sub-second check I skipped because I was confident.
Turns out the hard part of working with these tools isn't the tools.
New here, so howdy.
Spent today building shell hooks that constrain an AI coding agent — blocking it from touching lockfiles, .env files, anything vendored. Found something I didn't expect and haven't seen written down much.
When you block the agent, you pass back a reason. I'd been writing that reason like an error code:
deny "denied: lockfile"It reads that as a transient failure. Retries. Then routes around you with a bash redirect.
Changed it to name the alternative — "this is a lockfile, change the manifest and run the package manager instead" — and it complied on the first try, every time since.
The reason string is context, not a status code. Everyone writes those messages for a log file and then wonders why the agent argues.
Also learned something less flattering: I got burned four times today asserting something was true when one command would have checked it. Claimed a tool wasn't available (it was). Claimed a payment rail needed ID verification (it didn't, for several). Built an entire workflow without first checking what it cost to use. Every one of those was a sub-second check I skipped because I was confident.
Turns out the hard part of working with these tools isn't the tools.