Documentation / Fleet

Lifecycle Hooks

Execute custom logic at specific points during agent execution with lifecycle hooks.

What Are Lifecycle Hooks?

Lifecycle hooks allow agents to execute custom logic at specific points during their execution. Hooks are defined in an agent's AGENT.md file and can either run a shell script or spawn another agent.

Use hooks for:

  • Setup — Load context or validate environment on startup
  • Validation — Check tool calls before they execute
  • Logging — Audit tool usage and agent activity
  • Cleanup — Perform wrap-up tasks before agent returns
  • Notifications — Alert on errors or completions

Hook Events

Hooks fire at specific points in the agent lifecycle:

Event When It Fires Blocking Use Cases
onStart Agent begins a conversation Yes Load context, validate environment
onStop Agent is about to return Yes Cleanup, summaries, commit changes
beforeToolCall Before any tool is invoked Yes Validation, rate limiting, audit
afterToolCall After a tool completes No Logging, notifications
onError Agent encounters an error No Error reporting, recovery
beforeMessage Before sending to LLM Yes Prompt enrichment
afterMessage After receiving from LLM No Response logging, analytics

Blocking behavior:

  • Yes — Hook must complete before the operation proceeds
  • No — Default is non-blocking, but can be set to blocking via blocking: true

Hook Actions

Script Action

Execute a shell script with template variables substituted.

hooks:
  - event: onStop
    action: script
    script: |
      echo "Agent  completed in ms"
      echo "Token usage:  in /  out"

Exit codes:

Code Meaning Effect
0 Success Continue normally
1 Failure Respect onFailure behavior
2 Skip Skip the operation (e.g., skip tool call for beforeToolCall)

Agent Action

Spawn another agent to handle the hook.

hooks:
  - event: onStop
    action: agent
    agent: wrap-up-agent
    prompt: |
      The conversation is ending. Please perform any wrap-up tasks.

      Summary of session:
      - Agent: 
      - Duration: ms
      - Tool calls: 

The spawned agent runs with full access to its configured tools.


Configuration

Define hooks in the AGENT.md frontmatter:

---
name: my-agent
description: Agent with lifecycle hooks
model:
  provider: anthropic
  model: claude-sonnet-4-20250514

hooks:
  - event: onStart
    action: script
    script: |
      if [ -f "/CONVENTIONS.md" ]; then
        cat "/CONVENTIONS.md"
      fi
    captureOutput: true

  - event: beforeToolCall
    action: script
    filter:
      tools: [Bash]
    script: |
      if echo '' | grep -qE 'rm\s+-rf'; then
        echo "BLOCKED: Dangerous command pattern"
        exit 1
      fi
    onFailure: abort

  - event: onStop
    action: agent
    agent: wrap-up
    prompt: "Summarize what was done and commit any changes"
---

Hook Definition Fields

Field Type Required Default Description
event string Yes When the hook fires
action string Yes script or agent
script string If action=script Shell script to execute
agent string If action=agent Agent name to spawn
prompt string If action=agent Prompt for spawned agent
filter object No Conditions for when hook applies
blocking boolean No varies Whether to wait for completion
timeout integer No 30000 Max execution time in ms
onFailure string No warn warn, abort, or ignore
captureOutput boolean No false Capture stdout as {{hook_output}}
enabled boolean No true Whether hook is active
name string No Optional name for logging

Filtering Hooks

Limit when hooks run with filters:

hooks:
  - event: beforeToolCall
    action: script
    filter:
      tools: [Bash, Write]       # Only for these tools
      excludeTools: [Read, Glob] # Never for these tools
      workspaces: ["/home/user/projects/*"]
    script: |
      # Only runs for Bash/Write in matching workspaces

Filter Fields

Field Type Description
tools string[] Only run for these tools
excludeTools string[] Don't run for these tools
workspaces string[] Only in matching workspaces (glob patterns)

Failure Behavior

Control what happens when a hook fails:

Value Description
warn Log a warning and continue (default)
abort Abort the current operation
ignore Silently continue without logging
hooks:
  - event: beforeToolCall
    action: script
    script: |
      # Validate tool call
      if [ dangerous ]; then exit 1; fi
    onFailure: abort  # Block the tool call

Context Variables

Hooks receive context through template substitution ({{variable}}).

Common Variables (All Hooks)

Variable Type Description
{{agent_name}} string Agent name
{{agent_id}} string Agent instance ID
{{conversation_id}} string Current conversation ID
{{workspace}} string Working directory
{{timestamp}} string ISO 8601 timestamp
{{json_context}} string Full context as JSON

onStart Variables

Variable Description
{{trigger_type}} How started: cli, trigger, api, subagent
{{trigger_name}} Trigger name if applicable
{{parameters.<name>}} Individual parameter values
{{parent_agent}} Parent agent name if subagent

onStop Variables

Variable Description
{{duration_ms}} Total conversation duration
{{message_count}} Number of messages exchanged
{{tool_call_count}} Number of tool invocations
{{token_usage.input}} Input tokens consumed
{{token_usage.output}} Output tokens generated
{{exit_reason}} complete, error, timeout, user_cancel
{{files_modified}} List of modified files
{{hook_output}} Output from previous hooks

beforeToolCall Variables

Variable Description
{{tool_name}} Tool being called
{{tool_args}} Tool arguments object
{{tool_args.<param>}} Individual argument
{{tool_call_index}} Call number (1-indexed)

afterToolCall Variables

Variable Description
{{tool_name}} Tool that was called
{{tool_result}} Tool output
{{tool_error}} Error message if failed
{{tool_success}} Whether tool succeeded
{{tool_duration_ms}} Execution time

onError Variables

Variable Description
{{error_type}} tool_error, api_error, timeout, permission_denied
{{error_message}} Human-readable error
{{error_stack}} Stack trace if available
{{last_tool}} Last tool before error
{{recoverable}} Whether error is recoverable

Examples

Load Project Context

hooks:
  - name: load-context
    event: onStart
    action: script
    script: |
      cd ""
      echo "=== Project Structure ==="
      find . -type f -name "*.go" | head -20
      echo ""
      echo "=== Recent Commits ==="
      git log --oneline -5 2>/dev/null || echo "Not a git repo"
    captureOutput: true
    timeout: 10000

The captured output is available in the system prompt as {{hook_output}}.

Validate Dangerous Commands

hooks:
  - name: bash-guard
    event: beforeToolCall
    action: script
    filter:
      tools: [Bash]
    script: |
      CMD=''
      if echo "$CMD" | grep -qE 'rm\s+-rf\s+/|rm\s+-rf\s+~|mkfs'; then
        echo "BLOCKED: Destructive command pattern"
        exit 1
      fi
      exit 0
    onFailure: abort

Log Tool Usage

hooks:
  - name: tool-logger
    event: afterToolCall
    action: script
    script: |
      mkdir -p ~/.familiar/logs
      echo '{"ts":"","agent":"","tool":"","duration":,"success":}' \
        >> ~/.familiar/logs/tool-usage.jsonl
    blocking: false
    onFailure: ignore

Wrap-Up Agent

hooks:
  - name: session-wrap-up
    event: onStop
    action: agent
    agent: wrap-up
    prompt: |
      The session is ending.

      Session stats:
      - Duration: ms
      - Tool calls: 
      - Files modified: 

      Please:
      1. Check for uncommitted changes
      2. Verify tests pass if code was modified
      3. Update relevant documentation
    timeout: 120000

Error Notifications

hooks:
  - name: error-alert
    event: onError
    action: script
    script: |
      curl -X POST "https://hooks.slack.com/services/..." \
        -H "Content-Type: application/json" \
        -d '{"text": "Agent  error: "}'
    blocking: false
    onFailure: ignore

Execution Logs

Hook executions are logged for debugging:

Location: ~/Library/Application Support/com.usefamiliar.desktop/agents/<agent-name>/hook-logs/

Each log entry includes:

  • Hook name and event
  • Input context
  • Output or error
  • Execution duration
  • Spawned agent info (for agent actions)

Best Practices

Keep Hooks Fast

Long-running hooks slow down agents. Use reasonable timeouts:

hooks:
  - event: beforeToolCall
    timeout: 5000  # 5 seconds max

Use Non-Blocking for Logging

Logging shouldn't slow down execution:

hooks:
  - event: afterToolCall
    blocking: false  # Don't wait
    onFailure: ignore  # Don't fail on log errors

Filter Appropriately

Don't run hooks unnecessarily:

hooks:
  - event: beforeToolCall
    filter:
      tools: [Bash, Write]  # Only for risky tools

Capture Context on Start

Load project context once at startup:

hooks:
  - event: onStart
    captureOutput: true  # Available as 

Next Steps