Interpolation is how an Action passes
fleet-specific values into the external work it triggers. Every
interpolation-aware field accepts {{ ... }} expressions: trigger URLs, headers,
auth values, webhook payloads, PR titles and bodies, branch names, file contents,
labels, reviewers, and the name/properties of cascade-created entities and
relationships. The same syntax resolves identically across all six trigger types
(webhook, pull-request, terraform-cloud, atmos-workflow, atlantis, noop) and
inside cascade operations.
This is the lookup reference. There is one expression form per resolution root — Terrantula's interpolation is variable substitution, not a function language: there are no filters, pipes, conditionals, or calls. Each root below is documented man-page style: purpose → syntax → example → notes.
A trigger is resolved in two passes, in this order:
{{ secrets.<name> }} is replaced with the named
Secret's decrypted value, loaded from the project's encrypted store at
dispatch time. This runs first so secret values are in place before anything
else looks at the field.{{ ... }} expression — parameters,
entity, recommendations, run, operation — is substituted from the
run's context.The expression grammar is intentionally small: a {{, optional whitespace, a
dotted path (word characters, dots, and hyphens), optional whitespace, a }}.
Anything else is left untouched.
An unresolved variable renders as its own literal, not an empty string. If a
blueprint uses {{ entity.name }} but the run has no entity in context (a
collection-scoped Action, say), the field keeps the literal text
{{ entity.name }} rather than collapsing to "". This is deliberate: a missing
value surfaces loudly in the PR or payload instead of silently vanishing. The one
exception is {{ secrets.<name> }} — a missing or value-less secret fails the
run (see secretsnotes).
Path segments named __proto__, constructor, or prototype never resolve —
they short-circuit to the unresolved literal. This prototype-pollution guard
applies to every nested-path root (parameters, entity.properties,
entity.labels, recommendations.*.properties).
secretsPurpose. Inject a decrypted Secret value — a TFC API token, a GitHub token, an Atlantis API secret, a webhook HMAC secret — into a trigger's auth field, header, or payload. The catalog only ever names the credential; the value is set out-of-band and never lands in YAML.
Syntax.
<name> is the Secret's name. Names may contain word characters, dots, hyphens,
and colons.
Example.
Notes.
terrantula secrets set-value <name> --value ….parametersPurpose. Read an input collected when the Action was triggered. Parameters
are declared on the Action's parameters field and supplied per run (by the
operator in the UI/CLI, or by a cascade rule).
Syntax.
<path> may be nested (parameters.network.cidr) for object-valued parameters.
Example.
Notes.
entityPurpose. Reference the entity the Action is firing against — its name,
declared properties, and labels. Available on instance-scoped Actions
(associatedWith.scope: instance) and on cascade operations, where it refers to
the entity the cascade is acting on (for a create-entity operation, the
just-created entity).
Syntax.
Example.
Notes.
instance-scoped Actions and cascade operations. On a
collection-scoped Action there is no entity in context, so entity.*
references render the literal.{{ entity.id }} is deprecated: entities are now keyed by name, not a
UUID. Prefer {{ entity.name }} for new blueprints.entity.properties.* and entity.labels.* accept nested paths and are
prototype-pollution-guarded.recommendationsPurpose. Read a cell-ranked placement suggestion surfaced at trigger time.
When an Action declares recommendations, Terrantula ranks candidate
Cells and exposes the chosen target so the
trigger can wire the entity to the right pen — the core of the tenant-placement
cattle workflow.
Syntax.
<name> is the recommendation's declared name.
Example.
Notes.
<name>. An unresolved recommendation renders the literal.{{ recommendations.<name>.id }} is deprecated for the same reason as
entity.id; prefer .name..properties.* accepts nested paths and is prototype-pollution-guarded.runPurpose. Reference the firing ActionRun itself — its identifier and the callback channel an external workflow uses to report completion back to Terrantula.
Syntax.
Example.
Notes.
{{ run.id }} — the ActionRun UUID. Always safe to embed in PR bodies,
commit messages, or logs: it identifies a run for human reference but cannot
authorize anything on its own.{{ run.callbackUrl }} — the endpoint your external workflow POSTs to when it
finishes, so Terrantula can mark the run succeeded or failed.{{ run.callbackToken }} — the bearer token your workflow presents to that
endpoint. Format: {runId}:{expiresAtMs}:{hmac}. The HMAC-SHA256 signature is
computed with a key derived from the server encryption key and binds the token
to this run and this expiry (the Action's timeout, default 60
minutes). The callback endpoint verifies it in constant time and guards on run
status, so a token issued for one run cannot be replayed against another.
Because the binding — not the string's secrecy — is what protects it, the token
is safe to embed in a PR body or payload.operationPurpose. Inside a cascade createRelationship on a create-entity operation,
reference the entity the parent operation just created. This lets one Action
create an entity and wire its relationship atomically, without a second call.
Syntax.
Example.
Notes.
createRelationship block on a create-entity
operation. Anywhere else it renders the literal.createRelationship can point at it before the entity exists by any other
reference.| Expression | Available when | Pass | Miss behavior |
|---|---|---|---|
{{ secrets.<name> }} | always | secrets | fails the run |
{{ parameters.<path> }} | run supplied the parameter | variable | renders literal |
{{ entity.name }} / .properties.<p> / .labels.<p> | instance scope or cascade operation | variable | renders literal |
{{ entity.id }} | (deprecated — use entity.name) | variable | renders literal |
{{ recommendations.<name>.name }} / .properties.<p> | Action declares recommendations | variable | renders literal |
{{ recommendations.<name>.id }} | (deprecated — use .name) | variable | renders literal |
{{ run.id }} / {{ run.callbackUrl }} / {{ run.callbackToken }} | always | variable | renders literal |
{{ operation.entity.id }} | createRelationship on a create-entity op | variable | renders literal |
A single instance-scoped Action wiring every root together. Terrantula opens
this PR; your CI applies it — Terrantula never runs terraform apply itself.
{{ secrets.* }} surface and
how values are set out-of-band.