Scope Resolvers

What It Is

Scope is the set of named values and helper functions an expression can reference where it runs. Jetstack distinguishes two scopes that matter most for builders:

  • automation scope — what an automation action can read while it runs
  • canvas scope — what a canvas item can read while it renders

Both scopes feed the same code processor, but each exposes a different set of roots. This chapter is a reference for what those roots are, why scope behaves differently in different places, and how to think about choosing values in builder configuration.

Why It Matters

Scope explains:

  • why a token like iteratorItem resolves in one position of the canvas tree and not in another
  • why an expression that works in an automation may not work the same way in a canvas
  • why some helpers are available everywhere (today(), concat(...)) while others are scope-specific (trigger(...), iteratorItem)
  • why a chain like currentUser.created_by.email traverses relations through typed properties and not through arbitrary fields

Without a clear understanding of scope, builder-assisted configuration becomes guesswork.

The Shared Core

Both scopes share the code processor's universal helper catalog: literals, operators (+, -, ==, &&, ??, ? :, …), date helpers (today, formatDate, …), string and collection helpers (concat, length, map, …), casting helpers (toBool, toString, …), crypto helpers, and so on. The full reference is in Code Processor Functions.

What differs between the two scopes is the roots — the named entry points that bring runtime data into the expression.

Automation Scope

Automation scope is centered on execution context. Depending on the running automation and action, it exposes:

Root / helperWhat it brings in
trigger('name')A parameter from the trigger that started the automation
endpoint('name')A parameter returned by the previous endpoint in the action chain
var('name')A local automation variable
env('name')A tenant-wide environment variable from app settings
templateVar('name')A variable from the surrounding page template (when one exists, e.g. web-triggered automations)
appParameter('name')A request/route parameter
dataQuery(...)The current data-query helpers (when relevant)
getSecret('name'), saveSecret(...)Access to the tenant secret store

This makes automation expressions a good fit for branching, routing, integration payloads, and scheduling.

Canvas Scope

Canvas scope is centered on interactive UI context. The roots exposed to a canvas item's expressions are:

Tree-position-derived roots

RootResolves to
iteratorItemThe current iteration item of the nearest iterator-role ancestor
iteratorIndexThe zero-based position in that iteration
parentObjectThe pinned object of the nearest non-iterator object wrapper

iteratorItem follows the nearest iterator (GeneralIterator, QueryIterator, TableGeneralIterator, or any item with iterate set). parentObject skips iterators and follows the nearest stable object wrapper. The truth table for typical nestings is documented in Canvas Items And CanvasBuilder — Tree-Position-Derived.

Always-available roots and helpers

Root / helperWhat it brings in
currentUserThe currently authenticated user resource
var('name')A canvas-level variable set by Set variable items or by preload automation
templateVar('name')A variable from the surrounding page template
env('name')A tenant-wide environment variable from app settings
appParameter('name')A request/route parameter
selection()The selection app parameter, combined with the current id
formStatus('formId')Submission status for a form by its form id
queryResultCount(queryId)Row count for a stored Query
queryResultCalc(queryId, 'propId', 'code')Calculation result for a stored Query
getSecret('name')Access to the tenant secret store

Property traversal through relations

When a root resolves to a typed object (e.g. currentUser, or iteratorItem inside an iterator with a fixed typeId), expressions can chain through its properties using dot notation: currentUser.email, iteratorItem.created_by.first_name, parentObject.linked_query.parent.id. Each step is resolved through the canvas's property model — relations cross into the related type, primitives terminate the chain.

The canvas builder uses this same model to power its type-aware autocomplete: when it can statically determine the type at the cursor's position, it offers the type's properties as suggestions.

Choosing The Right Kind Of Value

A common canvas design question is whether a parameter should be:

  • a literal — when the value is presentational and static
  • a context root reference — parentObject.title, iteratorItem.email, currentUser.id — when the value should follow the surrounding object or iteration
  • a function call — appParameter('id'), formStatus('contactForm'), today() — when the value comes from a helper
  • a composed expression — concat('Hello, ', currentUser.first_name, '!'), iteratorItem.price * 1.21, currentUser.email ?? 'guest' — when several sources combine

If a single parameter expression starts pulling in too many sources or branches, consider moving the logic upstream: into a Set variable item, into preload automation, or into a model-level calculated property.

Failure Modes

Common scope problems include:

  • referencing a root that does not exist at this position — e.g. iteratorItem in a subtree that has no iterator ancestor
  • chaining past a primitive — once a chain lands on a string/int field, it is a leaf
  • expecting a value from a dynamically-typed root — when an iterator's typeId is itself an expression, the autocomplete falls back to the bare root and chained fields are not introspectable
  • reusing an automation expression inside a canvas verbatim — trigger(...) and endpoint(...) are automation-only roots
  • expecting a scalar where the path resolves to an object or array — coerce explicitly with toString(...), toInt(...), etc., when the consuming parameter is a scalar type

Best Practices

  • Keep chains short enough that another implementer can read them at a glance.
  • Prefer stable roots: currentUser, parentObject inside a wrapper, iteratorItem inside an iterator.
  • When you find yourself writing the same long chain repeatedly, factor it out into a Set variable item near the top of the canvas, or into preload automation.
  • Use the type-aware autocomplete in the canvas editor to verify that a chain segment actually exists — if the editor doesn't suggest it, the chain probably won't resolve.
  • When an expression becomes hard to explain in one sentence, split it into intermediate variables or move the logic into an automation.