Skip to main content

Session hooks

Hooks allow you to intercept and customize the behavior of Copilot sessions at key points in the conversation lifecycle. Use hooks to:

  • Control tool execution - approve, deny, or modify tool calls
  • Transform results - modify tool outputs before they're processed
  • Add context - inject additional information at session start
  • Handle errors - implement custom error handling
  • Audit and log - track all interactions for compliance

Available hooks

HookTriggerUse Case
Pre-tool use hookBefore a tool executesPermission control, argument validation
Post-tool use hookAfter a tool executes (success only)Result transformation, logging
Post-tool use hookAfter a tool execution whose result was a failureInject retry guidance, log failures
User prompt submitted hookWhen user sends a messagePrompt modification, filtering
Session lifecycle hooksSession beginsAdd context, configure session
Session lifecycle hooksSession endsCleanup, analytics
Error handling hookError happensCustom error handling

Quick start

Code languages navigation

TypeScript
import { CopilotClient } from "@github/copilot-sdk";

const client = new CopilotClient();

const session = await client.createSession({
  hooks: {
    onPreToolUse: async (input) => {
      console.log(`Tool called: ${input.toolName}`);
      // Allow all tools
      return { permissionDecision: "allow" };
    },
    onPostToolUse: async (input) => {
      console.log(`Tool result: ${JSON.stringify(input.toolResult)}`);
      return null; // No modifications
    },
    onSessionStart: async (input) => {
      return { additionalContext: "User prefers concise answers." };
    },
  },
});

Hook invocation context

Every hook receives an invocation parameter with context about the current session:

FieldTypeDescription
sessionIdstringThe ID of the current session

This allows hooks to maintain state or perform session-specific logic.

Common patterns

Logging all tool calls

const session = await client.createSession({
  hooks: {
    onPreToolUse: async (input) => {
      console.log(`[${new Date().toISOString()}] Tool: ${input.toolName}, Args: ${JSON.stringify(input.toolArgs)}`);
      return { permissionDecision: "allow" };
    },
    onPostToolUse: async (input) => {
      console.log(`[${new Date().toISOString()}] Result: ${JSON.stringify(input.toolResult)}`);
      return null;
    },
  },
});

Blocking dangerous tools

const BLOCKED_TOOLS = ["shell", "bash", "exec"];

const session = await client.createSession({
  hooks: {
    onPreToolUse: async (input) => {
      if (BLOCKED_TOOLS.includes(input.toolName)) {
        return {
          permissionDecision: "deny",
          permissionDecisionReason: "Shell access is not permitted",
        };
      }
      return { permissionDecision: "allow" };
    },
  },
});

Adding user context

const session = await client.createSession({
  hooks: {
    onSessionStart: async () => {
      const userPrefs = await loadUserPreferences();
      return {
        additionalContext: `User preferences: ${JSON.stringify(userPrefs)}`,
      };
    },
  },
});

Hook guides

See also