Skip to main content

Gancho de uso pós-ferramenta

Use o onPostToolUse gancho para transformar os resultados da ferramenta, registrar a execução da ferramenta e adicionar contexto após a execução em SDK do Copilot.

Quem pode usar esse recurso?

SDK do GitHub Copilot está disponível com todos os Copilot planos.

Observação

SDK do Copilot está atualmente em versão prévia técnica. A funcionalidade e a disponibilidade estão sujeitas a alterações.

O onPostToolUse gancho é chamado após a execução de uma ferramenta. Use-o para:

  • Transformar ou filtrar resultados da ferramenta
  • Registro da execução da ferramenta para auditoria
  • Adicionar contexto com base nos resultados
  • Suprimir resultados da conversa

Assinatura do gancho

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

Para obter assinaturas de gancho em Python, Go e .NET, consulte o github/copilot-sdk repositório.

Entrada

CampoTipoDescrição
timestampnúmeroTimestamp Unix quando o hook foi acionado
cwdcadeiaDiretório de trabalho atual
toolNamecadeiaNome da ferramenta que foi chamada
toolArgsobjetoArgumentos que foram passados para a ferramenta
toolResultobjetoResultado retornado pela ferramenta

Saída

Retorne null ou undefined para passar o resultado inalterado. Caso contrário, retorne um objeto com qualquer um dos campos a seguir.

CampoTipoDescrição
modifiedResultobjetoResultado modificado a ser usado em vez de original
additionalContextcadeiaContexto extra injetado na conversa
suppressOutputbooleanSe verdadeiro, o resultado não aparecerá na conversa

Exemplos

Registrar todos os resultados da ferramenta

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
    },
  },
});

Para obter exemplos em Python, Go e .NET, consulte o github/copilot-sdk repositório.

Redigir dados confidenciais

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;
    },
  },
});

Truncar resultados grandes

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;
    },
  },
});

Adicionar contexto com base nos resultados

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;
    },
  },
});

Filtrar rastreamentos de pilha de erros

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;
    },
  },
});

Trilha de auditoria para conformidade

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;
    },
  },
});

Suprimir resultados ruidosos

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;
    },
  },
});

Práticas recomendadas

  •         **Retorne `null` quando nenhuma alteração for necessária.** Isso é mais eficiente do que retornar um objeto vazio ou o mesmo resultado.
    
  •         **Tenha cuidado com a modificação do resultado.** A alteração dos resultados pode afetar a forma como o modelo interpreta a saída da ferramenta. Somente modifique quando necessário.
    
  •         **Use `additionalContext` para dicas.** Em vez de modificar os resultados, adicione contexto para ajudar o modelo a interpretá-los.
    
  •         **Considere a privacidade ao fazer registros.** Os resultados da ferramenta podem conter dados confidenciais. Aplique a edição antes do log.
    
  •         **Mantenha os ganchos fixos.** Os ganchos pós-ferramenta são executados de forma síncrona. O processamento pesado deve ser feito de forma assíncrona ou em lote.
    

Leitura adicional

  •         [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)