Skip to content
Bifrost Docs

Context API

Complete reference for the execution context

The context proxy provides access to organization, user, and execution information in workflows and data providers. No need to pass it as a parameter—just import and use it.

from bifrost import workflow, context
@workflow(name="example")
async def example(name: str):
# Access context via proxy - no parameter needed
org_id = context.org_id
user_id = context.user_id
return {"org": org_id, "user": user_id}
Property Type Description Example
user_id str Current user’s ID "user-123"
email str User’s email address "alice@example.com"
name str User’s display name "Alice Smith"
Property Type Description Example
org_id str | None Organization ID (None for global scope) "org-456" or None
org_name str | None Organization name "Acme Corp"
organization Organization | None Full organization object (None for global scope) See Organization type
scope str Raw scope identifier (use org_id instead) "org-456" or "GLOBAL"
Property Type Description Example
execution_id str Unique execution ID "exec-789"
parameters dict[str, Any] Extra parameters passed to workflow {"custom_key": "value"}
startup dict[str, Any] | None Results from launch workflow {"user_data": {...}}
Property Type Description
is_platform_admin bool User is platform administrator
is_function_key bool Called via API key (not user)
is_global_scope bool Executing in global scope (no org)
Property Type Description
roi ROIContext ROI tracking context
roi.time_saved int Minutes saved (from workflow definition)
roi.value float Value metric (from workflow definition)
Method Parameters Returns Description
set_scope(org_id) org_id: str | None None Override effective scope for all subsequent SDK calls. Pass an org UUID to target that org (provider orgs only). Pass None to reset to original scope.

Returns organization ID or None for global scope.

org_id: str | None = context.org_id
if context.org_id:
# Organization-scoped operation
users = await get_org_users(context.org_id)
else:
# Global operation
all_orgs = await get_all_organizations()

Returns organization display name.

org_name: str | None = context.org_name
logger.info(f"Executing for {context.org_name}")

Check if executing in global (platform-wide) scope.

if context.is_global_scope:
# Platform-level operation
pass
else:
# Organization-level operation
pass

When context.organization is not None:

Property Type Description
id str Organization ID
name str Display name
is_active bool Organization is active
is_provider bool Provider organization (can access other org scopes)
if context.organization:
org_name = context.organization.name
is_active = context.organization.is_active

Provider organizations can use set_scope() to target managed organizations for all subsequent SDK calls. Managed orgs are locked to their own scope.

from bifrost import workflow, context, integrations
@workflow(name="provision_tenant")
async def provision_tenant(target_org_id: str):
# Switch scope to the managed org
context.set_scope(target_org_id)
# All SDK calls now target the managed org
graph = await integrations.get("Microsoft Graph")
cfg = await config.get("timezone")
# Reset to original scope
context.set_scope(None)
from bifrost import workflow, context
@workflow(name="admin_task")
async def admin_task():
if not context.is_platform_admin:
return {
"success": False,
"error": "Admin privileges required"
}
# Perform admin operation
return {"success": True}

Data providers can access context the same way:

from bifrost import data_provider, context
@data_provider(name="get_org_users")
async def get_org_users():
# Filter users by organization
users = await db.query(
"SELECT id, name FROM users WHERE org_id = ?",
context.org_id
)
return [
{"label": u["name"], "value": u["id"]}
for u in users
]
from dataclasses import dataclass
from datetime import datetime
from typing import Any
@dataclass
class ROIContext:
time_saved: int # Minutes saved per execution
value: float # Value metric per execution
@dataclass
class ExecutionContext:
user_id: str
email: str
name: str
scope: str
organization: Organization | None
is_platform_admin: bool
is_function_key: bool
execution_id: str
parameters: dict[str, Any] # Extra parameters passed to workflow
startup: dict[str, Any] | None # Results from launch workflow
roi: ROIContext # ROI tracking context
_scope_override: str | None # Set via set_scope()
@property
def org_id(self) -> str | None:
if self._scope_override is not None:
return self._scope_override
return self.organization.id if self.organization else None
@property
def org_name(self) -> str | None:
return self.organization.name if self.organization else None
@property
def is_global_scope(self) -> bool:
return self.scope == "GLOBAL"
def set_scope(self, org_id: str | None) -> None:
"""Override effective scope for all subsequent SDK calls.
Only provider orgs can target a different org."""
...
  1. Use the Proxy: Import from bifrost import context - no parameter needed
  2. Always Check org_id: Verify org context before org-scoped operations
  3. Log Context: Include context in log messages for debugging
  4. Don’t Mutate: Context is read-only except for set_scope()
  5. Use Properties: Use context.org_id not context.organization.id
  6. Never Log Secrets: Don’t include sensitive data in log messages