Skip to content

Guard Example

Z-M-Huang edited this page Apr 27, 2026 · 2 revisions

Guard hook (reference)

A minimal reference guard. Demonstrates the canonical shape of a guard hook that votes on a tool call by inspecting its arguments. Reference only — normative shape and rules live in Hooks (contract).


Purpose

A guard hook is the last line of defense before a tool body runs. This example denies any Bash tool invocation whose command argument contains rm -rf. It is the kind of per-call, argument-sensitive policy the Hooks § Orthogonality with State Machines section calls out as guard territory — coarse allowedTools at the SM level cannot express this, because the SM cannot peek inside command strings.


Shape

Field Value
Kind Hook.
subKind guard.
Attachment TOOL_CALL/pre.
Firing sync (guards are always sync — see Firing mode).
Validation severity Critical by default — a guard on TOOL_CALL/pre is critical per Hooks § Validation severity. A load failure fails the session, because silently dropping the guard would weaken security posture.
State slot None needed. Guards should be stateless and deterministic.

Behavior

flowchart LR
    Call[TOOL_CALL/pre fires] --> Check{tool is Bash<br/>and command<br/>matches rm -rf?}
    Check -->|yes| Deny["return deny<br/>reason: dangerous-delete"]
    Check -->|no| Approve[return approve]
    Deny --> Audit["emit audit record:<br/>GuardDeny"]
    Approve --> Next[next guard / body]
Loading

On deny:

  1. The turn-stage body does not run.
  2. Post-slot transforms and observers do not run.
  3. TOOL_CALL/pre observers still fire so the deny is visible in the event stream.
  4. The guard writes a GuardDeny audit record through host.audit — see Hooks § Security notes. Audit on deny is non-optional.
  5. Core translates the deny into a typed tool-result the LLM can see on the next turn. See Guard-Deny-Reproposal flow.

Config

Field Meaning Default
enabled Whether the hook participates. true.
severity critical or optional. Cannot demote below critical per the conditional-severity rule. critical.
patterns[] Regex or substring patterns the command is matched against. [] (no-op if empty).

The guard reads its own config through the validated config object delivered during init; it does not read env or files directly.


When to copy this pattern

  • You need to block a tool call based on arguments, not on identity. Coarse "block the whole Bash tool" belongs in allowedTools, not here.
  • The decision is cheap and pure — no network calls, no filesystem reads per invocation. Guards are on the hot path.
  • The decision can be audited with useful context. A deny a user cannot understand is worse than no deny at all.

Do not use a guard for:

  • Mutating arguments — that is a transform.
  • Recording every tool call for analytics — that is an observer.
  • Asking the user "are you sure?" — that is the Security Mode gate or an interactive tool, not a guard. Guards cannot drive the Interaction Protocol.

Related pages

Introduction

Reading

Core runtime

Contracts

Category contracts

Context

Security

Runtime behavior

Operations

Providers (bundled)

Integrations

Reference extensions

Tools

UI

Session Stores

Loggers

Providers

Hooks

Context Providers

Commands

Case studies

Flows

Maintainers

Clone this wiki locally