How It Works
Hooks
How Team Hooks fit into team operations, delivery lifecycles, and compaction handling.
Team Hooks let you attach shell scripts to key team events so automation can run at the right time without changing gg source code.
Mental model
Think of Team Hooks as a thin, deterministic runtime:
- gg observes a canonical team event.
- gg resolves effective hooks (user + project config).
- Hooks run concurrently with JSON input over
stdin. - Hook outputs are aggregated in stable order.
- gg injects lifecycle context into target sessions and appends typed
system_noticetimeline rows.
Two properties matter most:
- Hooks do not replace core team operations; they augment them.
- Delivery-aware events wait for real message lifecycle completion.
What hooks are good for
Practical use cases:
- Pre-add teammate setup in the source session checkout before native worktree creation (
pre_teammate_add). - Post-add onboarding reminders and policy injection.
- Post-remove cleanup notices and audit signal.
- Delivery-aware follow-ups after direct/broadcast send success.
- Compaction recovery guidance when a member loses context.
Hooks are not worktree init
pre_teammate_add hooks and worktree init are separate runtime steps:
pre_teammate_addruns before native worktree creation in the source session cwd.- Worktree init runs after new native worktree creation in the new worktree cwd, using
.agents/gg/worktree-init.sh. - The Add Agent pre-hook checkbox controls hooks only; it does not disable worktree init.
For the worktree-init contract, see Configure: Worktree Init.
Delivery-aware automation
Message hooks are not queue-time hooks. They fire on delivery success semantics:
- Direct hooks fire only when direct delivery is fully injected.
- Broadcast hooks can still succeed if a recipient is removed mid-flight, as long as all still-eligible recipients are injected.
- Partial terminal failures do not fire message hooks.
This avoids false positives for workflows that depend on actual delivery completion.
Event applicability at runtime
Hook outputs apply per event as follows:
pre_teammate_add: after the new member session is created, injection can target the caller and explicit targets.agent_id="__new_member__"resolves to the spawned member session.post_teammate_add: applies to caller/targets from hook output after canonical member-add commit.post_teammate_remove: applies after canonical member-remove commit, but any injection targeting removed member session IDs is suppressed.post_direct_message_send: applies only on full direct-delivery success.post_broadcast_message_send: applies on full broadcast delivery, or terminal completion where every still-eligible (still-member) recipient is injected.post_compaction: baseline compaction guidance is emitted for resolved recipients; post-compaction hook injection can override recipient text/kind for those recipients.
Where config lives
Team Hooks resolve from:
~/.agents/gg/team-hooks.json(user)<session cwd>/.agents/gg/team-hooks.json(project)
Project hooks override user hooks on (event, normalized name) collisions.
Safety and failure boundaries
Failure policy is explicit:
pre_teammate_addis fail-closed and can block add-member operations.- All
post_*hooks are fail-open and do not roll back committed operations.
Compaction handling is resilient:
- If post-compaction hook resolution/execution fails, gg still sends baseline compaction notices.
Current v1 limits
Team Hooks v1 intentionally stays narrow:
- Shell commands only (no HTTP hook transport).
- One JSON-in / JSON-out contract version (
schema_version: 1). - No global “disable all hooks” toggle.
- Post teammate/message hooks are source-filtered to tool-originated agent operations (
agent_tool) to avoid automation recursion.
UI behavior to know
When pre-add hooks exist, the Add Agent dialog shows a checkbox:
- Checked (default): run pre hooks.
- Unchecked: skip pre hooks for that one quick-add action.
- This checkbox does not disable worktree init for create-new native worktree adds.
Lifecycle hook notices render as typed timeline system_notice rows (team_hook_*_notice kinds plus baseline team_member_compaction_notice).
Legacy non-transport wrapper parsing for team_hook_* envelopes is not a supported runtime path.
Next step
Use the full contract page for schema, merge rules, per-event payloads, and copy-paste examples: