Skip to content
Engineering#ai-agents#engineering#governance#developer-tooling#automation#hooks

Why We Built Sentinel Enforcement into Agent Development Tools

Reading time:9 min read
By

Why We Built Sentinel Enforcement into Agent Development Tools

The Problem Was Not a Lack of Rules

By the time the Sentinel pattern emerged inside Agent Development Tools, the system already had rules, skills, hooks, and enforcement intent.

The missing layer was not policy. It was memory.

A lot of hook-based governance systems assume that each lifecycle event can make a correct decision in isolation. In practice that breaks down quickly in agentic environments.

A PreToolUse hook often needs to know something that happened earlier in the session:

  • was the right skill already activated?
  • did the last test run fail?
  • did the user explicitly ask for a certain discipline?
  • did another agent just touch this file?
  • did this subagent actually run, or was that only mentioned in the prompt?

Without some durable session evidence, every enforcement attempt starts guessing.

The Core Need Sentinel Solved

Sentinel was not introduced to make ADT stricter for its own sake. It was introduced because lifecycle hooks are stateless, while agent governance often depends on something that happened one or two events earlier.

Why LLM-Only Enforcement Was Not Enough

One of the clearest examples in the repo history is the move away from an LLM-based skill gate.

A PreToolUse prompt hook using Haiku tried to determine whether a required write-* skill had been activated before someone edited ADT rules, hooks, or skills. That sounded elegant. In practice it was brittle.

The commit that replaced it says the quiet part out loud: the model hook had no reliable visibility into the session's actual activation state. It could read the current event, but it could not deterministically know whether the skill tool had fired earlier in the same session.

That is the key conception point for Sentinel. The system needed an enforcement primitive that was:

  • cheap
  • deterministic
  • session-scoped
  • visible to ordinary shell hooks
  • and independent of whether an LLM could reconstruct context correctly

What Sentinel Actually Is

In ADT, Sentinel is a small file-based state layer written into /tmp/ and read back by later hooks. The canonical pattern is:

/tmp/.adt-{type}-{session_id}[-{discriminator}]

That sounds simple because it is simple. That is part of why it works.

Sentinel typeExample shapeWritten byRead byPurpose
Skill active.adt-skill-active-write-hooks-{session_id}skill-activation-sentinel.shrequire-skill-for-adt.shBlock ADT edits unless the right skill was actually activated
Debug required.adt-debug-required-{session_id}detect-test-failure.shrequire-debug-skill.shStop blind editing after a failing test or typecheck run
Prompt intent.adt-intent-{session_id}-{skill}prompt-intent-sentinel.shintent-skill-check.shCompare what the user asked for with what actually got activated
Agent run.adt-agent-{session_id}-{type}agent-run-sentinel.shintent-skill-check.shAccept completed agent execution as evidence
File lock.adt-filelock-{file_hash}file-lock-write.shfile-lock-check.shWarn about parallel edits to the same file

This is not a database. It is not a workflow engine. It is a deliberately tiny state-bridge between otherwise stateless hook invocations.

Why a File-Based Technique Made Sense

I think the design makes sense for five practical reasons.

1

It records the smallest useful fact

Each sentinel stores a binary or near-binary fact: this skill was activated, this test run failed, this file was recently touched, this intent was declared. That keeps the mechanism simple enough to trust.

2

It works across lifecycle boundaries

PostToolUse hooks can write state that PreToolUse, TaskCompleted, or Stop hooks can read later. That is exactly the gap ordinary hook systems struggle with.

3

It stays cheap in the hot path

Checking whether a file exists in /tmp/ is fast. ADT's own enforcement docs explicitly say heavy enforcement should sit at natural boundaries, while hot-path checks stay cheap.

4

It isolates sessions cleanly

Most sentinels include session_id, which means parallel sessions and subagents do not interfere with one another by accident. That matters a lot in orchestrated agent workflows.

5

It remains inspectable

When enforcement behaves unexpectedly, the mechanism is debuggable with ordinary shell tools. You can inspect the sentinel, check whether it exists, see when it was written, and reason about why the next hook made the decision it did.

The Need Behind It

The deeper need was not just technical convenience. It was enforcement reliability.

ADT is trying to turn rules like these into real behaviour:

  • use the right skill before editing governance files
  • do root-cause work before blindly patching after a failed test run
  • distinguish between a user mentioning a skill and an agent actually activating it
  • keep parallel work visible without freezing the whole system

Those are all examples of a broader pattern:

a later decision depends on verified evidence from an earlier event

That is the category Sentinel serves.

The Evolution of the Technique

The git history shows a fairly clear progression.

StageWhat changedWhy it mattered
63f01f4ADT added a 4-layer skill activation reliability systemThis established that skill activation was not just guidance. It was a reliability problem that needed multiple enforcement layers.
2183c88ADT added real-time test-failure enforcement using a debug-required sentinelThis was the first strong expression of the pattern: a later edit gate depended on earlier test evidence.
bc911aeThe Haiku skill gate was replaced with deterministic skill sentinelsThis appears to be the clearest conception moment for Sentinel as a named enforcement technique. The system moved from inference to evidence.
4ed5029Sentinel usage expanded across prompt intent, stale-read tracking, file locks, and agent-run evidenceSentinel stopped being a single fix and became a general enforcement architecture for cross-event state.
331b173Skill sentinels expanded beyond write-* skills and intent-vs-activation checks were addedThe technique matured from simple gating to governance auditing. It could now compare what was requested with what actually happened.
287ce53Several legacy hooks and sentinels were retired or reducedThis was the correction phase: keep sentinel where the signal is strong, remove it where latency and false positives outweigh value.

That last stage matters as much as the first ones. A lot of systems know how to add enforcement. Fewer know how to narrow it back down after observing real operational cost.

The Intent Was Never Maximal Blocking

One of the strongest ideas in docs/enforcement-system.md is that hard blocks should be reserved for unambiguous violations with near-zero false positives.

That principle explains why some Sentinel use cases stayed and others did not.

The good fits are easy to see:

  • if write-hooks was not activated, blocking edits to ADT hooks is reasonable
  • if a test failure sentinel exists, forcing explicit debugging discipline is reasonable
  • if another session touched the same file, surfacing an advisory is reasonable

But other uses created more drag than value. The stale-read system is the clearest example. It was added to detect edits made against outdated reads, then later removed when the repo concluded that Claude 4.6 self-corrected well enough and the enforcement added false positives and hot-path latency.

That tells you something important about the real intent. Sentinel was not meant to become ideology. It was meant to become calibrated infrastructure.

What Sentinel Is Really For

My current read is that Sentinel exists to do four things well:

  • turn session history into cheap, testable evidence
  • let deterministic shell hooks enforce rules that would otherwise require memory
  • support multi-agent workflows without requiring a central service
  • keep enforcement inspectable enough that it can be audited and tuned back when necessary

That is a narrower claim than saying Sentinel is the future of agent governance. I do not think it is.

I think it is a very good answer to a more specific question:

how do you give stateless lifecycle hooks just enough memory to enforce the right thing one step later?

For that problem, Sentinel is a strong technique.

My Current View

I think the most interesting part of the ADT Sentinel story is not that it introduced more enforcement. It is that it made enforcement more evidence-based.

The shift was basically this:

  • from model inference about what probably happened
  • to deterministic proof that something did happen

That is a big difference in an agentic system.

Once agents are doing many steps across multiple hooks, fuzzy enforcement becomes expensive. A hook that guesses wrong either blocks legitimate work or lets weak discipline slip through.

Sentinel reduces that ambiguity by carrying small pieces of verified state forward. Then the later hook makes a narrower, more defensible decision.

That is why I think the technique matters. Not because writing tiny files in /tmp/ is clever, but because it is a practical way to give governance systems memory without making them heavy.

Conclusion

Sentinel enforcement in Agent Development Tools did not emerge because hooks were fashionable or because stricter governance sounded impressive.

It emerged because stateless hooks kept running into decisions that required memory.

The technique gave ADT a lightweight memory layer. That made some gates deterministic, made some advisories evidence-based, and made the broader enforcement system easier to reason about.

Just as importantly, the repo history shows that the technique was later pruned where it was no longer earning its keep.

I think that is the real lesson.

Good agent governance is not just about adding more rules. It is about finding the smallest amount of durable state that lets the next decision become trustworthy.