Geoffrey Huntley solved a specific agent compliance problem: coding agents kept calling observability modules directly instead of using his diagnostics wrapper library. Documentation drift was inevitable. His solution was to turn git itself into an enforcement boundary.
The technique is simple. A pre-commit hook inspects the git diff for direct calls to observability modules. If it finds any, the commit fails and the hook injects a prompt instructing the agent to use the correct abstraction. Huntley reports 10/10 compliance after implementation.
This is not a linter. It is a runtime constraint system that uses version control as a control plane for agent behavior.
The Enforcement Flow
The hook runs before every commit. It parses the staged diff, looking for import statements or function calls that bypass the diagnostics library. When it detects a violation:
- The commit is rejected with a non-zero exit code
- The error message includes a structured prompt
- The agent receives the failure signal and the corrective instruction
- The agent retries with the correct library usage
The key insight is that agents already understand git commit failures. They retry. The hook exploits that retry loop to inject corrective context at exactly the moment the agent is attempting to persist code.
Implementation Shape
A minimal pre-commit hook for this pattern looks like:
#!/bin/bash
# .git/hooks/pre-commit
DIFF=$(git diff --cached)
# Check for direct observability imports
if echo "$DIFF" | grep -E "^\+.*import (opentelemetry|prometheus_client|logging)" | grep -v "diagnostics"; then
cat <<EOF
COMMIT REJECTED: Direct observability module usage detected.
You must use the diagnostics wrapper library instead of calling
observability modules directly. This ensures consistent tracing,
metrics, and log correlation across all agent-generated code.
Example:
from diagnostics import trace, metrics
# NOT: from opentelemetry import trace
Please update your code to use the diagnostics library and retry.
EOF
exit 1
fi
exit 0
The hook can be more sophisticated. It can parse AST diffs, check for specific function calls, or validate that wrapper methods are used correctly. The pattern scales to any constraint you can express as a diff inspection.
Why This Works for Agents
Agents treat git as a persistence layer. When a commit fails, they interpret the error message as actionable feedback. Unlike human developers who might get frustrated or use --no-verify, agents will retry with corrections.
The hook creates a tight feedback loop:
- Detection latency: Zero. The hook runs before the commit is created.
- Correction latency: One retry cycle. The agent sees the prompt immediately.
- Enforcement coverage: 100%. Every commit goes through the hook.
This is fundamentally different from documentation-based guidance. Documentation is a suggestion. A pre-commit hook is a gate.
State Management and Observability
The hook itself is stateless. It inspects the current diff and makes a binary decision. But you can extend it to track compliance over time:
- Log every violation to a structured log file
- Emit metrics to track violation frequency by agent or module
- Store violation patterns in a database for trend analysis
You can also make the hook context-aware. Pass the current agent session ID or task context into the hook environment, then include that metadata in the rejection message. This lets the agent correlate the failure with its current goal.
Security Boundaries and Bypass Risk
The obvious attack vector is git commit --no-verify. Agents can learn to bypass hooks if they observe that flag in training data or documentation.
Mitigations:
| Approach | Effectiveness | Trade-off |
|---|---|---|
Remove --no-verify from agent tool definitions | High | Requires custom git tooling |
| Server-side hooks on push | Medium | Adds latency, requires git server control |
Audit logs for --no-verify usage | Low | Reactive, not preventive |
| Wrapper script that intercepts git commands | High | Adds complexity, must handle all git workflows |
The cleanest solution is to give agents a git wrapper that does not expose --no-verify. If the agent only has access to a controlled git interface, it cannot bypass the hook.
Failure Modes
Hook script errors: If the hook itself crashes, the commit fails. Agents will retry indefinitely. You need robust error handling and logging inside the hook.
Ambiguous diffs: Rename detection, whitespace changes, and binary files can confuse diff parsing. The hook must handle edge cases or risk false positives.
Prompt injection: If the agent can manipulate the diff content to inject text into the error message, it might confuse itself or other agents reading the log. Sanitize all output.
Performance: Parsing large diffs is slow. If the hook takes more than a few seconds, agents may time out or assume the commit succeeded. Keep the hook fast or run expensive checks asynchronously.
Deployment Shape
For single-agent projects, install the hook in .git/hooks/pre-commit and make it executable. For multi-agent or team environments, use a hook management tool like pre-commit (the Python framework, not the git feature) to version and distribute hooks.
If agents clone repositories, you need to ensure hooks are installed automatically. Options:
- Include a setup script that installs hooks on clone
- Use git templates to inject hooks into new clones
- Require agents to run an initialization command before their first commit
Server-side enforcement is cleaner but requires infrastructure. A git server with update hooks can reject pushes that violate the same rules, providing a second enforcement layer.
When to Use This Pattern
This technique is effective when:
- You have a specific, detectable constraint (library usage, code patterns, file structure)
- Agents are already using git as a persistence layer
- You can express the constraint as a diff inspection
- The cost of a failed commit is low (agents retry automatically)
Avoid this pattern when:
- The constraint is too complex to detect in a diff (requires runtime analysis)
- Agents do not use git (they write directly to filesystems or APIs)
- The feedback loop is too slow (agents time out before seeing the error)
- You need to enforce constraints across multiple commits (use CI instead)
Technical Verdict
Pre-commit hooks as agent guardrails are a clean, low-latency enforcement mechanism for coding agents that use git. They exploit the agent’s natural retry behavior and turn version control into a control plane. The pattern works best for syntactic constraints that can be detected in diffs.
Use this when you need deterministic enforcement of library usage, code structure, or file organization. Avoid it for semantic constraints that require runtime analysis or cross-commit validation. Combine with server-side hooks for defense in depth, and always log violations for observability.
The technique is simple, fast, and effective. It turns a development tool into an agent constraint system without adding new infrastructure.