Skip to main content

Hook exécuté avant l’utilisation d’un outil

Utilisez le hook onPreToolUse pour contrôler l’exécution de l’outil, modifier les arguments et ajouter du contexte avant l’exécution d’un outil Kit de développement logiciel (SDK) Copilot.

Qui peut utiliser cette fonctionnalité ?

SDK GitHub Copilot est disponible dans tous les forfaits Copilot.

Remarque

Kit de développement logiciel (SDK) Copilot est actuellement en préversion technique. Les fonctionnalités et la disponibilité sont susceptibles de changer.

Le onPreToolUse hook est appelé avant l’exécution d’un outil. Utilisez-le pour :

  • Approuver ou refuser l’exécution de l’outil
  • Modifier les arguments de l’outil
  • Ajouter un contexte pour l’outil
  • Supprimer la sortie de l’outil de la conversation

Signature de point d'interception

import type { PreToolUseHookInput, HookInvocation, PreToolUseHookOutput } from "@github/copilot-sdk";
type PreToolUseHandler = (
  input: PreToolUseHookInput,
  invocation: HookInvocation
) => Promise<PreToolUseHookOutput | null | undefined>;

Pour obtenir les signatures de hook dans Python, Go et .NET, consultez le github/copilot-sdk référentiel.

Input

ChampTypeDescription
timestampnombreHorodatage Unix lorsque le hook a été déclenché
cwdficelleRépertoire de travail actuel
toolNameficelleNom de l’outil appelé
toolArgsobjetArguments passés à l’outil

Sortie

Retournez null ou undefined autorisez l’outil à s’exécuter sans aucune modification. Sinon, retournez un objet avec l’un des champs suivants.

ChampTypeDescription
permissionDecision
          `"allow"`
          \|
          `"deny"`
          \|
          `"ask"`
         | Si l’on doit autoriser l’appel de l’outil |

| permissionDecisionReason | ficelle | Explication présentée à l’utilisateur (pour refuser/demander) | | modifiedArgs | objet | Arguments modifiés pour passer à l’outil | | additionalContext | ficelle | Contexte supplémentaire injecté dans la conversation | | suppressOutput | booléen | Si c'est vrai, la sortie de l’outil n’apparaît pas dans la conversation |

Décisions d’autorisation

DécisionComportement
"allow"L’outil s’exécute normalement
"deny"L’outil est bloqué, raison indiquée à l’utilisateur
"ask"L’utilisateur est invité à approuver (mode interactif)

Exemples

Autoriser tous les outils (journalisation uniquement)

const session = await client.createSession({
  hooks: {
    onPreToolUse: async (input, invocation) => {
      console.log(
        `[${invocation.sessionId}] `
        + `Calling ${input.toolName}`
      );
      console.log(
        `  Args: ${JSON.stringify(input.toolArgs)}`
      );
      return { permissionDecision: "allow" };
    },
  },
});

Pour obtenir des exemples dans Python, Go et .NET, consultez le github/copilot-sdk référentiel.

Bloquer des outils spécifiques

const BLOCKED_TOOLS = [
  "shell", "bash", "write_file", "delete_file",
];

const session = await client.createSession({
  hooks: {
    onPreToolUse: async (input) => {
      if (BLOCKED_TOOLS.includes(input.toolName)) {
        return {
          permissionDecision: "deny",
          permissionDecisionReason:
            `Tool '${input.toolName}' `
            + `is not permitted in this environment`,
        };
      }
      return { permissionDecision: "allow" };
    },
  },
});

Modifier les arguments de l’outil

const session = await client.createSession({
  hooks: {
    onPreToolUse: async (input) => {
      // Add a default timeout to all shell commands
      if (
        input.toolName === "shell" && input.toolArgs
      ) {
        const args = input.toolArgs as {
          command: string;
          timeout?: number;
        };
        return {
          permissionDecision: "allow",
          modifiedArgs: {
            ...args,
            timeout: args.timeout ?? 30000,
          },
        };
      }
      return { permissionDecision: "allow" };
    },
  },
});

Restreindre l’accès aux fichiers à des répertoires spécifiques

const ALLOWED_DIRECTORIES = [
  "/home/user/projects", "/tmp",
];

const session = await client.createSession({
  hooks: {
    onPreToolUse: async (input) => {
      if (
        input.toolName === "read_file"
        || input.toolName === "write_file"
      ) {
        const args = input.toolArgs as {
          path: string;
        };
        const isAllowed =
          ALLOWED_DIRECTORIES.some((dir) =>
            args.path.startsWith(dir)
          );

        if (!isAllowed) {
          return {
            permissionDecision: "deny",
            permissionDecisionReason:
              `Access to '${args.path}' `
              + `is not permitted. `
              + `Allowed directories: `
              + ALLOWED_DIRECTORIES.join(", "),
          };
        }
      }
      return { permissionDecision: "allow" };
    },
  },
});

Réduire la sortie verbeuse de l’outil

const VERBOSE_TOOLS = ["list_directory", "search_files"];

const session = await client.createSession({
  hooks: {
    onPreToolUse: async (input) => {
      return {
        permissionDecision: "allow",
        suppressOutput: VERBOSE_TOOLS.includes(input.toolName),
      };
    },
  },
});

Ajouter un contexte basé sur l’outil

const session = await client.createSession({
  hooks: {
    onPreToolUse: async (input) => {
      if (input.toolName === "query_database") {
        return {
          permissionDecision: "allow",
          additionalContext:
            "Remember: This database uses "
            + "PostgreSQL syntax. "
            + "Always use parameterized queries.",
        };
      }
      return { permissionDecision: "allow" };
    },
  },
});

Bonnes pratiques

  •         **Retournez toujours une décision.** Le retour de `null` autorise l'outil, mais il est plus clair d'être explicite avec `{ permissionDecision: "allow" }`.
    
  •         **Fournissez des raisons de déni utiles.** Lorsque vous refusez, expliquez pourquoi les utilisateurs comprennent ce qui s’est passé.
    
  •         **Soyez prudent avec la modification de l’argument.** Vérifiez que les arguments modifiés conservent le schéma attendu pour l’outil.
    
  •         **Tenez compte des performances.** Les hooks pré-exécution s’exécutent de manière synchrone avant chaque appel à un outil. Gardez-les rapidement.
    
  •         **Utilisez `suppressOutput` judicieusement.** La suppression de la sortie signifie que le modèle ne verra pas le résultat, ce qui peut affecter la qualité de la conversation.
    
  •         **Tenez compte des données sensibles.** Les arguments et résultats de l’outil peuvent contenir des secrets, des chemins d’accès de fichier ou des informations d’identification personnelle. Évitez de journaliser ou d’exposer ces données dans des environnements de production.
    

Lectures complémentaires

  •         [AUTOTITLE](/copilot/how-tos/copilot-sdk/use-hooks/quickstart)
    
  •         [AUTOTITLE](/copilot/how-tos/copilot-sdk/use-hooks/post-tool-use)
    
  •         [AUTOTITLE](/copilot/how-tos/copilot-sdk/use-hooks/error-handling)