Skip to content

Scopes and Permissions

Learn how to manage OAuth scopes and permissions for Agent Auth connections to control what your application can access.

OAuth scopes and permissions determine what data and actions your application can access on behalf of users. Understanding how to properly configure and manage scopes is essential for building secure and functional Agent Auth integrations.

OAuth scopes are permission grants that define the level of access your application has to a user’s data with third-party providers.

Scopes are strings that represent specific permissions:

# Example OAuth scopes
https://www.googleapis.com/auth/gmail.readonly # Read Gmail messages
https://www.googleapis.com/auth/gmail.send # Send Gmail messages
https://www.googleapis.com/auth/calendar.events # Manage calendar events
channels:read # Read Slack channels
chat:write # Send Slack messages

###How scopes work

  1. Application requests scopes - Your connection specifies required scopes
  2. User sees consent screen - Provider shows what permissions are requested
  3. User grants access - User approves or denies the requested permissions
  4. Tokens include scopes - Access tokens are limited to granted scopes
  5. API enforces scopes - Provider APIs check tokens have required scopes

Scopes typically follow a hierarchy from broad to specific:

Gmail example:

  • https://mail.google.com/ - Full Gmail access (read, send, delete)
  • https://www.googleapis.com/auth/gmail.modify - Read and modify (but not delete)
  • https://www.googleapis.com/auth/gmail.readonly - Read-only access
  • https://www.googleapis.com/auth/gmail.send - Send emails only

Different providers use different scope formats and naming conventions:

Google uses URL-based scopes with hierarchical permissions:

Gmail Scopes

Read-only access:

https://www.googleapis.com/auth/gmail.readonly

Send emails:

https://www.googleapis.com/auth/gmail.send

Full access:

https://mail.google.com/

Modify (read/write, no delete):

https://www.googleapis.com/auth/gmail.modify

Google Calendar Scopes

Read-only calendar access:

https://www.googleapis.com/auth/calendar.readonly

Manage calendar events:

https://www.googleapis.com/auth/calendar.events

Full calendar access:

https://www.googleapis.com/auth/calendar

Google Drive Scopes

Read-only access:

https://www.googleapis.com/auth/drive.readonly

Per-file access:

https://www.googleapis.com/auth/drive.file

Full drive access:

https://www.googleapis.com/auth/drive

Google Sheets Scopes

Read-only sheets:

https://www.googleapis.com/auth/spreadsheets.readonly

Edit sheets:

https://www.googleapis.com/auth/spreadsheets

Microsoft uses dotted notation with resource.permission format:

Outlook/Mail Scopes

Read mail:

Mail.Read

Send mail:

Mail.Send

Read/write mail:

Mail.ReadWrite

Calendar Scopes

Read calendar:

Calendars.Read

Manage calendar:

Calendars.ReadWrite

OneDrive Scopes

Read files:

Files.Read.All

Read/write files:

Files.ReadWrite.All

Teams Scopes

Read teams:

Team.ReadBasic.All

Send messages:

ChannelMessage.Send

Slack uses simple string-based scopes:

Channel Scopes

Read channels:

channels:read

Manage channels:

channels:manage

Join channels:

channels:join

Chat Scopes

Send messages:

chat:write

Send as user:

chat:write.customize

User Scopes

Read user info:

users:read

Read user email:

users:read.email

File Scopes

Read files:

files:read

Write files:

files:write

Atlassian uses colon-separated scopes:

read:jira-work # Read issues and projects
write:jira-work # Create and update issues
read:jira-user # Read user information
manage:jira-project # Manage projects

Scopes are configured at the connection level in Scalekit:

  1. Navigate to Agent AuthConnections
  2. Select your connection or create a new one
  3. In the Scopes section, enter required scopes
  4. Scopes vary by provider - refer to provider’s documentation
  5. Save the connection configuration
  6. Existing users must re-authenticate to get new scopes

Gmail connection with multiple scopes:

// Dashboard configuration (for reference)
{
"connection_name": "gmail",
"provider": "GMAIL",
"scopes": [
"https://www.googleapis.com/auth/gmail.readonly",
"https://www.googleapis.com/auth/gmail.send",
"https://www.googleapis.com/auth/gmail.modify"
]
}

Slack connection with workspace scopes:

// Dashboard configuration (for reference)
{
"connection_name": "slack",
"provider": "SLACK",
"scopes": [
"channels:read",
"chat:write",
"users:read",
"files:read"
]
}

Verify which scopes a user has granted:

# Get connected account and check granted scopes
account = actions.get_connected_account(
identifier="user_123",
connection_name="gmail"
)
print(f"Granted scopes: {account.scopes}")
# Check if specific scope is granted
required_scope = "https://www.googleapis.com/auth/gmail.send"
if required_scope in account.scopes:
print("✓ User granted email sending permission")
else:
print("✗ Email sending permission not granted")
# Request re-authentication with required scope

When you need additional permissions, users must re-authenticate:

  1. Update connection - Add new scopes to connection configuration
  2. Detect missing scopes - Check connected account for required scopes
  3. Generate auth link - Create new authorization link for user
  4. User re-authenticates - User approves additional permissions
  5. Verify new scopes - Confirm scopes were granted
def ensure_required_scopes(identifier: str, connection_name: str, required_scopes: list):
"""
Ensure user has granted all required scopes.
Returns True if all scopes granted, False if re-authentication needed.
"""
# Get current account and scopes
account = actions.get_connected_account(
identifier=identifier,
connection_name=connection_name
)
# Check if all required scopes are granted
granted_scopes = set(account.scopes)
missing_scopes = [s for s in required_scopes if s not in granted_scopes]
if not missing_scopes:
print("✓ All required scopes granted")
return True
print(f"⚠ Missing scopes: {missing_scopes}")
# Generate authorization link for re-authentication
link_response = actions.get_authorization_link(
connection_name=connection_name,
identifier=identifier
)
print(f"🔗 User must re-authorize with additional permissions:")
print(f" {link_response.link}")
print(f"\nMissing permissions:")
for scope in missing_scopes:
print(f" - {scope}")
return False
# Usage
required_scopes = [
"https://www.googleapis.com/auth/gmail.readonly",
"https://www.googleapis.com/auth/gmail.send",
"https://www.googleapis.com/auth/gmail.modify"
]
if ensure_required_scopes("user_123", "gmail", required_scopes):
# All scopes granted, proceed with operation
result = actions.execute_tool(...)
else:
# Waiting for user to re-authenticate
print("Please authorize additional permissions")

Always validate scopes before executing tools to provide better error messages:

# Map tools to required scopes
TOOL_SCOPE_REQUIREMENTS = {
'gmail_send_email': ['https://www.googleapis.com/auth/gmail.send'],
'gmail_fetch_mails': ['https://www.googleapis.com/auth/gmail.readonly'],
'gmail_delete_email': ['https://mail.google.com/'],
'calendar_create_event': ['https://www.googleapis.com/auth/calendar.events'],
'slack_send_message': ['chat:write'],
}
def execute_tool_with_scope_check(identifier, connection_name, tool_name, tool_input):
"""Execute tool after validating required scopes"""
# Get required scopes for this tool
required_scopes = TOOL_SCOPE_REQUIREMENTS.get(tool_name, [])
if required_scopes:
# Verify user has granted required scopes
account = actions.get_connected_account(
identifier=identifier,
connection_name=connection_name
)
granted_scopes = set(account.scopes)
missing_scopes = [s for s in required_scopes if s not in granted_scopes]
if missing_scopes:
raise PermissionError(
f"Missing required permissions for {tool_name}: {missing_scopes}. "
f"Please re-authorize to grant these permissions."
)
# Scopes verified, execute tool
return actions.execute_tool(
identifier=identifier,
tool_name=tool_name,
tool_input=tool_input
)
# Usage
try:
result = execute_tool_with_scope_check(
identifier="user_123",
connection_name="gmail",
tool_name="gmail_send_email",
tool_input={"to": "user@example.com", "subject": "Test", "body": "Hello"}
)
print("✓ Email sent successfully")
except PermissionError as e:
print(f"✗ Permission error: {e}")
# Prompt user to re-authorize

Good:

# Only request scopes you need
scopes = [
"https://www.googleapis.com/auth/gmail.readonly", # For reading emails
"https://www.googleapis.com/auth/gmail.send" # For sending emails
]

Avoid:

# Don't request overly broad access
scopes = [
"https://mail.google.com/" # Full Gmail access including delete
]

Provide clear explanations of why you need specific permissions:

SCOPE_EXPLANATIONS = {
"https://www.googleapis.com/auth/gmail.readonly":
"Read your emails to analyze and summarize them",
"https://www.googleapis.com/auth/gmail.send":
"Send emails on your behalf",
"https://www.googleapis.com/auth/calendar.events":
"Create and manage calendar events for you",
"chat:write":
"Send messages in Slack channels",
}
# Show explanations in your UI before redirecting to OAuth
def get_scope_explanation(scope):
return SCOPE_EXPLANATIONS.get(scope, "Access your account data")
# After OAuth callback
if user_denied_scopes:
# Don't show error - explain what features won't work
message = """
Some features will be limited because certain permissions weren't granted:
- Email sending: Requires 'Send email' permission
- Email reading: Requires 'Read email' permission
You can grant these permissions later in Settings.
"""
# Provide link to re-authorize in settings

Request additional scopes only when needed:

# Start with minimal scopes
initial_scopes = ["https://www.googleapis.com/auth/gmail.readonly"]
# Later, when user wants to send email
if user_wants_to_send_email:
# Request additional scope
additional_scopes = ["https://www.googleapis.com/auth/gmail.send"]
# Prompt user to grant additional permission

Error: “Insufficient permissions” or 403 Forbidden

Solution:

  1. Check which scopes are currently granted
  2. Verify the tool requires those specific scopes
  3. Update connection configuration if needed
  4. Have user re-authenticate to grant additional scopes

Error: Invalid scope or scope not recognized

Solution:

  1. Verify scope name matches provider’s documentation exactly
  2. Check if scope requires special provider approval
  3. Some scopes only available to verified applications
  4. Review provider’s scope documentation for correct format

Issue: OAuth consent shows different or additional permissions

Causes:

  • Scopes configured in connection don’t match expected
  • Provider groups related scopes together
  • Sensitive scopes trigger additional consent

Solution:

  • Review connection scope configuration
  • Check provider’s scope grouping behavior
  • Ensure sensitive scopes are truly necessary