Skip to main content

Enlace de uso posterior a la herramienta

Use el onPostToolUse gancho para transformar los resultados de la herramienta, registrar la ejecución de la herramienta y agregar contexto después de que se ejecute una herramienta en SDK de Copilot.

¿Quién puede utilizar esta característica?

SDK de GitHub Copilot está disponible con todos los Copilot planes.

Nota:

SDK de Copilot actualmente está en Versión preliminar técnica. La funcionalidad y la disponibilidad están sujetas a cambios.

Al onPostToolUse enlace se le llama después de que se ejecute una herramienta. Utilícelo para:

  • Resultados de la herramienta de transformación o filtro
  • Ejecución de la herramienta de registro para la auditoría
  • Agregar contexto basado en los resultados
  • Ocultar los resultados de la conversación

Firma de hook

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

Para obtener firmas de enlace en Python, Go y .NET, consulte el github/copilot-sdk repositorio.

Entrada

CampoTipoDescripción
timestampnúmeroMarca de tiempo de Unix cuando se desencadenó el enlace
cwdcuerda / cadenaDirectorio de trabajo actual
toolNamecuerda / cadenaNombre de la herramienta llamada
toolArgsobjetoArgumentos que se pasaron a la herramienta
toolResultobjetoResultado devuelto por la herramienta

Salida

Devuelve null o undefined para pasar el resultado sin cambios. De lo contrario, devuelve un objeto con cualquiera de los campos siguientes.

CampoTipoDescripción
modifiedResultobjetoResultado modificado que se va a usar en lugar de original
additionalContextcuerda / cadenaContexto adicional insertado en la conversación
suppressOutputbooleanSi es verdadero, el resultado no aparecerá en la conversación.

Ejemplos

Registrar todos los resultados de la herramienta

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 obtener ejemplos en Python, Go y .NET, consulte el github/copilot-sdk repositorio.

Redactar datos sensibles

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

Agregar contexto basado en los 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 seguimientos de pila de errores

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

Seguimiento de auditoría para el cumplimiento

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

procedimientos recomendados

  •         **Devuelve `null` cuando no se necesitan cambios.** Esto es más eficaz que devolver un objeto vacío o el mismo resultado.
    
  •         **Tenga cuidado con la modificación de resultados.** Cambiar los resultados puede afectar a la forma en que el modelo interpreta la salida de la herramienta. Modifique solo cuando sea necesario.
    
  •         **Use `additionalContext` para sugerencias.** En lugar de modificar los resultados, agregue contexto para ayudar al modelo a interpretarlos.
    
  •         **Tenga en cuenta la privacidad al registrar.** Los resultados de la herramienta pueden contener datos confidenciales. Aplique la redacción antes de registrar.
    
  •         **Mantenga los ganchos seguros.** Los ganchos de la herramienta se ejecutan sincrónicamente. El procesamiento intensivo debe realizarse de forma asincrónica o por lotes.
    

Lectura 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)