Wiring a "read this first" hook as "ask" (don't)

작성자

카테고리:

← 피드로
DEV Community · Gábor Mészáros · 2026-07-01 개발(SW)
Cover image for Wiring a "read this first" hook as "ask" (don't)

 Gábor Mészáros

In retrospect, it was pretty obvious… sharing it anyway.

I’m currently working on a self-steering progressive disclosure system, and I wanted my agent to read a design doc before it touched the code that doc governs. Simple PreToolUse hook: match Edit/Write, check whether the doc was Read this session, and if not, stop the edit and tell the agent to read it first.

I returned permissionDecision: "ask". My reasoning at that time: “ask has an escape hatch. Approve and the call proceeds, so a bad condition can never wedge the agent – you can always wave it through.”

That safety was the whole problem. The approval is an escape from the prerequisite, not a path through it. The edits went through without the doc reads.

Here is what ask actually does. It surfaces the tool call for approval. Approve it – or auto-approve it – and the action runs. The doc never gets read. ask is a checkpoint for a human, not a gate on the agent. Nothing about it makes the agent do the prerequisite step.

The fix was one field. Return deny:

// PreToolUse hook, matcher: Edit|Write
if (!wasReadThisSession(governingDoc)) {
  return {
     hookSpecificOutput: {
         hookEventName: "PreToolUse",
         permissionDecision: "deny",
         permissionDecisionReason: `Read ${governingDoc} before editing this, then retry.`
     }
  };
}

Enter fullscreen mode Exit fullscreen mode

deny refuses the tool call and hands the agent the reason. The agent can’t proceed, so it does what the reason says – reads the file – and retries. The read clears the check, the retry passes.

This is the behavior Claude Code already ships natively: when it tries to Edit a file that haven’t been Read before, the tool refuses the action until the relevant Read happens. The deny hook lets you apply that same read-before-edit rule to any file you designate, not only the file being edited.

The distinction I missed:

  • ask gates on approving the call.

  • deny gates on the agent doing the prerequisite work first.

If the goal is to force the agent’s own behavior – read this, run that check, load that context – deny is the lever. ask just adds a human to the loop.

Important: this only works, if the gate releases accurately, when the prerequisite is actually done. A deny on a condition that never clears will wedge the agent. Mine keys off “was this file read this session,” which the read itself flips.

원문에서 계속 ↗

코멘트

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다