Agentic AI Atlasby a5c.ai
OverviewWikiGraphFor AgentsEdgesSearchWorkspace
/
GitHubDocsDiscord
iiRecord
Agentic AI Atlas · Hooks: Extensible Lifecycle Events
page:docs-user-guide-features-hooksa5c.ai
Search record views/
Record · tabs

Available views

II.Record viewspp. 1 - 1
overviewarticlejsongraph
II.
Page JSON

page:docs-user-guide-features-hooks

Structured · live

Hooks: Extensible Lifecycle Events json

Inspect the normalized record payload exactly as the atlas UI reads it.

File · wiki/docs/user-guide/features/hooks.mdCluster · wiki
Record JSON
{
  "id": "page:docs-user-guide-features-hooks",
  "_kind": "Page",
  "_file": "wiki/docs/user-guide/features/hooks.md",
  "_cluster": "wiki",
  "attributes": {
    "nodeKind": "Page",
    "sourcePath": "docs/user-guide/features/hooks.md",
    "sourceKind": "repo-docs",
    "title": "Hooks: Extensible Lifecycle Events",
    "displayName": "Hooks: Extensible Lifecycle Events",
    "slug": "docs/user-guide/features/hooks",
    "articlePath": "wiki/docs/user-guide/features/hooks.md",
    "article": "\n# Hooks: Extensible Lifecycle Events\n\n**Version:** 1.1\n**Last Updated:** 2026-01-26\n**Category:** Feature Guide\n\n---\n\n## In Plain English\n\n**Hooks are automatic triggers that run your custom code at specific moments.**\n\nLike setting up an automatic notification: \"When the workflow finishes, send me a Slack message.\" That's a hook.\n\n**Common examples:**\n- 📧 Send an email when a run completes\n- 📊 Log metrics to your dashboard when quality is scored\n- 🔔 Get a desktop notification when approval is needed\n\n**Do you need hooks as a beginner?** No - they're an advanced feature for customizing behavior. You can use Babysitter perfectly well without ever writing a hook.\n\n---\n\n## Overview\n\nHooks are shell scripts that execute at specific lifecycle points during Babysitter orchestration. They enable custom behavior for task execution, notifications, logging, metrics collection, and third-party integrations without modifying core SDK code.\n\n### Why Use Hooks\n\n- **Notifications**: Send Slack, email, or desktop alerts when runs complete or fail\n- **Metrics Collection**: Capture timing, quality scores, and execution data for dashboards\n- **Custom Orchestration**: Implement specialized task execution logic (e.g., native Node.js execution)\n- **Audit Logging**: Write events to external systems for compliance and debugging\n- **Integration**: Connect Babysitter to CI/CD pipelines, monitoring systems, or team tools\n- **Session Control**: Manage Claude Code session behavior for continuous orchestration loops\n\n---\n\n## Hook Lifecycle Overview\n\nThe following diagram shows when each hook type fires during a Babysitter run:\n\n```\n                            SESSION LIFECYCLE\n    +==========================================================================+\n    |                                                                          |\n    |   SessionStart -----> [Claude Code Session Active] -----> Stop           |\n    |        |                                                    |            |\n    |        v                                                    v            |\n    |   Session setup,                                    Decision: allow      |\n    |   environment vars                                  exit or continue     |\n    |                                                                          |\n    +==========================================================================+\n\n                              RUN LIFECYCLE\n    +==========================================================================+\n    |                                                                          |\n    |   on-run-start -----> [Run Created]                                      |\n    |        |                                                                 |\n    |        v                                                                 |\n    |   post-planning -----> [Plan Generated]                                  |\n    |        |                                                                 |\n    |        v                                                                 |\n    |   +------------------------------------------------------------------+   |\n    |   |                    ORCHESTRATION LOOP                            |   |\n    |   |                                                                  |   |\n    |   |   on-iteration-start ---+                                        |   |\n    |   |         |               |                                        |   |\n    |   |         v               |                                        |   |\n    |   |   on-step-dispatch      |                                        |   |\n    |   |         |               |                                        |   |\n    |   |         v               |                                        |   |\n    |   |   on-task-start ------> [Task Executes] ------> on-task-complete |   |\n    |   |                               |                                  |   |\n    |   |                               v                                  |   |\n    |   |                         on-score (if quality task)               |   |\n    |   |                               |                                  |   |\n    |   |                               v                                  |   |\n    |   |                         on-breakpoint (if breakpoint)            |   |\n    |   |                               |                                  |   |\n    |   |                               v                                  |   |\n    |   |                       on-iteration-end ---+                      |   |\n    |   |                               |           |                      |   |\n    |   |                               +-----------+ (loop continues)     |   |\n    |   +------------------------------------------------------------------+   |\n    |                                   |                                      |\n    |                                   v                                      |\n    |   +--- on-run-complete <----[Success]                                    |\n    |   |                                                                      |\n    |   +--- on-run-fail <--------[Failure]                                    |\n    |                                                                          |\n    +==========================================================================+\n\n                            GIT LIFECYCLE\n    +==========================================================================+\n    |                                                                          |\n    |   pre-branch -----> [Branch Operation] -----> pre-commit                 |\n    |                                                                          |\n    +==========================================================================+\n```\n\n---\n\n## Available Hook Types\n\n### SDK Lifecycle Hooks\n\nThese hooks fire during the orchestration lifecycle managed by the Babysitter SDK.\n\n| Hook | Trigger | Purpose |\n|------|---------|---------|\n| `on-run-start` | Run creation | Initialize resources, set up monitoring |\n| `on-run-complete` | Successful completion | Cleanup, send success notifications |\n| `on-run-fail` | Run failure | Error alerts, debugging information |\n| `on-iteration-start` | Before each iteration | **Core orchestration logic**, effect execution |\n| `on-iteration-end` | After each iteration | Finalization, iteration logging |\n| `on-task-start` | Before task execution | Preparation, timing metrics |\n| `on-task-complete` | After task execution | Result processing, cleanup |\n| `on-breakpoint` | Breakpoint created | Notifications to reviewers |\n| `on-score` | Quality score computed | Metrics collection, dashboards |\n| `on-step-dispatch` | Step dispatch decision | Custom routing logic |\n| `post-planning` | After plan generation | Plan validation, notifications |\n| `pre-branch` | Before git branch operation | Branch naming, validation |\n| `pre-commit` | Before git commit | Linting, formatting, validation |\n\n### Claude Code Hooks\n\nThese hooks integrate with Claude Code's session management.\n\n| Hook | Trigger | Purpose |\n|------|---------|---------|\n| `SessionStart` | Session begins | Persist session ID, set environment variables |\n| `Stop` | Exit attempt | Implement in-session orchestration loops |\n| `PreToolUse` | Before tool call | Validation, logging |\n| `PostToolUse` | After tool call | Result logging, metrics |\n\n---\n\n## Hook Discovery and Priority\n\nHooks are discovered and executed in a specific priority order. All matching hooks in each location are executed.\n\n**Discovery Order (highest to lowest priority):**\n\n1. **Per-repo hooks:** `.a5c/hooks/<hook-type>/*.sh`\n2. **Per-user hooks:** `~/.config/babysitter/hooks/<hook-type>/*.sh`\n3. **Plugin hooks:** `plugins/babysitter-unified/hooks/<hook-type>.sh`\n\n**Execution Order:**\n\nWithin each location, hooks are executed in lexicographic (alphabetical) order by filename.\n\n```\n.a5c/hooks/on-run-complete/\n  01-metrics.sh       # Executes first\n  02-notify.sh        # Executes second\n  99-cleanup.sh       # Executes last\n```\n\n---\n\n## Hook Execution Model\n\n### Input/Output Protocol\n\n| Channel | Purpose | Notes |\n|---------|---------|-------|\n| **stdin** | JSON payload input | Contains event-specific data |\n| **stdout** | JSON result output | Must be valid JSON (or empty) |\n| **stderr** | Logging output | Not captured, visible in console |\n\n### Exit Codes\n\n| Exit Code | Meaning |\n|-----------|---------|\n| `0` | Success - hook completed normally |\n| Non-zero | Failure - logged but does not stop other hooks |\n\n**Important:** Hook failures are logged but do not stop the dispatcher from executing remaining hooks.\n\n---\n\n## Creating Custom Hooks\n\n### Step 1: Create Hook Directory\n\nChoose the appropriate location for your hook:\n\n```bash\n# Per-repo hook (version controlled, project-specific)\nmkdir -p .a5c/hooks/on-run-complete\n\n# Per-user hook (applies to all your projects)\nmkdir -p ~/.config/babysitter/hooks/on-run-complete\n```\n\n### Step 2: Create Hook Script\n\nCreate a shell script with the `.sh` extension:\n\n```bash\n#!/bin/bash\nset -euo pipefail\n\n# Read JSON payload from stdin\nPAYLOAD=$(cat)\n\n# Parse payload using jq\nRUN_ID=$(echo \"$PAYLOAD\" | jq -r '.runId')\nSTATUS=$(echo \"$PAYLOAD\" | jq -r '.status // \"unknown\"')\n\n# Log to stderr (visible in console)\necho \"[my-hook] Processing run: $RUN_ID\" >&2\n\n# Your custom logic here\n# ...\n\n# Return JSON result via stdout (must be valid JSON)\necho '{\"ok\": true, \"action\": \"processed\"}'\n```\n\n### Step 3: Make Executable\n\n```bash\nchmod +x .a5c/hooks/on-run-complete/my-hook.sh\n```\n\n### Step 4: Test Hook\n\nTest your hook manually by piping sample JSON:\n\n```bash\necho '{\"runId\": \"run-test-123\", \"status\": \"completed\"}' | \\\n  .a5c/hooks/on-run-complete/my-hook.sh\n```\n\n---\n\n## Hook Payloads and Environment Variables\n\n### Common Payload Fields\n\nMost SDK lifecycle hooks receive these fields:\n\n```json\n{\n  \"runId\": \"run-20260125-143012\",\n  \"timestamp\": \"2026-01-25T14:30:12.123Z\"\n}\n```\n\n### Hook-Specific Payloads\n\n#### on-iteration-start / on-iteration-end\n\n```json\n{\n  \"runId\": \"run-20260125-143012\",\n  \"iteration\": 3,\n  \"timestamp\": \"2026-01-25T14:35:00.000Z\"\n}\n```\n\n#### on-task-start / on-task-complete\n\n```json\n{\n  \"runId\": \"run-20260125-143012\",\n  \"effectId\": \"effect-01HJKMNPQR3STUVWXYZ\",\n  \"taskId\": \"build\",\n  \"kind\": \"node\",\n  \"label\": \"Build project\"\n}\n```\n\n#### on-breakpoint\n\n```json\n{\n  \"runId\": \"run-20260125-143012\",\n  \"question\": \"Approve the deployment?\",\n  \"title\": \"Production Deployment\",\n  \"context\": {\n    \"runId\": \"run-20260125-143012\",\n    \"files\": [\n      {\"path\": \"artifacts/plan.md\", \"format\": \"markdown\"}\n    ]\n  }\n}\n```\n\n#### on-run-complete / on-run-fail\n\n```json\n{\n  \"runId\": \"run-20260125-143012\",\n  \"status\": \"completed\",\n  \"duration\": 45000\n}\n```\n\n#### on-score\n\n```json\n{\n  \"runId\": \"run-20260125-143012\",\n  \"score\": 85,\n  \"target\": 90,\n  \"iteration\": 2\n}\n```\n\n### Environment Variables\n\nThese environment variables are available to hooks:\n\n| Variable | Description |\n|----------|-------------|\n| `HOOK_PAYLOAD` | The JSON payload (also available via stdin) |\n| `HOOK_TYPE` | The hook type being executed |\n| `REPO_ROOT` | Repository root directory |\n| `AGENT_SESSION_ID` | Cross-harness session identifier |\n| `CLAUDE_PLUGIN_ROOT` | Plugin installation directory |\n| `CLAUDE_ENV_FILE` | Path to session environment file |\n\n---\n\n## Example Use Cases\n\n### Example 1: Slack Notification on Run Complete\n\n**File:** `.a5c/hooks/on-run-complete/slack-notify.sh`\n\n```bash\n#!/bin/bash\nset -euo pipefail\n\nPAYLOAD=$(cat)\nRUN_ID=$(echo \"$PAYLOAD\" | jq -r '.runId')\nSTATUS=$(echo \"$PAYLOAD\" | jq -r '.status')\nDURATION=$(echo \"$PAYLOAD\" | jq -r '.duration')\n\n# Calculate duration in human-readable format\nDURATION_SEC=$((DURATION / 1000))\n\n# Send to Slack webhook\nif [[ -n \"${SLACK_WEBHOOK_URL:-}\" ]]; then\n  curl -s -X POST \"$SLACK_WEBHOOK_URL\" \\\n    -H \"Content-Type: application/json\" \\\n    -d \"{\n      \\\"text\\\": \\\"Babysitter Run Complete\\\",\n      \\\"attachments\\\": [{\n        \\\"color\\\": \\\"$([ \\\"$STATUS\\\" = \\\"completed\\\" ] && echo 'good' || echo 'danger')\\\",\n        \\\"fields\\\": [\n          {\\\"title\\\": \\\"Run ID\\\", \\\"value\\\": \\\"$RUN_ID\\\", \\\"short\\\": true},\n          {\\\"title\\\": \\\"Status\\\", \\\"value\\\": \\\"$STATUS\\\", \\\"short\\\": true},\n          {\\\"title\\\": \\\"Duration\\\", \\\"value\\\": \\\"${DURATION_SEC}s\\\", \\\"short\\\": true}\n        ]\n      }]\n    }\" >&2\nfi\n\necho '{\"ok\": true}'\n```\n\n### Example 2: Desktop Notification on Breakpoint\n\n**File:** `.a5c/hooks/on-breakpoint/desktop-notify.sh`\n\n```bash\n#!/bin/bash\nset -euo pipefail\n\nPAYLOAD=$(cat)\nTITLE=$(echo \"$PAYLOAD\" | jq -r '.title // \"Breakpoint\"')\nQUESTION=$(echo \"$PAYLOAD\" | jq -r '.question')\n\n# macOS notification\nif command -v osascript &>/dev/null; then\n  osascript -e \"display notification \\\"$QUESTION\\\" with title \\\"$TITLE\\\" sound name \\\"Glass\\\"\"\nfi\n\n# Linux notification\nif command -v notify-send &>/dev/null; then\n  notify-send \"$TITLE\" \"$QUESTION\" --urgency=critical\nfi\n\necho '{\"ok\": true}'\n```\n\n### Example 3: Metrics Collection\n\n**File:** `.a5c/hooks/on-score/metrics-collector.sh`\n\n```bash\n#!/bin/bash\nset -euo pipefail\n\nPAYLOAD=$(cat)\nRUN_ID=$(echo \"$PAYLOAD\" | jq -r '.runId')\nSCORE=$(echo \"$PAYLOAD\" | jq -r '.score')\nTARGET=$(echo \"$PAYLOAD\" | jq -r '.target')\nITERATION=$(echo \"$PAYLOAD\" | jq -r '.iteration')\n\n# Log to metrics file\nMETRICS_FILE=\"${HOME}/.babysitter/metrics.jsonl\"\nmkdir -p \"$(dirname \"$METRICS_FILE\")\"\n\njq -n --compact-output \\\n  --arg runId \"$RUN_ID\" \\\n  --argjson score \"$SCORE\" \\\n  --argjson target \"$TARGET\" \\\n  --argjson iteration \"$ITERATION\" \\\n  --arg timestamp \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\" \\\n  '{\n    timestamp: $timestamp,\n    runId: $runId,\n    score: $score,\n    target: $target,\n    iteration: $iteration,\n    gap: ($target - $score)\n  }' >> \"$METRICS_FILE\"\n\necho \"[metrics] Recorded score $SCORE/$TARGET for iteration $ITERATION\" >&2\necho '{\"ok\": true}'\n```\n\n### Example 4: Native Task Orchestration\n\nThe plugin includes a `native-orchestrator.sh` hook that automatically executes Node.js tasks:\n\n**File:** generated harness-specific runtime bundle under `artifacts/generated-plugins/<target>/hooks/`\n\nThis hook:\n1. Queries run status via CLI\n2. Identifies pending node tasks\n3. Executes them externally (up to 3 in parallel)\n4. Posts results back to the SDK\n\n```bash\n# Key excerpt - executes node tasks\n(cd \"$CWD_ABS\" && node \"$ENTRY_ABS\" \"${NODE_ARGS[@]}\") >\"$STDOUT_ABS\" 2>\"$STDERR_ABS\"\nEXIT_CODE=$?\n\nif [ \"$EXIT_CODE\" -eq 0 ]; then\n  \"${CLI[@]}\" task:post \"$RUN_ID\" \"$EFFECT_ID\" --status ok --value \"$OUTPUT_REF\"\nelse\n  \"${CLI[@]}\" task:post \"$RUN_ID\" \"$EFFECT_ID\" --status error --error - <<< '{\"message\":\"Task failed\"}'\nfi\n```\n\n### Example 5: In-Session Loop Control (Stop Hook)\n\nThe `babysitter-stop-hook.sh` implements continuous orchestration by intercepting exit attempts:\n\n```bash\n# Returns JSON to block exit and continue loop\njq -n \\\n  --arg prompt \"$PROMPT_TEXT\" \\\n  --arg msg \"Babysitter iteration $NEXT_ITERATION | Continue orchestration\" \\\n  '{\n    \"decision\": \"block\",\n    \"reason\": $prompt,\n    \"systemMessage\": $msg\n  }'\n```\n\n---\n\n## Hook Execution\n\nThe SDK discovers per-repo and per-user runtime hooks directly. Harness entrypoints in the maintained plugin source live under `plugins/babysitter-unified/hooks/*.sh` and invoke `babysitter hook:run` for harness-specific lifecycle hooks such as `session-start` and `stop`.\n\n### Example Dispatcher Output\n\n```\n[per-repo] Executing hooks from: .a5c/hooks/on-run-complete\n[per-repo] Running: 01-metrics.sh\n[per-repo] + 01-metrics.sh succeeded\n[per-user] Executing hooks from: /home/user/.config/babysitter/hooks/on-run-complete\n[per-user] Running: notify.sh\n[per-user] + notify.sh succeeded\n\nHook execution summary:\nper-repo:01-metrics.sh:success\nper-user:notify.sh:success\n```\n\n---\n\n## Configuration in hooks.json\n\nThe `hooks.json` file registers Claude Code hooks (SessionStart, Stop, PreToolUse, PostToolUse).\n\n**Location:** generated from `plugins/babysitter-unified/plugin.json`\n\n```json\n{\n  \"description\": \"Babysitter plugin hooks for orchestration loops\",\n  \"hooks\": {\n    \"SessionStart\": [\n      {\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"bash ${CLAUDE_PLUGIN_ROOT}/hooks/session-start.sh\"\n          }\n        ]\n      }\n    ],\n    \"Stop\": [\n      {\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"bash ${CLAUDE_PLUGIN_ROOT}/hooks/stop.sh\"\n          }\n        ]\n      }\n    ]\n  }\n}\n```\n\n---\n\n## Troubleshooting\n\n### Hook Not Executing\n\n**Symptom:** Custom hook is not being called.\n\n**Solutions:**\n\n1. **Verify file is executable:**\n   ```bash\n   ls -la .a5c/hooks/on-run-complete/my-hook.sh\n   # Should show: -rwxr-xr-x (x permission required)\n\n   chmod +x .a5c/hooks/on-run-complete/my-hook.sh\n   ```\n\n2. **Verify hook type directory name:**\n   ```bash\n   # Correct\n   .a5c/hooks/on-run-complete/\n\n   # Wrong\n   .a5c/hooks/on_run_complete/  # underscore instead of hyphen\n   ```\n\n3. **Check for syntax errors:**\n   ```bash\n   bash -n .a5c/hooks/on-run-complete/my-hook.sh\n   ```\n\n### Hook Failing Silently\n\n**Symptom:** Hook runs but produces no output or effect.\n\n**Solutions:**\n\n1. **Add verbose logging to stderr:**\n   ```bash\n   echo \"[my-hook] Starting...\" >&2\n   echo \"[my-hook] Payload: $PAYLOAD\" >&2\n   ```\n\n2. **Check jq parsing:**\n   ```bash\n   # Test jq command\n   echo '{\"runId\":\"test\"}' | jq -r '.runId'\n   ```\n\n3. **Verify external services are accessible:**\n   ```bash\n   # Test Slack webhook\n   curl -X POST \"$SLACK_WEBHOOK_URL\" -d '{\"text\":\"test\"}'\n   ```\n\n### Hook Breaking JSON Output\n\n**Symptom:** Error messages about invalid JSON.\n\n**Solutions:**\n\n1. **Ensure stdout only contains JSON:**\n   ```bash\n   # Wrong - prints to stdout\n   echo \"Processing...\"\n   echo '{\"ok\": true}'\n\n   # Correct - logging to stderr\n   echo \"Processing...\" >&2\n   echo '{\"ok\": true}'\n   ```\n\n2. **Validate JSON output:**\n   ```bash\n   # Test your hook's output\n   echo '{\"runId\":\"test\"}' | ./my-hook.sh | jq .\n   ```\n\n### Stop Hook Not Blocking Exit\n\n**Symptom:** Claude Code exits instead of continuing the loop.\n\n**Solutions:**\n\n1. **Verify state file exists:**\n   ```bash\n   ls -la ~/.a5c/state/\n   ```\n\n2. **Check stop hook output is valid JSON:**\n   ```bash\n   # Must include decision: \"block\" to prevent exit\n   {\"decision\": \"block\", \"reason\": \"...\", \"systemMessage\": \"...\"}\n   ```\n\n3. **Verify session ID is being passed:**\n   ```bash\n   babysitter session:whoami --json\n   ```\n\n---\n\n## Best Practices\n\n### Do\n\n- **Log to stderr** - Keep stdout clean for JSON output\n- **Use `set -euo pipefail`** - Fail fast on errors\n- **Parse JSON with jq** - Robust JSON handling\n- **Make hooks idempotent** - Safe to run multiple times\n- **Use meaningful exit codes** - 0 for success, non-zero for failure\n- **Prefix log messages** - `[hook-name]` for easy identification\n\n### Don't\n\n- **Don't block indefinitely** - Use timeouts for external calls\n- **Don't print non-JSON to stdout** - Breaks the output protocol\n- **Don't rely on working directory** - Use absolute paths\n- **Don't store secrets in scripts** - Use environment variables\n- **Don't skip error handling** - Validate inputs before processing\n\n---\n\n## Related Documentation\n\n- [Configuration Reference](../reference/configuration.md) - Hook configuration options\n- [Glossary](../reference/glossary.md) - Hook terminology definitions\n- [Process Definitions](./process-definitions.md) - Using hooks in processes\n- [Breakpoints](./breakpoints.md) - on-breakpoint hook integration\n- [Run Resumption](./run-resumption.md) - How hooks interact with resumption\n- [Best Practices](./best-practices.md) - Patterns for workflow design and team collaboration\n\n---\n\n## Summary\n\nHooks provide a powerful extension mechanism for customizing Babysitter behavior at every lifecycle stage. Use SDK lifecycle hooks for run orchestration, notifications, and metrics. Use Claude Code hooks for session management and continuous orchestration loops. Follow the input/output protocol (stdin JSON, stdout JSON, stderr logging) and ensure scripts are executable. Place hooks in per-repo, per-user, or plugin directories based on your needs.\n",
    "documents": []
  },
  "outgoingEdges": [],
  "incomingEdges": [
    {
      "from": "page:docs-user-guide-features",
      "to": "page:docs-user-guide-features-hooks",
      "kind": "contains_page"
    }
  ]
}

Shortcuts

Back to overview
Open graph tab