Skip to main content

!starlark

Compute configuration values with the Atmos Automation Language. Use functions, conditions, and loops to derive tags, names, lists, and maps from the component's merged configuration.

Usage​

Write a function body inside a !starlark YAML scalar. Use return to supply the value that replaces it:

vars:
stage: dev
region: us-east-2
resource_tags: !starlark |
return {
"Environment": ctx.vars["stage"],
"Region": ctx.vars["region"],
"Owner": ctx.metadata.get("owner", "platform"),
}

Atmos evaluates the code after imports, inheritance, and overrides have been merged. An inherited expression reads the consuming component's values. For example, overriding stage to prod produces an Environment tag of prod.

An expression is a scalar during inheritance. A higher-precedence expression or concrete value replaces that field; returned dictionaries are not deep-merged with lower-precedence values.

The returned dictionary becomes a YAML mapping. Strings, booleans, numbers, lists, and None also retain their types; None becomes YAML null.

Try it​

In an Atmos project with a Terraform component named service, add this component to a stack manifest:

vars:
stage: dev
region: us-east-2

components:
terraform:
service:
metadata:
owner: platform
vars:
resource_tags: !starlark |
return {
"Environment": ctx.vars["stage"],
"Region": ctx.vars["region"],
"Owner": ctx.metadata.get("owner", "platform"),
}

Inspect it with your project's stack name:

atmos describe component service -s <stack> --format json

The vars.resource_tags field contains:

{
"Environment": "dev",
"Region": "us-east-2",
"Owner": "platform"
}

Context​

The read-only ctx object exposes the effective component configuration. Access sections as attributes, then use dictionary indexing or .get() for values. Mappings also support iteration, .keys(), .values(), and .items().

ctx.vars
Merged component variables, including inherited values and overrides.
ctx.metadata
Component metadata. Use .get() for optional fields.
ctx.settings
Merged component settings.
ctx.env
The component's configured environment mapping. This is not the process environment.
ctx.locals
Local values available in the component configuration.
ctx.stack
The stack being evaluated.
ctx.component
The component instance name when evaluation has a component context.
ctx.component_type
The component type, such as terraform or helmfile, when available.

Missing configuration sections are empty mappings. Reading a missing key with ctx.vars["name"] fails; ctx.vars.get("name", "default") supplies a fallback. The context and its nested values cannot be modified. Build and return a new value instead.

Computed dependencies​

Values are resolved when accessed, so a computed field can depend on another computed field regardless of their order in YAML:

vars:
replicas: !starlark |
return ctx.vars["minimum_replicas"] * 2
minimum_replicas: !starlark |
return 3 if ctx.vars["stage"] == "prod" else 1
stage: prod

Here, replicas is 6. Each field is resolved once per component evaluation. A circular dependency fails with the configuration paths involved, rather than depending on YAML key order.

Go templates run before YAML functions. Starlark can read rendered values from ctx; a Go template cannot read the result of a !starlark expression in that same pass. Source inside !starlark is literal: {{ ... }} inside a Starlark string stays unchanged.

Functions and results​

A block is an implicit function body. It supports local variables, helper functions, loops, conditions, and early returns:

vars:
stage: dev
enabled_regions: [us-east-1, us-east-2]
deployment_names: !starlark |
def name(region):
return "%s-%s" % (ctx.vars["stage"], region)

return [name(region) for region in ctx.vars["enabled_regions"]]

The evaluator includes Starlark builtins, sum, round, and the json module. See the language overview for the language's syntax and Starlark background.

Return None, a boolean, string, finite number, list, or dictionary with string keys. Integers must fit a signed or unsigned 64-bit value. An empty list or dictionary remains empty. Falling through without a return produces null. Functions, sets, tuples, non-string dictionary keys, and cyclic collections are rejected as return values.

Evaluation scope​

Use !starlark in component configuration values within stack manifests. It computes values after structural merging; it does not generate imports, component names, inheritance rules, or stack identities. It is not supported in atmos.yaml or scaffold configuration.

The selector fields metadata.tags and metadata.labels reject !starlark. They determine component selection before full evaluation, while context reads can resolve dependencies that require authentication or execute commands.

This configuration evaluator provides ctx, language builtins, and json. Automation modules such as exec, fs, and steps, and module loading with load(), are unavailable here. Use automation scripts for commands, prompts, and other operations. Existing YAML functions referenced through ctx retain their own behavior, including any external reads they perform.

Each block has a budget of 100,000 interpreter steps. This catches runaway loops; it is not a hard memory or CPU limit. Evaluation errors include the configuration field and, for source errors, the originating filename and line.

Commands that support --skip !starlark preserve the expression without evaluating it.