Hooks

Hooks

Hooks are shell commands that fire at specific points in the agent’s lifecycle. Use them for policy enforcement, telemetry, automation, and integrations that should run automatically — not when the agent feels like it.

Why Hooks (Not Memory)

The harness executes hooks, not the agent. That means:

  • Hooks always run when their event fires
  • Hooks block tool calls (e.g., reject a git push --force)
  • Hooks run before the agent sees the result

Memory and skills are guidance the agent may follow. Hooks are rules the harness will enforce.

Hook Events

EventFires
SessionStartWhen a session opens
UserPromptSubmitAfter the user submits a prompt
PreToolUseBefore any tool runs
PostToolUseAfter any tool returns
StopWhen the agent ends a turn
NotificationWhen the agent needs user input
PreCompactBefore automatic context compaction
SubagentStopWhen a sub-agent finishes

Configuration

Hooks live in ~/.syntic/settings.json (global) or .syntic/settings.json (project):

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "scripts/check-bash-allowlist.sh"
          }
        ]
      }
    ],
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "npx prettier --write $SYNTIC_FILE_PATH"
          }
        ]
      }
    ]
  }
}

Hook Input & Output

Hooks receive JSON on stdin and can reply on stdout:

Input (PreToolUse)

{
  "session_id": "abc123",
  "tool_name": "Bash",
  "tool_input": { "command": "rm -rf /" }
}

Output — block the tool call

{ "decision": "block", "reason": "rm -rf is not allowed in this repo" }

Output — let it run — exit code 0 with empty stdout.

Common Patterns

Block force pushes

#!/usr/bin/env bash
input=$(cat)
cmd=$(echo "$input" | jq -r '.tool_input.command')
if echo "$cmd" | grep -qE 'git push.*--force'; then
  echo '{"decision":"block","reason":"force push blocked by policy"}'
fi

Auto-format after every edit

{
  "matcher": "Edit|Write",
  "hooks": [{ "type": "command", "command": "npx prettier --write $SYNTIC_FILE_PATH" }]
}

Audit every tool call to a SIEM

#!/usr/bin/env bash
cat | curl -s -X POST https://siem.internal/syntic --data @-