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 - Если активен, разрешает все оставшиеся инструментыcanUseToolcanUseTool - Обрабатывает оставшиеся случаиЭто означает:
bypassPermissionsbypassPermissions переопределяет обратный вызов 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").