Skip to main content

Language Basics

OpalScript uses Starlark syntax, which is similar to Python. This section gives you a quick overview of Starlark syntax and its key differences from Python.

Syntax Overview

# Variables
count = 10
name = "alice"
is_active = True

# Conditionals
if count > 5:
    print("high")
elif count > 0:
    print("low")
else:
    print("zero")

# Loops
for item in [1, 2, 3]:
    print(item)

for i in range(10):
    print(i)

# Functions
def calculate_score(base, multiplier):
    return base * multiplier

# String operations
text = "Hello World"
lower_text = text.lower()          # "hello world"
contains_hello = "hello" in lower_text  # True

# Lists
items = ["a", "b", "c"]
items.append("d")
first = items[0]

# Dictionaries
config = {"key": "value", "count": 42}
value = config["key"]
config["new_key"] = "new_value"

Key Differences from Python

OpalScript (Starlark) has some intentional limitations compared to Python:
FeatureOpalScriptPython
Import statementsNot supported (modules pre-loaded)Supported
ClassesNot supportedSupported
ExceptionsNot supported (try/except)Supported
While loopsNot supported (use for with range())Supported
Global variablesLimited mutationFull support
Standard libraryMinimalExtensive
These limitations ensure scripts are predictable, terminate reliably, and execute safely.

Quick Reference

Utility Functions (All Script Types)

ModuleFunctionDescription
accesscheck_access(principal, entity, [level])Check whether a principal has access to an entity
notificationsnotify_user(user_id, title, body)Notify a specific user via email and Slack (if configured)
notificationsnotify_admins(title, body)Notify all Opal admins
notificationsnotify_owner(owner_id, title, body)Notify an owner via Slack channel (if configured) or all owner members
requestsby_user(user_id, [status], [cursor], [per_page])Get requests a user submitted or was the target of (paginated)
requestsby_resource(resource_id, [user_id], [status], [cursor], [per_page])Get historical requests for a resource (paginated)
requestsby_group(group_id, [user_id], [status], [cursor], [per_page])Get historical requests for a group (paginated)
riskresource_sensitivity(resource_id)Get the risk sensitivity level of a resource
riskgroup_sensitivity(group_id)Get the risk sensitivity level of a group
timenow()Get the current Unix timestamp
timefrom_unix(timestamp)Convert a Unix timestamp to an RFC3339 string
timeis_before(timestamp1, timestamp2)Check if the first timestamp is before the second
timeis_after(timestamp1, timestamp2)Check if the first timestamp is after the second
timeseconds_since(timestamp1, timestamp2)Get the number of seconds between two timestamps
timeminutes(n) / hours(n) / days(n)Convert time intervals to seconds
entityget_user(user_id)Look up a user by ID
entityget_group(group_id)Look up a group by ID
entityget_resource(resource_id)Look up a resource by ID
ticketsproviders.<PROVIDER>Access an installed ticket provider (e.g. tickets.providers.JIRA)
ticketslist_projects(provider)List projects on a provider; returns a dict keyed by project key
ticketscreate_ticket(project, title, description)Create a ticket on the provider; returns a ticket object
ticketsget_ticket(provider, remote_ticket_id)Fetch an existing ticket by its remote identifier
ticketscomment_ticket(provider, remote_ticket_id, comment)Add a comment to an existing ticket
ticketsclose_ticket(provider, remote_ticket_id, [comment])Close a ticket, with an optional closing comment

Request Review Functions

ModuleFunctionDescription
contextget_request()Get the request being reviewed
actionsapprove([comment], [duration_minutes])Approve the request, optionally overriding the access duration
actionsdeny(comment)Deny the request (comment required)
actionscomment(comment, [duration_minutes])Add a comment, optionally overriding the access duration
actionspause(minutes)Pause script execution for 1–1440 minutes, then resume from the same point; actions before the pause are skipped on replay
actionspoll(pollFunction, minutes, max_iterations)Call pollFunction every minutes minutes (1–1440) up to max_iterations times (1–50); returns True if it succeeded

Request Attributes

AttributeTypeAlways Present
idStringYes
reasonStringYes
requester_idStringYes
statusStringYes
target_user_idStringNo
target_group_idStringNo
requested_duration_minutesintNo
requested_resourcesListYes (may be empty)
requested_groupsListYes (may be empty)
custom_fieldsDictYes (may be empty)
Last modified on June 30, 2026