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 참조하세요.

입력

분야유형설명
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 참조하세요.

특정 도구 차단

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` .** 출력을 억제하면 모델이 결과를 볼 수 없으므로 대화 품질에 영향을 줄 수 있습니다.
    
  •         **중요한 데이터를 염두에 두어야 합니다.** 도구 인수 및 결과에는 비밀, 파일 경로 또는 개인 식별 정보가 포함될 수 있습니다. 프로덕션 환경에서 이 데이터를 로깅하거나 노출하지 마세요.
    

추가 읽기

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