Skip to main content

사전 도구 사용 후크

onPreToolUse 후크를 사용하여 도구 실행을 제어하고, 인수를 수정하고, 도구가 실행코필로트 SDK되기 전에 컨텍스트를 추가합니다.

누가 이 기능을 사용할 수 있나요?

GitHub Copilot SDK 는 모든 Copilot 계획에서 사용할 수 있습니다.

참고

코필로트 SDK가 현재 공개 미리 보기에 있습니다. 기능 및 가용성은 변경될 수 있습니다.

onPreToolUse 도구가 실행되기 전에 후크가 호출됩니다. 이를 사용하여 다음을 수행합니다.

  • 도구 실행 승인 또는 거부
  • 도구 인수 수정
  • 도구에 대한 컨텍스트 추가
  • 대화에서 도구 출력 표시 안 함

후크 서명

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

Python, Go 및 .NET의 후크 서명은 리포지토리를github/copilot-sdk 참조하세요. Java의 경우 리포지토리를github/copilot-sdk-java 참조하세요.

입력

분야유형설명
timestamp숫자후크가 트리거될 때의 Unix 타임스탬프
cwd문자열현재 작업 디렉터리
toolName문자열호출되는 도구의 이름
toolArgs객체도구에 전달된 인수

출력

null 또는 undefined을(를) 반환하여 변경 없이 도구를 실행할 수 있도록 합니다. 그렇지 않으면 다음 필드 중 하나가 있는 객체를 반환합니다.

분야유형설명
permissionDecision
"allow"
|
"deny"
|
"ask"
도구 호출을 허용할지 여부
permissionDecisionReason문자열사용자에게 표시되는 설명(거부/요청)
modifiedArgs객체도구에 전달할 수정된 인수
additionalContext문자열대화에 삽입된 추가 컨텍스트
suppressOutput부울true이면 도구 출력이 대화에 표시되지 않습니다.

권한 결정

의사 결정작동 방식
"allow"도구가 정상적으로 실행됩니다.
"deny"도구가 차단되었습니다. 이유가 사용자에게 표시됨
"ask"승인하라는 메시지가 사용자에게 표시됩니다(대화형 모드)

예제

모든 도구 허용(로깅에만 해당)

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

Python, Go 및 .NET의 예제는 리포지토리를github/copilot-sdk 참조하세요. Java의 경우 리포지토리를github/copilot-sdk-java 참조하세요.

특정 도구 차단

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

도구 인수 수정

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

특정 디렉터리에 대한 파일 액세스 제한

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

도구의 장황한 출력 억제

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

도구 기반 컨텍스트 추가

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

모범 사례

  • 항상 결정을 반환합니다. null(을)를 반환하면 도구가 허용되지만, { permissionDecision: "allow" }을 명시하는 것이 더 명확합니다.
  • 유용한 거부 이유를 제공합니다. 거부할 때 사용자가 발생한 일을 이해하는 이유를 설명합니다.
  • 인수 수정에 주의하세요. 수정된 인수가 도구에 필요한 스키마를 유지하도록 합니다.
  • 성능을 고려합니다. 사전 도구 후크는 각 도구 호출 전에 동기적으로 실행됩니다. 계속 빠르게 처리하세요.
  • 신중하게 사용합니다 suppressOutput . 출력을 억제하면 모델이 결과를 볼 수 없으므로 대화 품질에 영향을 줄 수 있습니다.
  • 중요한 데이터를 염두에 두어야 합니다. 도구 인수 및 결과에는 비밀, 파일 경로 또는 개인 식별 정보가 포함될 수 있습니다. 프로덕션 환경에서 이 데이터를 로깅하거나 노출하지 마세요.

추가 읽기