ClaudeAgentSDK.Permission (claude_agent_sdk v0.11.0)

Copy Markdown View Source

Permission System for Claude Agent SDK.

This module provides a structured permission system for controlling tool execution at runtime through callbacks and permission modes.

Permission Modes

The SDK supports six permission modes that control how tool permissions are handled:

  • :default - All tools go through the permission callback
  • :accept_edits - Edit operations (Write, Edit, MultiEdit) are auto-allowed
  • :plan - Claude creates a plan, shows it to user, then executes after approval
  • :bypass_permissions - All tools are allowed without callback invocation
  • :delegate - Delegate tool execution to the SDK (CLI does not run built-in tools)
  • :dont_ask - Do not prompt for permissions; tools proceed without callback

Permission Callbacks

Permission callbacks allow fine-grained control over tool execution. They receive context about the tool being used and return a permission result.

Callback Signature

(Context.t() -> Result.t())

Example

callback = fn context ->
  case context.tool_name do
    "Bash" ->
      if String.contains?(context.tool_input["command"], "rm -rf") do
        Result.deny("Dangerous command detected")
      else
        Result.allow()
      end

    "Write" ->
      # Redirect system file writes to safe location
      file_path = context.tool_input["file_path"]
      if String.starts_with?(file_path, "/etc/") do
        safe_path = "/tmp/safe_output/" <> Path.basename(file_path)
        Result.allow(updated_input: %{context.tool_input | "file_path" => safe_path})
      else
        Result.allow()
      end

    _ ->
      Result.allow()
  end
end

options = %Options{
  can_use_tool: callback,
  permission_mode: :default
}

Runtime Mode Switching

Permission mode can be changed at runtime using Client.set_permission_mode/2:

{:ok, client} = Client.start_link(options)

# Switch to plan mode
Client.set_permission_mode(client, :plan)

# Switch back to default
Client.set_permission_mode(client, :default)

Integration with Hooks

The permission system integrates with the existing hooks system. Permission callbacks are invoked via the control protocol when the CLI requests permission to use a tool. If the CLI does not emit can_use_tool requests, the SDK automatically invokes the callback via a PreToolUse hook when possible. In that hook-based path, updated_permissions updates are ignored. When can_use_tool is set, the SDK enables partial messages and configures the CLI permission prompt tool to "stdio" internally.

See:

Summary

Types

Permission callback function type.

Permission mode controlling how tool permissions are handled.

Functions

Converts permission mode atom to CLI string format.

Converts CLI permission mode string to atom.

Validates a permission mode.

Returns all valid permission modes.

Validates a permission callback function.

Types

callback()

Permission callback function type.

Receives permission context and returns permission result.

permission_mode()

@type permission_mode() ::
  :default | :accept_edits | :plan | :bypass_permissions | :delegate | :dont_ask

Permission mode controlling how tool permissions are handled.

Functions

mode_to_string(mode)

@spec mode_to_string(permission_mode()) :: String.t()

Converts permission mode atom to CLI string format.

Examples

iex> ClaudeAgentSDK.Permission.mode_to_string(:accept_edits)
"acceptEdits"

iex> ClaudeAgentSDK.Permission.mode_to_string(:default)
"default"

string_to_mode(arg1)

@spec string_to_mode(String.t()) :: permission_mode() | nil

Converts CLI permission mode string to atom.

Returns nil for unknown mode strings.

Examples

iex> ClaudeAgentSDK.Permission.string_to_mode("acceptEdits")
:accept_edits

iex> ClaudeAgentSDK.Permission.string_to_mode("invalid")
nil

valid_mode?(mode)

@spec valid_mode?(term()) :: boolean()

Validates a permission mode.

Returns true if the mode is valid, false otherwise.

Examples

iex> ClaudeAgentSDK.Permission.valid_mode?(:default)
true

iex> ClaudeAgentSDK.Permission.valid_mode?(:invalid)
false

valid_modes()

@spec valid_modes() :: [permission_mode()]

Returns all valid permission modes.

Examples

iex> ClaudeAgentSDK.Permission.valid_modes()
[:default, :accept_edits, :plan, :bypass_permissions, :delegate, :dont_ask]

validate_callback(callback)

@spec validate_callback(term()) :: :ok | {:error, String.t()}

Validates a permission callback function.

Returns :ok if the callback is valid, {:error, reason} otherwise.

Examples

iex> callback = fn _context -> Result.allow() end
iex> ClaudeAgentSDK.Permission.validate_callback(callback)
:ok

iex> ClaudeAgentSDK.Permission.validate_callback("not a function")
{:error, "Permission callback must be a function"}