# How to Track Which Parameters Were Called During Hypster Instantiation

> Learn how to track parameters called during Hypster instantiation using HP.called_params and the instantiate wrapper. Simplify your configuration tracking.

- Repository: [Gilad Rubin/hypster](https://github.com/gilad-rubin/hypster)
- Tags: how-to-guide
- Published: 2026-03-02

---

**Hypster automatically records every parameter your configuration function accesses through the `HP.called_params` set and the `instantiate` wrapper's delta calculation mechanism.**

The `gilad-rubin/hypster` library provides built-in parameter tracking to help you debug configurations and detect unused values. When you call `instantiate()`, Hypster captures exactly which parameters were accessed during the configuration function's execution, enabling you to identify unreachable parameters or validate that nested configurations behave as expected.

## How Parameter Tracking Works in Hypster

Hypster implements parameter tracking through two coordinated mechanisms in the `HP` class and the `instantiate` wrapper.

### The `called_params` Set in `HP`

Every `HP` instance maintains a `called_params` attribute—a Python `set` that stores the full parameter paths accessed during configuration.

In [`src/hypster/hp.py`](https://github.com/gilad-rubin/hypster/blob/main/src/hypster/hp.py) (lines 55-56), the `HP` class initializes this set during construction:

```python

# From src/hypster/hp.py L55-L56

self.called_params: Set[str] = set()

```

When you invoke any public API method—such as `hp.int()`, `hp.float()`, or `hp.select()`—the implementation adds the parameter's full path to this set. For example, in the `_int` method (lines 39-61), the code executes `self.called_params.add(full_path)` to record the access.

### The `instantiate` Wrapper Delta Calculation

The `instantiate` function in [`src/hypster/core.py`](https://github.com/gilad-rubin/hypster/blob/main/src/hypster/core.py) (lines 52-66) wraps your configuration function to compute which parameters were actually used:

```python

# Conceptual flow from src/hypster/core.py L52-L66

original_called_params = hp.called_params.copy()

# ... execute config function ...

called_params = hp.called_params - original_called_params

```

This delta calculation isolates exactly which parameters the current instantiation accessed, excluding any parameters tracked during previous nested calls or prior executions.

## Accessing Called Parameters After Instantiation

To inspect which parameters were accessed, you must obtain the `HP` instance after `instantiate` completes. Since the standard `instantiate` call returns only your configuration function's result, modify your config function to return the `HP` object itself:

```python
from hypster import instantiate, HP

def cfg_with_hp(hp: HP):
    hp.float(0.01, name="learning_rate")
    hp.int(32, name="batch_size")
    return hp  # Return the HP object to access called_params

values = {
    "learning_rate": 0.001, 
    "batch_size": 64, 
    "unused_param": "ignored"
}

hp_instance = instantiate(cfg_with_hp, values=values)
print(hp_instance.called_params)

# Output: {'learning_rate', 'batch_size'}

```

The `called_params` set contains only `'learning_rate'` and `'batch_size'`, confirming that `unused_param` was never accessed during instantiation.

## Tracking Parameters in Nested Configurations

When using `hp.nest()` to compose configurations, Hypster maintains a shared `called_params` set across parent and child `HP` instances. In [`src/hypster/hp.py`](https://github.com/gilad-rubin/hypster/blob/main/src/hypster/hp.py) (lines 82-90), the `nest` method ensures the child `HP` inherits the parent's `called_params` set:

```python
def outer(hp):
    hp.nest(inner, name="submodule")
    hp.int(10, name="threshold")
    return hp

def inner(hp):
    hp.select(["a", "b"], name="mode")
    return hp

hp = instantiate(outer, values={"submodule.mode": "b", "threshold": 5})
print(sorted(hp.called_params))

# Output: ['submodule.mode', 'threshold']

```

The output demonstrates that nested parameters report their full path—including the namespace prefix—allowing you to distinguish between `submodule.mode` and top-level parameters.

## Detecting Unknown or Unused Parameters

The `instantiate` wrapper uses the `called_params` delta to identify values provided by the user but never accessed by the configuration function. You can control this behavior using the `on_unknown` parameter:

```python
values = {"learning_rate": 0.01, "unknown_param": 42}

try:
    instantiate(cfg, values=values, on_unknown="raise")
except ValueError as e:
    print(e)
    # -> Unknown or unreachable parameters: 'unknown_param'

```

In [`src/hypster/core.py`](https://github.com/gilad-rubin/hypster/blob/main/src/hypster/core.py) (lines 62-66), the `_handle_unknown_parameters` function compares the provided value keys against the `called_params` set computed during instantiation. When `on_unknown="warn"`, it emits a warning; when set to `"raise"`, it raises a `ValueError` listing the specific parameters that were supplied but never accessed.

## Summary

- **Hypster tracks parameter access** through the `HP.called_params` set, which stores full parameter paths including nested namespaces.
- **The `instantiate` wrapper** computes a delta of accessed parameters by comparing the set before and after configuration function execution.
- **Nested configurations** share the same `called_params` set, recording full paths like `submodule.parameter_name`.
- **Unknown parameter detection** compares provided values against `called_params`, allowing you to raise errors or warnings for unused inputs via the `on_unknown` argument.

## Frequently Asked Questions

### What is the `HP.called_params` attribute?

The `HP.called_params` attribute is a Python `set` initialized in [`src/hypster/hp.py`](https://github.com/gilad-rubin/hypster/blob/main/src/hypster/hp.py) that records every parameter path accessed during configuration. Each time you call a parameter method like `hp.int()` or `hp.select()`, Hypster adds the parameter's full name—including any namespace prefixes—to this set. After instantiation, you can inspect this set to see exactly which configuration options your code actually used.

### How does the `instantiate` wrapper track parameter usage?

The `instantiate` function in [`src/hypster/core.py`](https://github.com/gilad-rubin/hypster/blob/main/src/hypster/core.py) implements a snapshot-and-diff mechanism. Before executing your configuration function, it copies the current state of `hp.called_params`. After the function completes, it subtracts the original set from the updated set to produce a delta containing only the parameters accessed during this specific instantiation. This delta powers the unknown parameter detection and provides a clean record of which values were actually consumed.

### Can I track parameters in nested Hypster configurations?

Yes. When you use `hp.nest()` to compose configuration functions, Hypster ensures that nested `HP` instances share the same `called_params` set as their parent. As implemented in [`src/hypster/hp.py`](https://github.com/gilad-rubin/hypster/blob/main/src/hypster/hp.py), the child `HP` inherits the parent's set, so parameter accesses within nested namespaces—like `submodule.mode`—are recorded with their full path in the parent's `called_params` set. This allows you to track parameters across complex, hierarchical configuration trees.

### How do I detect unused parameters in my configuration?

To detect unused parameters, provide the `on_unknown` argument to `instantiate`. When set to `"raise"` or `"warn"`, Hypster compares the keys in your `values` dictionary against the `called_params` set computed during instantiation. Any parameters present in `values` but missing from `called_params` are considered unknown or unreachable. With `on_unknown="raise"`, Hypster raises a `ValueError` listing these parameters; with `"warn"`, it emits a warning while continuing execution.