Skip to main content

Session hooks

With hooks, you can insert logic at each stage of a Copilot session lifecycle. You can add tool execution control, audit logging, prompt enrichment, and error handling without changing core implementation. This is separate from the declarative hooks in custom agent definitions and from file-based hook loading. For per-agent configuration, see Custom agents.

File-based hook discovery

hookDirectories lets you specify explicit roots for discovering file-based hooks. This is for discovery only and does not grant the agent general file access permissions. Explicit roots remain available even when enableConfigDiscovery or enableFileHooks is disabled. Relative paths are resolved once, against the effective workingDirectory at the time they are specified.
  • Omitted or null: other discovery sources are left unchanged
  • []: clears only the explicit SDK roots
Hook source disable settings and Managed Settings still apply. enableFileHooks controls repository-sourced file hooks (.github/hooks/ and roots from trusted repository settings). It does not disable explicit hookDirectories or PHP callback hooks.

Hook flow

Basic usage

Available hooks

Returning null keeps default behavior.

Blocking prompts

onUserPromptSubmitted can reject a prompt by returning decision: 'block'. When a prompt is rejected, no model turn starts and the user message is not recorded. If you specify reason, it is included in a transient session.warning event with warningType: "policy_blocked".

Typical use cases

1) Permission control

  • Use onPreToolUse with allow-list policies.
  • Require human approval for destructive actions with permissionDecision: 'ask'.
  • Use permissionDecisionReason for explicit denial reasons.
  • See Tools for tool name candidates such as view, glob, and bash.

2) Auditing and compliance

  • Combine lifecycle hooks to collect audit events.
  • Persist collected records by session ID.

3) Prompt enrichment

  • Add project context in onSessionStart (language, framework, conventions).
  • Expand shortcuts such as /fix and /test in onUserPromptSubmitted.

4) Result filtering

  • Mask API keys, tokens, and passwords in onPostToolUse.
  • Summarize oversized results and return details only when needed.

5) Error recovery

  • Retry only when errorContext is model_call and recoverable=true.
  • Provide concise user notifications for non-recoverable paths.

6) Session metrics

  • Record start time in onSessionStart.
  • Update counters in onPreToolUse and onUserPromptSubmitted.
  • Emit duration, tool counts, and termination reason in onSessionEnd.

Hook input and output types

Common input (BaseHookInput)

agentId / agentType / parentAgentId are available on hooks where a subagent is the actor. They are not included in root agent hooks. Older runtimes omit the fields entirely when the information is unavailable. As a result, any of them can be null.

PreToolUseHookInput

PreToolUseHookOutput

PostToolUseHookInput

PostToolUseHookOutput

UserPromptSubmittedHookInput

UserPromptSubmittedHookOutput

SessionStartHookInput

SessionStartHookOutput

SessionEndHookInput

SessionEndHookOutput

ErrorOccurredHookInput

ErrorOccurredHookOutput

ToolResultObject

Standard object for tool execution results.

Best practices

  1. Avoid heavy sync work inside hooks. Offload when needed.
  2. Return null when no customization is required.
  3. Make permissionDecision explicit whenever possible.
  4. Do not over-suppress critical errors. Keep logs and notifications.
  5. Manage session state by session ID and clean up in onSessionEnd.
For the latest updates, see the GitHub repository.
Last modified on October 19, 2026