Claude Agent SDK는 애플리케이션에서 Claude가 도구를 사용하는 방식을 관리할 수 있는 강력한 권한 제어 기능을 제공합니다.
이 가이드에서는 canUseTool 콜백, 훅 및 settings.json 권한 규칙을 사용하여 권한 시스템을 구현하는 방법을 다룹니다. 전체 API 문서는 TypeScript SDK 참조를 참조하세요.
Claude Agent SDK는 도구 사용을 제어하는 네 가지 상호 보완적인 방법을 제공합니다:
각 접근 방식의 사용 사례:
canUseTool - 다루지 않은 경우에 대한 동적 승인, 사용자에게 권한 요청처리 순서: PreToolUse Hook → Deny Rules → Allow Rules → Ask Rules → Permission Mode Check → canUseTool Callback → PostToolUse Hook
권한 모드는 Claude가 도구를 사용하는 방식에 대한 전역 제어를 제공합니다. query()를 호출할 때 권한 모드를 설정하거나 스트리밍 세션 중에 동적으로 변경할 수 있습니다.
SDK는 각각 다른 동작을 가진 네 가지 권한 모드를 지원합니다:
| 모드 | 설명 | 도구 동작 |
|---|---|---|
default | 표준 권한 동작 | 일반 권한 검사 적용 |
plan | 계획 모드 - 실행 없음 | Claude는 읽기 전용 도구만 사용 가능; 실행 전에 계획 제시 (현재 SDK에서 지원되지 않음) |
acceptEdits | 자동 파일 편집 수락 | 파일 편집 및 파일 시스템 작업이 자동으로 승인됨 |
bypassPermissions | 모든 권한 검사 우회 | 모든 도구가 권한 프롬프트 없이 실행됨 (주의해서 사용) |
권한 모드를 두 가지 방법으로 설정할 수 있습니다:
쿼리를 생성할 때 모드를 설정합니다:
import { query } from "@anthropic-ai/claude-agent-sdk";
const result = await query({
prompt: "Help me refactor this code",
options: {
permissionMode: 'default' // Standard permission mode
}
});스트리밍 세션 중에 모드를 변경합니다:
import { query } from "@anthropic-ai/claude-agent-sdk";
// Create an async generator for streaming input
async function* streamInput() {
yield {
type: 'user',
message: {
role: 'user',
content: "Let's start with default permissions"
}
};
// Later in the conversation...
yield {
type: 'user',
message: {
role: 'user',
content: "Now let's speed up development"
}
};
}
const q = query({
prompt: streamInput(),
options: {
permissionMode: 'default' // Start in default mode
}
});
// Change mode dynamically
await q.setPermissionMode('acceptEdits');
// Process messages
for await (const message of q) {
console.log(message);
}acceptEdits)편집 수락 모드에서:
자동 승인 작업:
bypassPermissions)권한 우회 모드에서:
권한 모드는 권한 흐름의 특정 지점에서 평가됩니다:
bypassPermissions 모드 - 활성화되면 남은 모든 도구 허용canUseTool 콜백으로 연기canUseTool 콜백 - 남은 경우 처리이는 다음을 의미합니다:
bypassPermissions 모드에서도 항상 도구 사용을 제어할 수 있음bypassPermissions 모드는 일치하지 않은 도구에 대해 canUseTool 콜백을 무시모드 진행의 예:
// Start in default mode for controlled execution
permissionMode: 'default'
// Switch to acceptEdits for rapid iteration
await q.setPermissionMode('acceptEdits')canUseTool 콜백은 query 함수를 호출할 때 옵션으로 전달됩니다. 도구 이름과 입력 매개변수를 받으며, 허용 또는 거부 중 하나의 결정을 반환해야 합니다.
canUseTool은 Claude Code가 사용자에게 권한 프롬프트를 표시할 때마다 실행됩니다. 예를 들어 훅 및 권한 규칙으로 다루지 않고 acceptEdits 모드가 아닐 때입니다.
다음은 대화형 도구 승인을 구현하는 방법을 보여주는 완전한 예입니다:
import { query } from "@anthropic-ai/claude-agent-sdk";
async function promptForToolApproval(toolName: string, input: any) {
console.log("\n🔧 Tool Request:");
console.log(` Tool: ${toolName}`);
// Display tool parameters
if (input && Object.keys(input).length > 0) {
console.log(" Parameters:");
for (const [key, value] of Object.entries(input)) {
let displayValue = value;
if (typeof value === 'string' && value.length > 100) {
displayValue = value.substring(0, 100) + "...";
} else if (typeof value === 'object') {
displayValue = JSON.stringify(value, null, 2);
}
console.log(` ${key}: ${displayValue}`);
}
}
// Get user approval (replace with your UI logic)
const approved = await getUserApproval();
if (approved) {
console.log(" ✅ Approved\n");
return {
behavior: "allow",
updatedInput: input
};
} else {
console.log(" ❌ Denied\n");
return {
behavior: "deny",
message: "User denied permission for this tool"
};
}
}
// Use the permission callback
const result = await query({
prompt: "Help me analyze this codebase",
options: {
canUseTool: async (toolName, input) => {
return promptForToolApproval(toolName, input);
}
}
});AskUserQuestion 도구를 사용하면 Claude가 대화 중에 사용자에게 명확히 하는 질문을 할 수 있습니다. 이 도구가 호출되면 canUseTool 콜백이 질문을 받고 사용자의 답변을 반환해야 합니다.
canUseTool이 toolName: "AskUserQuestion"으로 호출될 때 입력에는 다음이 포함됩니다:
{
questions: [
{
question: "Which database should we use?",
header: "Database",
options: [
{ label: "PostgreSQL", description: "Relational, ACID compliant" },
{ label: "MongoDB", description: "Document-based, flexible schema" }
],
multiSelect: false
},
{
question: "Which features should we enable?",
header: "Features",
options: [
{ label: "Authentication", description: "User login and sessions" },
{ label: "Logging", description: "Request and error logging" },
{ label: "Caching", description: "Redis-based response caching" }
],
multiSelect: true
}
]
}updatedInput.answers에서 질문 텍스트를 선택한 옵션 레이블에 매핑하는 레코드로 답변을 반환합니다:
return {
behavior: "allow",
updatedInput: {
questions: input.questions, // Pass through original questions
answers: {
"Which database should we use?": "PostgreSQL",
"Which features should we enable?": "Authentication, Caching"
}
}
}다중 선택 답변은 쉼표로 구분된 문자열입니다 (예: "Authentication, Caching").