Skip to main content

Hook für die Verwendung des Tools nach der Sitzung

Verwenden Sie den onPostToolUse Hook, um Toolergebnisse zu transformieren, die Ausführung von Tools zu protokollieren und Kontext hinzuzufügen, nachdem ein Tool in Copilot SDK ausgeführt wird.

Wer kann dieses Feature verwenden?

GitHub Copilot SDK ist mit allen Copilot Tarifen verfügbar.

Hinweis

Copilot SDK ist zurzeit in Technische Preview. Funktionalität und Verfügbarkeit können geändert werden.

Der onPostToolUse Hook wird aufgerufen, nachdem ein Tool ausgeführt wird. Verwenden Sie es zu folgenden Zwecken:

  • Transformieren oder Filtern von Toolergebnissen
  • Protokollierung der Toolausführung für die Auditierung
  • Hinzufügen von Kontext basierend auf Ergebnissen
  • Unterdrücken von Ergebnissen aus der Unterhaltung

Hook-Signatur

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

Die Hook-Signaturen in Python, Go und .NET finden Sie im github/copilot-sdk Repository.

Eingabe

FeldTypBeschreibung
timestampZahlUnix-Zeitstempel, zu dem der Hook ausgelöst wurde
cwdSchnurAktuelles Arbeitsverzeichnis
toolNameSchnurName des Tools, das aufgerufen wurde
toolArgsObjektArgumente, die an das Tool übergeben wurden
toolResultObjektVom Tool zurückgegebenes Ergebnis

Output

Geben Sie null oder undefined zurück, um das Ergebnis unverändert zu lassen. Geben Sie andernfalls ein Objekt mit einem der folgenden Felder zurück.

FeldTypBeschreibung
modifiedResultObjektGeändertes Ergebnis, das anstelle des Originals verwendet werden soll
additionalContextSchnurZusätzlicher Kontext, der in die Unterhaltung eingefügt wurde
suppressOutputbooleanWenn wahr, wird das Ergebnis nicht in den Konversationen angezeigt.

Beispiele

Protokollieren aller Toolergebnisse

const session = await client.createSession({
  hooks: {
    onPostToolUse: async (input, invocation) => {
      console.log(
        `[${invocation.sessionId}] `
        + `Tool: ${input.toolName}`
      );
      console.log(
        `  Args: ${JSON.stringify(input.toolArgs)}`
      );
      console.log(
        `  Result: `
        + `${JSON.stringify(input.toolResult)}`
      );
      return null; // Pass through unchanged
    },
  },
});

Beispiele in Python, Go und .NET finden Sie im github/copilot-sdk Repository.

Vertrauliche Daten unkenntlich machen

const SENSITIVE_PATTERNS = [
  /api[_-]?key["\s:=]+["']?[\w-]+["']?/gi,
  /password["\s:=]+["']?[\w-]+["']?/gi,
  /secret["\s:=]+["']?[\w-]+["']?/gi,
];

const session = await client.createSession({
  hooks: {
    onPostToolUse: async (input) => {
      if (typeof input.toolResult === "string") {
        let redacted = input.toolResult;
        for (const pattern of SENSITIVE_PATTERNS) {
          redacted = redacted.replace(
            pattern, "[REDACTED]"
          );
        }

        if (redacted !== input.toolResult) {
          return { modifiedResult: redacted };
        }
      }
      return null;
    },
  },
});

Abschneiden großer Ergebnisse

const MAX_RESULT_LENGTH = 10000;

const session = await client.createSession({
  hooks: {
    onPostToolUse: async (input) => {
      const resultStr =
        JSON.stringify(input.toolResult);

      if (resultStr.length > MAX_RESULT_LENGTH) {
        return {
          modifiedResult: {
            truncated: true,
            originalLength: resultStr.length,
            content:
              resultStr.substring(
                0, MAX_RESULT_LENGTH
              ) + "...",
          },
          additionalContext:
            `Note: Result was truncated from `
            + `${resultStr.length} to `
            + `${MAX_RESULT_LENGTH} characters.`,
        };
      }
      return null;
    },
  },
});

Hinzufügen von Kontext basierend auf Ergebnissen

const session = await client.createSession({
  hooks: {
    onPostToolUse: async (input) => {
      // If a file read returned an error,
      // add helpful context
      if (
        input.toolName === "read_file"
        && input.toolResult?.error
      ) {
        return {
          additionalContext:
            "Tip: If the file doesn't exist, "
            + "consider creating it or "
            + "checking the path.",
        };
      }

      // If shell command failed,
      // add debugging hint
      if (
        input.toolName === "shell"
        && input.toolResult?.exitCode !== 0
      ) {
        return {
          additionalContext:
            "The command failed. Check if "
            + "required dependencies are installed.",
        };
      }

      return null;
    },
  },
});

Fehler-Stack-Traces filtern

const session = await client.createSession({
  hooks: {
    onPostToolUse: async (input) => {
      if (input.toolResult?.error && input.toolResult?.stack) {
        // Remove internal stack trace details
        return {
          modifiedResult: {
            error: input.toolResult.error,
            // Keep only first 3 lines of stack
            stack: input.toolResult.stack.split("\n").slice(0, 3).join("\n"),
          },
        };
      }
      return null;
    },
  },
});

Prüfpfad für Compliance

interface AuditEntry {
  timestamp: number;
  sessionId: string;
  toolName: string;
  args: unknown;
  result: unknown;
  success: boolean;
}

const auditLog: AuditEntry[] = [];

const session = await client.createSession({
  hooks: {
    onPostToolUse: async (input, invocation) => {
      auditLog.push({
        timestamp: input.timestamp,
        sessionId: invocation.sessionId,
        toolName: input.toolName,
        args: input.toolArgs,
        result: input.toolResult,
        success: !input.toolResult?.error,
      });

      // Optionally persist to database/file
      await saveAuditLog(auditLog);

      return null;
    },
  },
});

Unterdrücken von lauten Ergebnissen

const NOISY_TOOLS = ["list_directory", "search_codebase"];

const session = await client.createSession({
  hooks: {
    onPostToolUse: async (input) => {
      if (NOISY_TOOLS.includes(input.toolName)) {
        // Summarize instead of showing full result
        const items = Array.isArray(input.toolResult) 
          ? input.toolResult 
          : input.toolResult?.items || [];
        
        return {
          modifiedResult: {
            summary: `Found ${items.length} items`,
            firstFew: items.slice(0, 5),
          },
        };
      }
      return null;
    },
  },
});

Bewährte Methoden

  •         **Zurückgeben `null` , wenn keine Änderungen erforderlich sind.** Dies ist effizienter als das Zurückgeben eines leeren Objekts oder desselben Ergebnisses.
    
  •         **Achten Sie bei der Ergebnisänderung darauf.** Das Ändern von Ergebnissen kann sich darauf auswirken, wie das Modell die Toolausgabe interpretiert. Ändern Sie nur bei Bedarf.
    
  •         **Verwenden Sie `additionalContext` für Hinweise.** Anstatt Ergebnisse zu ändern, fügen Sie Kontext hinzu, um dem Modell zu helfen, sie zu interpretieren.
    
  •         **Berücksichtigen Sie den Datenschutz bei der Protokollierung.** Toolergebnisse können vertrauliche Daten enthalten. Wenden Sie vor der Protokollierung Redaction an.
    
  •         **Halten Sie Haken fest.** Post-Tool-Hooks werden synchron ausgeführt. Schwere Verarbeitung sollte asynchron oder batchweise durchgeführt werden.
    

Weiterführende Lektüre

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