what claude code's hooks taught me about agent design
claude code has hooks. user-prompt-submit, pre-tool-use, post-tool-use, stop, notification. the ones i actually use are the ones i didn’t expect to need.
the harness doesn’t prescribe, it intercepts
the design move that matters: you don’t configure the agent through a yaml of allowed-things; you write a shell script that runs at a specific moment in the loop. the unix philosophy showed up in a coding agent.
policy vs composition
what that does to your mental model: you stop thinking about “how do i tell the agent to do x” and start thinking about “what’s the lifecycle event where x belongs.” those are different shapes. the first is policy. the second is composition.
i’d been writing my own agent loops with everything inside the loop body — guards, retries, telemetry, formatting. each loop body grew until it was unreadable. when i moved that stuff into pre/post hooks (in my own code, not claude code’s), the loop became a loop again. it iterated. that was its job.
the trade-off is debuggability. when behaviour is split across the loop body and three hooks, the failing case isn’t where you look first. you have to know the lifecycle. that’s a cost. it pays back when you want to swap one hook for another — which i started wanting to do as soon as i had hooks at all.
agentic patterns covers a more general version of this: extensions, the pattern where middleware composes around the agent step. claude code is the proof that this isn’t theory — it’s how a working coding agent gets structured in 2025.
if i was starting an agent system today, i’d pick the harness with the most boring lifecycle and the most extensible hooks. not the one with the most features. and i’d put the per-feature intent in a spec the agent reads as input, not a chat transcript that doesn’t survive the session.