---
updatedAt: 2026-09-27T23:44:44.000Z
agentTools:
  projectIndex: https://docs.ascerta.com/llms.txt
---

# Day 4: Using get_context()

# Overview

When working with Ascerta's Python SDK, you often need to access information about the current execution context, such as which limits are being applied or what use case is being tracked. The `get_context()` function provides a straightforward way to retrieve this information at runtime.

This document explains how to use `get_context()` to access context information, with practical examples focused on common use cases.

## What is `get_context()`?

The `get_context()` function returns the current tracking context as a typed dictionary. This context includes values from:

* Global context set in `ascerta_instrument()`
* Context values from any active `@track` decorator
* Context values from any active `track_context()` manager

```python
from ascerta import get_context

# Get the current context
context = get_context()
```

The function **always returns a dictionary** - if no context is active, it returns an empty context dictionary. This ensures your code can safely access context values without checking for None return values.

## Understanding Context Sources

The context returned by `get_context()` combines values from multiple sources according to the parameter precedence rules. In general:

* Values set in `ascerta_instrument()` provide global defaults
* When contexts are nested, the innermost (latest) context's values typically take precedence for overlapping parameters
* Parameter inheritance and combination rules determine exactly how values are processed

For the specific rules about how values are inherited, overridden, or combined across different levels, refer to the [Parameter Precedence in Ascerta Instrumentation](/docs/parameter-precedence-in-pay-i-instrumentation) documentation.

## Key Use Cases for `get_context()`

### 1. Checking Active Limits

One of the most valuable uses of `get_context()` is retrieving the limits IDs currently applied in your execution context. This enables you to check limit usage and adapt your application's behavior accordingly:

```python
from ascerta import get_context, Ascerta

ascerta_client = Ascerta()

def check_active_limit_usage():
    """Check the usage status of limits active in the current context."""
    # Get the current context
    context = get_context()
    
    # Retrieve limit IDs from the context
    active_limit_ids = context.get('limit_ids', [])
    
    if not active_limit_ids:
        print("No limits are currently active in this context")
        return
    
    print(f"Active limit IDs: {active_limit_ids}")
    
    # Check each limit's status
    for limit_id in active_limit_ids:
        limit = ascerta_client.limits.retrieve(limit_id=limit_id).limit
        
        # Calculate usage metrics
        current_usage = limit.totals.cost.total.base
        max_limit = limit.max
        usage_percentage = (current_usage / max_limit) * 100 if max_limit > 0 else 0
        
        print(f"Limit '{limit.limit_name}':")
        print(f"  Usage: ${current_usage:.2f} of ${max_limit:.2f} ({usage_percentage:.1f}%)")
        
        # Detect if we're approaching the limit
        if usage_percentage >= 90:
            print("  ⚠️ Critical: Approaching maximum")
        elif usage_percentage >= limit.threshold * 100:
            print(f"  ⚠️ Warning: Exceeded threshold ({limit.threshold * 100:.0f}%)")
        else:
            print("  ✅ Within budget")
```

This function can be called anywhere in your application to check the status of limits active in the current context, without needing to pass limit IDs explicitly.

### 2. Accessing Use Case Information

When using the `@track` decorator or `track_context()` with use case parameters, `get_context()` allows you to access the current use case information:

```python
from ascerta import get_context

def log_use_case_info():
    """Log information about the current use case."""
    context = get_context()
    
    if 'use_case_name' in context:
        print(f"Current use case: {context.get('use_case_name')} (ID: {context.get('use_case_id', '')}, Version: {context.get('use_case_version', '')})")
        if 'use_case_step' in context:
            print(f"Current step: {context.get('use_case_step')}")
    else:
        print("No use case active in current context")
```

### 3. Retrieving User Attribution

When user IDs are set in the context, `get_context()` lets you access this information for logging or attribution:

```python
from ascerta import get_context

def get_current_user():
    """Get the user ID from the current context."""
    return get_context().get('user_id', "anonymous")
```

## Example: Nested Contexts

This example demonstrates how `get_context()` works with nested contexts, where the innermost context's values take precedence:

```python
from ascerta import ascerta_instrument, track, track_context, get_context

# Set global defaults
ascerta_instrument(config={
    "use_case_name": "GlobalApp",
    "limit_ids": ["global_limit"],
    "user_id": "default_user"
})

# Function with track decorator
@track(use_case_name="UserService")
def process_user_request():
    # At this point, get_context() would return:
    # - use_case_name: "UserService" (from decorator)
    # - limit_ids: ["global_limit"] (from global)
    # - user_id: "default_user" (from global)
    context = get_context()
    print("Outer context:")
    print(f"  use_case_name: {context.get('use_case_name', '')}")
    print(f"  limit_ids: {context.get('limit_ids', [])}")
    print(f"  user_id: {context.get('user_id', '')}")
    
    # Nested context with track_context
    with track_context(use_case_step="login", user_id="specific_user"):
        # Now get_context() would return:
        # - use_case_name: "UserService" (inherited from decorator)
        # - limit_ids: ["global_limit"] (inherited)
        # - user_id: "specific_user" (from inner context)
        # - use_case_step: "login" (from inner context)
        context = get_context()
        print("Inner context:")
        print(f"  use_case_name: {context.get('use_case_name', '')}")
        print(f"  limit_ids: {context.get('limit_ids', [])}")
        print(f"  user_id: {context.get('user_id','')}")
        print(f"  use_case_step: {context.get('use_case_step', '')}")
```

## Practical Example: Adaptive Behavior Based on Limit Status

This example demonstrates how `get_context()` is used to adapt application behavior based on limit usage:

```python
from ascerta import get_context, Ascerta
from openai import OpenAI

ascerta_client = Ascerta()
openai_client = OpenAI()

def adaptive_content_generation(prompt):
    """Generate content with adaptive behavior based on current limit usage."""
    # Get active limit IDs from the current context
    context = get_context()
    active_limit_ids = context.get('limit_ids', [])
    
    if not active_limit_ids:
        print("No limits active in current context")
        # Use default parameters when no limits are active
        model = "gpt-4"
        max_tokens = 500
    else:
        # Check if any active limit is close to its threshold
        approaching_limit = False
        
        for limit_id in active_limit_ids:
            limit = ascerta_client.limits.retrieve(limit_id=limit_id).limit
            usage_percentage = (limit.totals.cost.total.base / limit.max) * 100 if limit.max > 0 else 0
            
            if usage_percentage >= 90:
                # Very close to limit
                approaching_limit = True
                print(f"⚠️ Near limit '{limit.limit_name}': {usage_percentage:.1f}% used")
                break
            elif usage_percentage >= limit.threshold * 100:
                # Above threshold but not critical
                approaching_limit = True
                print(f"⚠️ Approaching limit '{limit.limit_name}': {usage_percentage:.1f}% used")
                break
        
        # Adjust parameters based on limit status
        if approaching_limit:
            # Use more economical settings when approaching limits
            model = "gpt-3.5-turbo"
            max_tokens = 250
            print(f"Using economical settings: {model} with {max_tokens} max tokens")
        else:
            # Use standard settings when well within limits
            model = "gpt-4"
            max_tokens = 500
            print(f"Using standard settings: {model} with {max_tokens} max tokens")
    
    # Generate content with the selected parameters
    response = openai_client.chat.completions.create(
        model=model,
        messages=[{"role": "user", "content": prompt}],
        max_tokens=max_tokens
    )
    
    return response.choices[0].message.content
```

<a id="payicontext-dictionary-keys"></a>

## AscertaContext Dictionary Keys

The dictionary returned by `get_context()` can contain the following optional keys:

| Property              | Type            | Description                                                                                                                                                                   |
| --------------------- | --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `use_case_name`       | string          | Name of the current use case                                                                                                                                                  |
| `use_case_id`         | string          | Unique ID of the current use case                                                                                                                                             |
| `use_case_version`    | integer         | Version of the current use case                                                                                                                                               |
| `use_case_step`       | string          | Current step in the use case flow                                                                                                                                             |
| `use_case_properties` | dict            | Custom use case properties (see [Property Bags](/docs/property-bags))                                                                                                         |
| `limit_ids`           | list of strings | IDs of limits being applied                                                                                                                                                   |
| `user_id`             | string          | ID of the current user                                                                                                                                                        |
| `account_name`        | string          | Name off the current account                                                                                                                                                  |
| `price_as_category`   | string          | Category for pricing                                                                                                                                                          |
| `price_as_resource`   | string          | Resource for pricing                                                                                                                                                          |
| `resource_scope`      | string          | Scope for resource pricing                                                                                                                                                    |
| `request_properties`  | dict            | Custom request properties (see [Property Bags](/docs/property-bags))                                                                                                          |
| `last_result`         | object          | Contains information about the last API call (if available).  Type will be `None` \|  `ascerta.types.shared.XproxyResult` \|  `ascerta.types.shared.xproxy_error.XproxyError` |

## Best Practices

### 1. Use Direct Dictionary Access

Since `get_context()` always returns a dictionary, you can directly access values without defensive coding:

```python
from ascerta import get_context

# Always safe - values will be None if not set
context = get_context()
user_id = context.get('user_id')
limit_ids = context.get('limit_ids')
```

### 2. Provide Default Values for Optional Keys

When you need a default value for a key that might be None, use the default parameter:

```python
from ascerta import get_context

# Use default values for keys that might be None
context = get_context()
user_id = context.get('user_id', "anonymous")
limit_ids = context.get('limit_ids', [])
```

### 3. Treat Context as Read-Only

The context object returned by `get_context()` should be treated as read-only. Any changes to the context do not change the current execution context:

```python
from ascerta import get_context, track_context

# Don't do this - modifying the returned context doesn't affect the actual context
context = get_context()
context.user_id = "new_user"  # This won't change the actual context

# Instead, use track_context to set new values
with track_context(user_id="new_user"):
    # Now the context has the new user_id
```

### 4. Use Context for Runtime Decisions

The primary value of `get_context()` is for making runtime decisions based on the current execution context:

```python
from ascerta import get_context

def select_appropriate_model():
    """Select the appropriate model based on the current context."""
    context = get_context()
    
    # Check if this is a premium use case
    use_case = context.get('use_case_name', '')
    if "premium" in use_case.lower():
        return "gpt-4"
    
    # Check if we're in a high-priority flow
    if context.get('use_case_step', '') in ["critical", "high_priority"]:
        return "gpt-4.1"
    
    # Default to more economical model
    return "gpt-3.5-turbo"
```

## Related Functions

### Context Management Functions

While `get_context()` is used to access context values, these functions are used to create and manage contexts:

* [`ascerta_instrument()`](/docs/configuring-payi_instrument) - Initializes the SDK and establishes the global context
* [`@track`](/docs/track-decorator) - Function decorator that creates a context for the decorated function
* [`track_context()`](/docs/track_context) - Context manager that creates a context for a block of code

For details on how context values are inherited, combined, or overridden across different levels, see [Parameter Precedence in Ascerta Instrumentation](/docs/parameter-precedence-in-pay-i-instrumentation).