Skip to main content
ELI5: a hook is a tripwire on the agent’s loop. Before or after the agent does something (use a tool, submit a prompt, start a subagent, stop), a hook fires and can allow it, deny it, ask the human, inject context, or suppress output. Hooks are how you steer an agent without rewriting its prompt.

The two halves: events and decisions

Hook events are when the tripwire fires (Claude Agent SDK event union): pre-action (PreToolUse, UserPromptSubmit, PermissionRequest), post-action (PostToolUse, PostToolUseFailure), lifecycle (SessionStart, SessionEnd, Stop), subagent (SubagentStart, SubagentStop), plus PreCompact and Notification. Hook decisions are what the hook says back — the rows you see on the Anthropic provider page:
DecisionEffect
allow_toolThe intercepted tool call proceeds.
deny_toolThe tool call is blocked; the agent sees the denial and must adapt.
ask_userEscalate to a human permission prompt before proceeding.
additional_contextInject a string into the agent’s context at the hook point.
suppress_outputHide the intercepted output from the transcript.
continue: falseHalt the loop entirely.

What works today (honest status)

Hooks are currently runtime-level, not workflow-level. There are no hook fields in workflow.md frontmatter yet, and Cadence does not construct hook callbacks at dispatch. That is why every hook row carries the partial-compatible badge: the SDK surface is real and plumbed, the deeda-authored policy path is not wired yet.
What you CAN do today:
  1. Native Claude Code harness mode — shell hooks defined in Claude settings (settingSources: [project, local], i.e. your project’s .claude/settings.json) fire normally when the harness drives Claude Code natively. This is where hooks are stored and persisted: in the project/local settings files, versioned with your repo — not in workflow markdown, not in a deeda database.
  2. In-band hook steering — deeda’s autopilot workflows instruct agents to treat PreToolUse hook output and Cadence policy blocks as authoritative: stop the unsafe action, record the policy-block text in the workpad, correct, retry. The reaction policy lives in workflow markdown prose; the enforcement lives in the hook.
What you CANNOT do yet: declare hooks: in workflow frontmatter and have Cadence enforce it per-run across providers. When that lands it will appear in the Workflow Schema — if the field is not there, it is not real.

Example: a project hook (works today, native mode)

.claude/settings.json in your repo:
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          { "type": "command", "command": "./scripts/guard-shell.sh" }
        ]
      }
    ]
  }
}
The guard script exits non-zero (with a reason on stdout) to deny the tool call; the agent sees the denial text and adapts. Pair it with workflow prose telling the agent how to react (see the autopilot pattern above).

When to use hooks vs alternatives

You wantUse
Block/allow specific tool calls deterministicallyHook (PreToolUse + deny)
Bound what a whole run may touchtool_policy / sandbox_profile in frontmatter — see Workflow Schema
Cross-provider, per-run policyCadence frontmatter (budgets, sandbox, review) — hooks are Anthropic-runtime today
Human sign-off on risky stepsreview_consensus or hook ask_user

See also