Skip to main content

Permission requests

Default behavior (deny-all)

When permission_approve in config/copilot.php is "deny-all" (the default), permission requests during Copilot::run() and Copilot::start() are automatically denied. This is a safe default because text-generation use cases usually don’t require permissions.

Available values

"approve-safety" and "approve-all" are dangerous when accepting user-supplied prompts. Always use false or "deny-all" in those cases. Even read-only permissions may allow Laravel project code to be read.

PermissionHandler::approveAll()

PermissionHandler::approveAll() auto-approves every request.

PermissionHandler::approveSafety()

PermissionHandler::approveSafety() denies only the high-risk permissions (shell and write) and auto-approves everything else.
This still isn’t perfectly safe. For strict control, implement a custom handler and inspect $request['kind'] to decide.

PermissionHandler::denyAll()

PermissionHandler::denyAll() denies everything.

Using the client directly

When using CopilotClient directly, specifying onPermissionRequest is required, just like the official SDK.

Custom handler

To control approvals by request kind, pass a closure. $request and $invocation are arrays with roughly the following shape.

$request

Fields other than kind and toolCallId vary based on kind.
If $request['managedApprovalRequired'] is true, your organization’s Managed Settings prevent this request from being auto-approved. In this case, PermissionHandler::approveAll() returns no-result and defers to the standard Copilot CLI flow.

$invocation

Prompt context (promptRequest)

With newer CLI runtimes, $invocation['promptRequest'] may contain the context of the user-facing prompt. Custom handlers can use this value to decide whether a human response is required. PermissionHandler::approveAll() gives precedence to promptRequest['managedApprovalRequired'] when all of the following conditions are met:
  • promptRequest['kind'] is one of commands / read / write / url / workflow
  • promptRequest['managedApprovalRequired'] is a boolean
This allows auto-approval when the prompt does not require a human response, even if $request['managedApprovalRequired'] remains as a policy-derived marker. The raw marker in $request is still preserved. With older CLIs that do not send promptRequest, unsupported kinds, or when there is no valid boolean value, the decision falls back to $request['managedApprovalRequired'] as before.

Response

Return the permission decision as an array. Using the PermissionRequestResultKind class makes the intent easier to read.

Protocol details

In Protocol v3 (the current default), permission requests are delivered as session events (permission.requested) rather than JSON-RPC requests. The SDK handles this internally and responds via the session.permissions.handlePendingPermissionRequest RPC. The usage of SessionConfig does not change. Pass a handler to onPermissionRequest and the SDK absorbs any protocol differences.

PermissionRequestResultKind

You can return ['kind' => 'approve-once'] directly, but PermissionRequestResultKind makes it clearer.

Available methods

To use Laravel\Prompts\select, retrieve the options via PermissionRequestResultKind::select().

no-result

If the handler cannot produce a result (for example, in a non-interactive environment), return no-result. Returning no-result skips the RPC call, and the Copilot CLI’s default deny applies.
For the latest updates, see the GitHub repository.
Last modified on October 19, 2026