Prompts are suggestions. Hooks are hard stops.
For months, I treated Claude Code like a junior developer who simply needed clear ground rules. My project instructions were explicit: never force-push, never delete branches, never run destructive commands. Most evenings, that worked. The agent wrote tests, refactored functions, and kept its hands off the git history. Then one rebase went sideways.
The context window filled with git error output. Conflict markers, detached HEAD messages, and branch divergence warnings stacked up, token by token. Buried under that noise was my polite instruction to avoid force-pushing. To the model, the most recent and salient text in the thread was the error stream. Statistical attention won over policy. The agent executed a command that wiped two hours of uncommitted local changes. It was not malicious; it was distracted. That distinction matters. An LLM does not break rules out of spite. It breaks them because a louder pattern in the context window temporarily overrides an earlier instruction.
That incident changed how I think about agent safety. A guardrail that works ninety-nine percent of the time is a liability. If the failure mode costs you time, money, or production data, you cannot leave it inside the prompt. You need enforcement outside the model’s reasoning loop.
Claude Code hooks solve exactly this. They are small scripts that intercept tool calls at three specific moments: before a tool executes (PreToolUse), after a tool finishes (PostToolUse), and when the agent decides it is done (Stop). Because they run as external code, they do not depend on the model’s memory, mood, or context pressure. The model can forget every instruction you ever gave it; the hook will still say no.
Here is the harness I built after that lost evening.
The Guard Hook: Intercept Before Damage
My PreToolUse hook inspects every Bash command before the shell touches it. I keep a tight denylist of destructive patterns. If the command string matches something dangerous, the hook aborts execution and returns an error directly back to the agent.
The patterns I block are simple and unambiguous:
git push --forceor any force-with-lease variant I do not trust yetgit reset --hardrm -rf
This is not sophisticated security research. It is a seatbelt. But the critical detail is what happens after the block.
I never return a blunt “Blocked.” A flat refusal confuses the agent and can trap it in a loop where it tries variations of the same destructive command. Instead, the error message includes an escape route. When the hook catches a hard reset, it tells the agent: “This command is blocked to protect uncommitted work. Commit a checkpoint first, then reassess.” That extra sentence changes the agent’s behavior completely. It pivots from attempting damage control to creating safety. The hook is not just a wall; it is traffic control.
I also chose a denylist over an allowlist for shell commands. At first, I considered allowing only an explicit set of safe git subcommands. That failed quickly. Agents are creatively literal. They run legitimate but unexpected commands like git stash push -m "wip" or git branch --show-current to check state. An allowlist breaks normal workflow the moment the model invents a valid but unlisted command. A short, curated denylist of genuinely destructive patterns gives the agent room to move while protecting the borders.
The Formatter Hook: Automate the Busywork
I used to waste prompt tokens telling the agent to “always run the formatter after editing a file.” It forgot half the time. The other half, it would pause and ask whether to format, burning a tool call on a decision that had only one right answer.
Now I handle that with a PostToolUse hook. After the agent edits a file, the hook checks the file extension. If it is Python, it runs Ruff. If it is JavaScript or TypeScript, it runs Prettier. If it is Go, it runs gofmt. The agent does not know the formatter exists. It does not need to.
Moving this out of the prompt had two effects. First, the code is consistently clean without adding cognitive load to the model. Second, my project instructions got shorter. Every “always” and “never” you remove from a prompt is a token the model can spend on actual problem-solving. The hook owns the invariant; the prompt owns the intent.
The Quality Gate: Redefining “Done”
જ્યારે એજન્ટ નક્કી કરે છે કે તેણે કાર્ય પૂર્ણ કરી લીધું છે અને સત્ર (session) સમાપ્ત કરવાનો પ્રયાસ કરે છે, ત્યારે Stop hook ચાલે છે. હું તેને તે કરવા દેતો નથી. તેના બદલે, આ hook સંપૂર્ણ ટેસ્ટ સૂટ (test suite) ચલાવે છે. જો કોઈ ટેસ્ટ નિષ્ફળ જાય, તો hook સ્ટોપ કમાન્ડને બ્લોક કરે છે અને એજન્ટને નિષ્ફળતાનું આઉટપુટ પરત કરે છે.
આ પૂર્ણતાની વ્યાખ્યા બદલી નાખે છે. “Done” એ હવે મોડેલની માત્ર એક લાગણી નથી. તે એક માપી શકાય તેવું દ્વાર (measurable gate) છે. એજન્ટ ત્યારે જ કાર્ય પૂર્ણ કરી શકે છે જ્યારે harness ખાતરી કરે કે કોડ કામ કરે છે. વ્યવહારમાં, આ એક મજબૂત ફીડબેક લૂપ (feedback loop) બનાવે છે. એજન્ટ કોડ લખે છે, તેને લાગે છે કે તે પૂર્ણ થઈ ગયો છે, સ્ટોપ બટન દબાવે છે, અને તરત જ pytest traceback જુએ છે. તે પછી તે સ્વયં-સુધારો કરે છે, ઇમ્પોર્ટ એરર અથવા બ્રોકન એસેર્શન (broken assertion) સુધારે છે, અને ફરીથી સ્ટોપ કરવાનો પ્રયાસ કરે છે. મેં એજન્ટોને માનવીય હસ્તક્ષેપ વિના આ લૂપની અંદર ત્રણ કે ચાર વાર પુનરાવર્તન (iterate) કરતા જોયા છે. Harness ગુણવત્તા જાળવી રાખે છે; મોડેલ પેચ (patches) પૂરા પાડે છે.
આ એજન્ટ એન્જિનિયરિંગ વિશે શું શીખવે છે
વિશ્વસનીય સ્વાયત્ત પ્રણાલીઓ (autonomous systems) બનાવવા માટે માનસિકતામાં પરિવર્તનની જરૂર છે. તમે લાંબા પ્રોમ્પ્ટ્સ લખવાથી બદલાઈને વધુ મજબૂત harnesses બનાવવાની દિશામાં આગળ વધો છો.
અમલીકરણ માટે hooks નો ઉપયોગ કરો અને નીતિ (policy) માટે prompts નો ઉપયોગ કરો. જો કોઈ નિયમ સો ટકા સમય માટે લાગુ પડવો જોઈએ, તો તે કોડમાં હોવો જોઈએ, કુદરતી ભાષામાં નહીં. પ્રોમ્પ્ટ્સ અસ્પષ્ટતા, રુચિ અને આર્કિટેક્ચર માટે ઉત્તમ છે. તેઓ ઇનવેરિયન્ટ્સ (invariants) માટે બિલકુલ યોગ્ય નથી. જો કોઈ ભૂલને કારણે તમારો આખો બપોરનો રિકવરી સમય બગડે અથવા તેનાથી પણ ખરાબ, પ્રોડક્શન અપટાઇમ (production uptime) માં સમસ્યા આવે, તો એક hook લખો.
ટૂંકા પ્રોમ્પ્ટ્સ વધુ સારા પરિણામો આપે છે. જ્યારે તમે યાંત્રિક નિયમોને સ્ક્રિપ્ટ્સમાં લઈ જાઓ છો, ત્યારે મોડેલે ઓછું યાદ રાખવું પડે છે અને વિરોધાભાસ કરવાની શક્યતા પણ ઓછી રહે છે. એજન્ટનું context window એક દુર્લભ સંસાધન છે. તેને ફોર્મેટિંગ રિમાઇન્ડર્સથી ભરી ન દો.
અંતે, સ્વીકારો કે તમારી ભૂમિકા બદલાઈ રહી છે. જેમ જેમ એજન્ટો સ્વાયત્તતા મેળવે છે, તેમ તેમ માણસનું કામ કન્ટેન્ટ જનરેટ કરવાથી બદલાઈને ગાર્ડરેલ્સ (guardrails) ડિઝાઇન કરવા તરફ જાય છે. તમે એવું harness બનાવી રહ્યા છો જે નક્કી કરે છે કે મોડેલ શેને સ્પર્શી શકે છે, તે ક્યારે પૂર્ણ કરી શકે છે, અને જ્યારે વસ્તુઓ ખોટી જાય ત્યારે તેણે કેવી રીતે વર્તવું જોઈએ. તે એન્જિનિયરિંગ છે, પ્રોમ્પ્ટિંગ નથી.
આ અભિગમથી પ્રેરિત સ્ત્રોત અને વધારાની અમલીકરણ વિગતો અહીં મળી શકે છે.
જો તમે AI એજન્ટ્સ સાથે કામ કરી રહ્યા છો અને અન્ય પ્રેક્ટિશનરો સાથે અનુભવો શેર કરવા માંગતા હોવ, તો તમે GyaanSetu લર્નિંગ કોમ્યુનિટી અહીં શોધી શકો છો.
