Summary
The architecture of agentic coding
Claude Code is built around an agentic coding system where a large language model collaborates with a deterministic harness. The harness is not just a simple wrapper. It is a structured environment that governs how the model interacts with a codebase. It manages file access, command execution, tool permissions, and the overall flow of a task. Understanding this dual architecture is the foundation for building reliable AI coding assistants. The model brings probabilistic reasoning and language understanding, while the harness enforces rules, boundaries, and reproducible outcomes.
This partnership means that purely relying on the model's instructions is not enough. The coding harness acts as a safety net and an orchestrator. It decides what the model can see and which actions it can perform. Without a well-designed harness, the system remains vulnerable to the inherent uncertainty of large language models. The harness is what transforms a chat interface into a production-grade engineering tool.
Why probabilistic models need guardrails
Large language models are inherently probabilistic. They generate responses based on patterns learned during training, which means the same prompt can produce different outputs over time. This non-deterministic nature poses significant risks in software projects. A critical file could be deleted, a database could be dropped, or an unsafe shell command could be executed, all based on a hallucination or a misaligned interpretation of an instruction. Simple prompt instructions, like those written in a claude.md file, still pass through this probabilistic filter and can be ignored or bypassed.
The unpredictability becomes a concrete risk when real-world consequences are attached to the model's output. A coding assistant that can modify your file system cannot operate purely on trust. It needs programmatic, deterministic guardrails that execute before or after the model's actions. These guardrails must follow strict rules that cannot be overridden by any prompt, no matter how persuasive. This is why hooks exist: they provide the deterministic layer that wraps around the probabilistic core, ensuring consistent safety and behavior.
The agent loop and session lifecycle
To implement effective hooks, it is essential to understand the agent loop that drives Claude Code. When a task is assigned, the system enters a continuous cycle. It observes the current environment, reasons about the next best action via the language model, executes that action through a tool like a terminal command or a file edit, and then observes the result. This loop continues until the task is completed or a termination condition is met. Each iteration is a potential point of failure, where a wrong action can cascade into larger issues.
This cycle is further framed by the session lifecycle. A session passes through distinct phases: starting, running a task, yielding results, and potentially encountering an error or ending. Crucially, specific events are emitted at these boundaries. Events such as before and after a tool call, on session start, and on error create natural interception points. Hooks latch onto these events, allowing developers to inject custom logic that runs deterministically at every stage, transforming a fluid, open-ended loop into a controlled engineering process.
Hooks as a deterministic intervention layer
The core concept of a hook is an action that is triggered automatically and deterministically by a specific event. In systems like Git, hooks run scripts before a commit or after a merge. Claude Code generalizes this pattern for AI-driven coding. A hook is defined by three components: an event that fires at a specific point in the lifecycle, a matcher that narrows the scope using criteria like file paths or command names, and the action to execute when those conditions are met.
This architecture allows for surgical interventions. For instance, a hook can listen to the PreToolUse event. Its matcher can be configured to watch for any command starting with rm -rf. The action, connected to an external script, can then evaluate the command. If the command targets a protected directory like a production database, the hook's action returns a decision telling the harness to block the operation. This prevents the dangerous command from ever reaching the system shell, turning a probabilistic recommendation into an enforced hard boundary.
Preventing dangerous file operations in practice
One of the most tangible applications of hooks is preventing catastrophic data loss. A practical file protection hook demonstrates this clearly. A developer can write an external script, in any language, that acts as a policy engine. When Claude Code attempts to use the Bash tool, the PreToolUse event fires. The hook system passes the full proposed command to the external script. The script analyzes the command against a configurable list of sensitive paths and critical files.
If a violation is detected, the script outputs a structured JSON message containing a decision to block the operation and a user-friendly message explaining why. Claude Code's harness reads this decision and halts the tool execution. This creates a protection mechanism that is far more robust than any prompt-based instruction. It works consistently regardless of the model's state, and it can be version-controlled and reviewed just like any other security-critical code. In a live demonstration, an attempt to delete a database file is intercepted and stopped before any damage occurs.
Automated workflows and quality enforcement
Safety is just one dimension. Hooks are also a powerful mechanism for automating workflows and ensuring code quality. An auto-formatting hook can trigger immediately after Claude edits a file. By listening to the PostToolUse event and matching on file writes, the hook can run a formatter like Prettier or Black on the modified file. This guarantees that the code checked into the repository always respects the project's style guide, without the developer ever having to issue a manual command.
The same principle applies to linting and security scanning. A linting hook can run ESLint, Pylint, or shellcheck after a file change, feeding any detected errors back into the session for an immediate fix. A security hook can scan for accidentally committed API keys or secrets. Other practical hook types include notification hooks that post a message to Slack when a long-running task finishes, and telemetry hooks that monitor and log the behavior of sub-agents for debugging and cost analysis.
Integration with real project ecosystems
Hooks are not isolated environments. They are designed to integrate deeply into larger development ecosystems. A typical workflow might involve Claude Code interacting with the Model Context Protocol, or MCP, to access external services like GitHub. A hook can run before a push, checking for correct branch names, linking issues, and valid commit messages. If a GitHub token lacks permissions, a hook can detect the error event and guide the developer through the remediation.
This allows for the creation of custom, high-level project commands. A Ship Feature command can be defined using a sequence of hooks. The command might trigger a series of events: a PostToolUse hook formats the code, a subsequent hook runs the full test suite, and a final hook builds and deploys the feature. Every step of this complex workflow is governed by the deterministic, predictable logic of hooks, ensuring the release pipeline is as reliable as possible.
Evolving towards harness engineering
The adoption of hooks signals a broader shift towards harness engineering. The ecosystem is moving away from the model of an AI as an autonomous agent and towards a model of a supervised, tool-equipped reasoning engine. The developer's role evolves from writing instructions to engineering the environment that constrains and guides the AI. This requires a new discipline that blends traditional software engineering with an understanding of probabilistic systems.
Designing effective coding harnesses means thinking in terms of failure modes, event-driven architectures, and policy enforcement. As AI coding tools become more capable and autonomous, the harness becomes the primary source of trust and safety. Hooks provide the fundamental building blocks for this new layer of the stack, allowing teams to codify their practices, enforce their security policies, and build software with AI in a way that is both powerful and safe.
What you will learn
- Understand the agent loop and session lifecycle within an agentic coding system
- Build deterministic safety guardrails that prevent dangerous file operations
- Apply hooks for automated code formatting, linting, and security scanning
- Implement notification and telemetry hooks for real-time monitoring
- Integrate custom hook workflows into production-grade projects using MCP and version control
Concepts covered
Technologies used
Chapters 10 markers
- Introduction
- Why Hooks Exist
- Understanding the Coding Harness
- The Core Problem of Safety in Probabilistic Systems
- How the Agent Loop Executes Tasks
- Session Lifecycle and Events
- Hooks Defined and How They Work
- Practical Hooks for Formatting, Linting, and Security
- Building a File Protection Hook
- Live Demo and Real Project Integration
Next suggested video
Reviews
No reviews yet. Be the first to rate this lesson.