---
sidebar:
  label: roboto.templating.substitution
  order: 0
title: roboto.templating.substitution
---
## Module Contents

### MappingResolver

```python
class roboto.templating.substitution.MappingResolver(values: Mapping[str, Any])
```

`from roboto.templating import MappingResolver`

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/templating/substitution.py#L45-L57)

A [`VariableResolver`](/reference/python-sdk/roboto/templating/substitution#roboto.templating.substitution.VariableResolver) backed by a flat `name -> value` mapping.

Values are coerced to `str` on access; a missing key or a `None` value resolves to `None` (leaving the placeholder unexpanded).

**Parameters**

- **values** (`Mapping[str, Any]`)

#### MappingResolver.resolve()

```python
def resolve(name: str) -> Optional[str]
```

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/templating/substitution.py#L55-L57)

**Parameters**

- **name** (`str`)

**Returns**

- `Optional[str]`

### PLACEHOLDER_RE

```python
roboto.templating.substitution.PLACEHOLDER_RE
```

`from roboto.templating import PLACEHOLDER_RE`

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/templating/substitution.py#L10-L10)

Recognizes `{{name}}` placeholders. Names start with a letter or underscore; dots are allowed so dotted names (`{{dataset.id}}`, `{{action.name}}`) work as a namespace convention for entity-bound expansion by a [`VariableResolver`](/reference/python-sdk/roboto/templating/substitution#roboto.templating.substitution.VariableResolver). The engine treats the full dotted string as one opaque key — the resolver decides what, if anything, it expands to.

### VARIABLE_NAME_RE

```python
roboto.templating.substitution.VARIABLE_NAME_RE
```

`from roboto.templating import VARIABLE_NAME_RE`

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/templating/substitution.py#L17-L17)

Mirrors [`PLACEHOLDER_RE`](/reference/python-sdk/roboto/templating/substitution#roboto.templating.substitution.PLACEHOLDER_RE) so every declared variable name is referenceable by `{{name}}`.

### VariableResolver

```python
class roboto.templating.substitution.VariableResolver
```

`from roboto.templating import VariableResolver`

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/templating/substitution.py#L23-L42)

Bases: `Protocol`

Decides what each `{{name}}` placeholder expands to during substitution.

Implementations bind placeholders to a source of values — a flat mapping for agent launch, or a lazily-hydrated event namespace for triggers — keeping the substitution engine itself agnostic to where values come from.

#### VariableResolver.resolve()

```python
def resolve(name: str) -> Optional[str]
```

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/templating/substitution.py#L31-L42)

Return the substitution string for placeholder `name`, or `None`.

**Parameters**

- **name** (`str`): The placeholder name written between `{{` and `}}`, dots included (e.g. `dataset.id`).

**Returns**

- `Optional[str]`: The string to splice in, or `None` to leave the literal `{{name}}` in place.

### collect_placeholders()

```python
def roboto.templating.substitution.collect_placeholders(node: Any) -> set[str]
```

`from roboto.templating import collect_placeholders`

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/templating/substitution.py#L60-L72)

Return every `{{name}}` placeholder found in the string leaves of `node`.

`node` is the JSON form of a template (nested dicts, lists, scalars). Only string *values* are scanned; placeholder syntax in dict keys is rejected so a templated key can't silently collapse two entries into one.

**Parameters**

- **node** (`Any`)

**Raises**

- `ValueError`: A dict key contains `{{...}}` placeholder syntax.

**Returns**

- `set[str]`

### substitute()

```python
def roboto.templating.substitution.substitute(
    node: Any,
    resolver: VariableResolver,
) -> Any
```

`from roboto.templating import substitute`

[Source](https://github.com/roboto-ai/roboto-python-sdk/blob/main/src/roboto/templating/substitution.py#L92-L106)

Return a copy of `node` with each `{{name}}` in a string leaf expanded via `resolver`.

Embedded and repeated placeholders within one string are supported. A name the resolver returns `None` for is left as the literal `{{name}}`; callers that require full resolution validate the placeholder set up front with [`collect_placeholders()`](/reference/python-sdk/roboto/templating/substitution#roboto.templating.substitution.collect_placeholders).

**Parameters**

- **node** (`Any`)
- **resolver** (`VariableResolver`)

**Returns**

- `Any`
