What you can write in an expression field, and what is in scope when it runs.
Application source is compiled by applications/main/src/templates/declarative/authoring-expressions.ts into
closed Expression data. Server and browser evaluate that data through the same generic interpreter;
no source evaluation or native callback registry runs at execution time.
| Slot | Lives on | Decides | Evaluated |
|---|---|---|---|
startExpression | template | Compatibility metadata only | Not activated as a start gate |
expression | condition step | Which branch? | When the step executes |
expression | automatic step | What value to store | When the step executes |
completeExpression | input step | May this step be finished? | Every completion attempt |
visibleExpression | field, view control | Show or hide | On render |
waitUntilExpression | wait step | Until when to park | Once, on arrival |
Plus two interpolation forms, which substitute rather than decide:
| Form | Where | Purpose |
|---|---|---|
${step.field} | defaultValue, message bodies | Insert a context value |
{{ … }} | view controls, downloadFilename | Supported authoring expression, compiled to closed data |
Accumulated context, keyed by step key:
input_description.description // a field written by an earlier step run.dealName // a run input, from template.runInputs currentProcess.url // built from APP_BASE_URL
completeExpression additionally gets hasPermission("name").
View controls and {{ }} get a wider surface: step keys, keccak256,
generatePayload, Date, Math, JSON.
conditionexpression: "review_description.description_review_ok === true", thenStepKey: "input_risk_model_availability", elseStepKey: "input_description",
inputcompleteExpression: "trim(input.name).length > 0 && trim(input.contractAddress).length > 0 && " + "trim(input.contactPlatform).length > 0 && trim(input.contact).length > 0 && " + "trim(input.agent).length > 0 && trim(input.wallet).length > 0",
integrator-onboarding marks no fields mandatory and enforces completeness
entirely through this expression.
{ key: "description_review", type: "string", title: "Provide feedback for the Prime",
visibleExpression: "review_description.description_review_ok === false" }
waitwaitUntilExpression: "nextUtcWeekdayTime(1, 20, 0)", // next Monday 20:00 UTC
{ key: "_view_0", type: "string", title: "Feedback from OEA",
readOnly: true, defaultValue: "${review_description.description_review}" }
{ title: "Payload", data: "{{ generatePayload(context) }}", plainText: true }
| Owner | Provides |
|---|---|
| Platform presentation scope | Explicit process/user metadata, permissions and time |
| Domain declarative definitions | Prime, dates (including isoDateAddDays and cadenceDates for choice recipes), amounts and EVM/Solana protocol expressions |
| App authoring compiler | Source lowering, helper expansion and named render macros |
| Canonical service / generic Forms | Completion validation and compiled field presentation |
completeExpression vs mandatoryBoth enforce completeness. They are not interchangeable.
mandatory | completeExpression | |
|---|---|---|
| Scope | one field | the whole step |
| Enforced | runner and service | server-side, on every completion |
| Sees | that field | all context |
| Skipped for hidden / read-only fields | yes | no |
Use completeExpression when the rule spans fields or is conditional. If a step will not
complete and nothing looks required, read its completeExpression — the API distinguishes authorization from invalid interaction data; inspect its error code
rather than assuming every refusal means missing permissions.
input.foo && input.foo.length > 0, never
input.foo.length > 0 on a field that may not be written yet.${…} substitutes; {{ … }} computes. They are not interchangeable.mandatory field does not block completion, so visibleExpression and
mandatory interact — prefer completeExpression for conditional rules.The source language is deliberately closed, not arbitrary JavaScript. Unknown calls/source are
rejected before registration. Predicate/display adapters handle expected semantic failures under
their documented policy; resource and invalid-AST defects cannot be hidden as ordinary validation.
enabledExpression remains source metadata without execution gating. Known failure recovery is
separate from uncertain external outcomes; see durability.