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.
- 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.
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.
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)
(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.
- 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.
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.

