Configure Hooks (Allow / Deny / Approval)

Hooks are pattern-matched rules that intercept tool calls before they execute. Use them to:

  • Block tools under certain conditions ("EMCON active -- no map emissions")
  • Allow tools that would otherwise require approval
  • Force approval on tools that would otherwise auto-run

Where hooks live

In custos.yaml:

hooks:
  rules:
    - event: PreToolUse
      toolPattern: "place_*"
      action: deny
      reason: "EMCON active — no map emissions"

    - event: PreToolUse
      toolPattern: "speak_alert"
      action: allow

    - event: PreToolUse
      toolPattern: "detect_*"
      action: require_approval

Rule fields

Field Required Description
event yes When to evaluate. Supported: PreToolUse, PostToolUse, PostToolUseFailure
toolPattern yes Glob pattern matched against the tool name. * matches anything.
action yes One of: allow, deny, require_approval
reason no Human-readable string shown to the operator on deny and logged to audit
whenTier no List of tier names. Rule only fires when the chat provider serving the current turn is in this set. Null/empty matches every tier.

Rule semantics

Rules are evaluated in order. The first match wins. If no rule matches, the tool is evaluated against its @impact level alone (the default approval gate).

  • allow -- tool runs immediately, bypassing the impact-level gate
  • deny -- tool does NOT run; the agent sees a denied result with your reason
  • require_approval -- the approval dialog opens regardless of impact level

If two rules match, only the first one fires. Order your rules carefully.

Recipes

Deny everything that mutates state

hooks:
  rules:
    - event: PreToolUse
      toolPattern: "place_*"
      action: deny
      reason: "Read-only mode"
    - event: PreToolUse
      toolPattern: "send_*"
      action: deny
      reason: "Read-only mode"
    - event: PreToolUse
      toolPattern: "delete_*"
      action: deny
      reason: "Read-only mode"
    - event: PreToolUse
      toolPattern: "create_*"
      action: deny
      reason: "Read-only mode"

Allow alerts without approval, require approval for everything else

hooks:
  rules:
    - event: PreToolUse
      toolPattern: "play_tone"
      action: allow
    - event: PreToolUse
      toolPattern: "speak_alert"
      action: allow
    - event: PreToolUse
      toolPattern: "send_notification"
      action: allow
    - event: PreToolUse
      toolPattern: "*"
      action: require_approval

The catch-all toolPattern: "*" at the end forces approval on anything not whitelisted above.

EMCON (radio silence) lockdown

hooks:
  rules:
    - event: PreToolUse
      toolPattern: "send_cot"
      action: deny
      reason: "EMCON in effect"
    - event: PreToolUse
      toolPattern: "send_chat"
      action: deny
      reason: "EMCON in effect"
    - event: PreToolUse
      toolPattern: "place_marker"
      action: deny
      reason: "EMCON in effect — markers broadcast as CoT"

Approval-gate the dangerous tools only

hooks:
  rules:
    - event: PreToolUse
      toolPattern: "delete_*"
      action: require_approval
    - event: PreToolUse
      toolPattern: "send_package"
      action: require_approval
    - event: PreToolUse
      toolPattern: "activate_beacon"
      action: require_approval

Require approval when reasoning is on the cloud or at the command post

whenTier lets a rule care about which provider is producing the tool call. Useful when you want tighter gates on comms actions when reasoning happens off-handheld, but want the local model to run the same tools without extra friction:

hooks:
  rules:
    - event: PreToolUse
      toolPattern: "send_*"
      whenTier: ["cloud", "command-post"]
      action: require_approval
      reason: "Comms tools require approval when reasoning at remote tiers"

This rule only fires when the active chat provider's tier is cloud or command-post. If a handheld-tier on-device model issues the same tool call, the rule is skipped and the default @impact gate applies.

What the operator sees on a deny

The agent reports the denial in plain language ("I cannot place a marker right now: EMCON in effect"). The denial is also recorded in the Audit panel.

What the operator sees on require_approval

An approval dialog opens with:

  • The tool name
  • The arguments the agent wants to pass
  • The impact level
  • An approve / deny / modify choice

The dialog blocks the agent until the operator chooses. If the operator picks "modify," they can edit the tool arguments inline before approving -- useful for sanity-checking coordinates.

Hot-reload

Saving custos.yaml reloads the config. New rules take effect on the next tool call. No restart needed.

Limits

  • First-match wins. Put specific rules above generic ones.
  • PreToolUse fires before the impact gate. Use it for the override-the-gate use case.
  • PostToolUse and PostToolUseFailure fire after -- useful for logging or auditing, but you cannot undo a tool call.
  • Glob patterns are simple. * matches anything. No ? or character classes.