Handle approvals and user input¶
Use allowedTools / disallowedTools rules and the canUseTool callback to control which tools the agent can
use and how permission requests are handled.
By default, the SDK enforces tool permissions and does not bypass them. The canUseTool callback gives you
granular control over permission requests that are not already resolved by allowedTools /
disallowedTools rules or by an explicit permission mode such as bypassPermissions.
The SDK does not provide an interactive permission prompt by default. If a permission-checked request reaches the SDK
and canUseTool is not provided, the request fails.
How it works¶
When you provide a canUseTool callback, the SDK calls it before each permission-checked tool execution. Your
callback decides what happens:
The agent decides to use a permission-checked tool.
The SDK calls your
canUseToolcallback with the tool name, request input, and permission context.Your callback returns
allowordeny.The tool execution proceeds or is blocked accordingly.
For many ordinary tool permission checks, the callback input contains fields such as
{ action, resource }. SDK-routed pseudo-tools such as AskUserQuestion and ExitPlanMode contain
tool-specific fields.
If canUseTool is not provided and a permission-checked request reaches the SDK, the SDK returns an error instead
of prompting interactively.
Basic example¶
Response patterns¶
Allow a tool call¶
Return { behavior: "allow" } to let the tool execute with its original input:
Deny a tool call¶
Return { behavior: "deny" } with an optional message. The agent sees the denial message and can adjust its
approach:
The AskUserQuestion tool¶
Cortex Code has a built-in AskUserQuestion tool that the agent uses when it needs clarification from the user.
When the agent calls AskUserQuestion, the SDK routes it through your canUseTool callback with
toolName set to "AskUserQuestion". The input contains the agent’s questions as structured multiple-choice
options.
Handling questions¶
Check for toolName === "AskUserQuestion" in your canUseTool callback. The input contains a questions
array where each question has:
Field |
Description |
|---|---|
|
The full question text to display |
|
Short label for the question |
|
Array of choices, each with |
|
If |
Return allow with an updatedInput that includes the original questions and an answers map. Each key
is the question text and each value is the selected option’s label. For multi-select questions, join labels with
", ".
To deny a question (cancel the interaction), return deny:
Tip
AskUserQuestion is routed through canUseTool. Without a callback, the interaction cannot be completed and
the request errors instead of silently proceeding.
The ExitPlanMode tool¶
When a session is in plan mode, Cortex Code stays in planning until the plan is approved. The approval request is
routed through your canUseTool callback with toolName / tool_name set to "ExitPlanMode".
The input contains:
Field |
Description |
|---|---|
|
The proposed plan text the agent wants to execute |
|
Optional additional approval prompt from the agent |
Approving or rejecting a plan¶
Return allow to approve the plan. You can optionally include updatedInput.message to pass review context back
to the agent before it leaves plan mode.
Return deny to reject the plan. Use message when you want the agent to revise the plan with specific feedback.
Rejecting ExitPlanMode keeps the current turn in plan mode so the agent can update the plan and ask again.
Approving ExitPlanMode ends plan mode for the current turn. Subsequent turns resume the session’s normal
non-plan permission behavior, so later tool calls are evaluated the same way they would be outside plan mode.
Recommended interaction pattern¶
Use plan mode as a review loop:
Start the session with
permissionMode: "plan"(TypeScript) orpermission_mode="plan"(Python).Let the agent gather any missing information through
AskUserQuestion.When the agent calls
ExitPlanMode, inspect the proposedplantext.Return
denywith a precise review message if the plan needs changes.Return
allowonce the plan is acceptable. You can optionally includeupdatedInput.message/updated_input["message"]with reviewer guidance for execution.After approval, later turns go back to the session’s normal non-plan permission behavior.
Review-loop example¶
The simplest review loop is to reject a weak plan once with specific feedback, then approve the revised plan:
Rule-based permissions¶
For common permission patterns, you can use rule-based configuration instead of writing callback logic. The
allowedTools and disallowedTools options let you define lists of tools that are automatically approved or
blocked:
allowedTools entries can include patterns. For example, Bash(npm test:*) auto-approves any Bash command
matching that pattern. disallowedTools entries block specific tools entirely.
These rules are evaluated by the CLI before the canUseTool callback. If a tool matches an allowed or disallowed
rule, the callback is not invoked for that tool.
Combining with permission modes¶
The canUseTool callback works alongside permission modes. When both are set, the CLI’s built-in permission mode
filters run first, and your callback handles any remaining tool calls that need approval.
The available permission modes are:
Mode |
Description |
|---|---|
|
Uses standard permission checks. In SDK sessions, control permission-checked tools with |
|
Auto-approves plan requests and plan-exit confirmations. It does not bypass ordinary tool permissions. |
|
The agent plans changes but does not execute them without approval. With |
|
Skip all permission checks. Requires |
Change permission mode during a session¶
You can change permission mode after the session starts. TypeScript exposes setPermissionMode() on both
Query and CortexCodeSession. Python exposes set_permission_mode() on CortexCodeSDKClient.
The updated mode applies to later turns after the control request is processed. It does not retroactively change a tool call that is already running.
Hooks¶
Hooks let you intercept tool execution at different lifecycle stages. Unlike canUseTool which only controls
whether a tool runs, hooks can inspect tool results, inject context, and control agent flow.
Hook events¶
Event |
When it fires |
|---|---|
|
Before a tool executes. Can block execution or modify input. |
|
After a tool completes successfully. |
|
When a user prompt is submitted. |
|
When the agent stops. |
|
When a sub-agent stops. |
|
When the agent emits a notification. |
|
When a tool permission request occurs. |
|
Before context compaction. |
The matcher field on a hook entry is optional. When provided, it filters by the event’s match value:
tool name for PreToolUse, PostToolUse, and PermissionRequest; notification type for Notification;
and trigger for PreCompact. When omitted, the hook fires for all values for that event.
See the TypeScript SDK reference and Python SDK reference for the complete hook input and output type definitions.
Choosing an approach¶
Approach |
When to use |
|---|---|
|
Sandboxed environments, CI pipelines, or fully trusted scenarios where you don’t need to review tool calls.
Requires |
|
When you can express your permission policy as a static list of allowed or blocked tools |
|
Production systems where you need to audit, filter, or modify tool calls before they execute |
Permission mode only (no callback) |
When |
Hooks |
When you need to observe or react to tool results, inject context, or control agent flow beyond allow/deny decisions |
Note
The SDK does not bypass permissions or prompt interactively by default. If a permission-checked request reaches the
SDK and canUseTool is not provided, the request fails. To bypass permissions, you must explicitly set
permissionMode: "bypassPermissions" with the appropriate safety flag.
Legal notices¶
Where your configuration of Cortex Code uses a model provided on the Model and Service Pass-Through Terms, your use of that model is further subject to the terms for that model on that page.
The data classification of inputs and outputs are as set forth in the following table.
Input data classification |
Output data classification |
Designation |
|---|---|---|
Usage Data |
Customer Data |
Covered AI Features [1] |
For additional information, refer to Snowflake AI and ML.