Dynamic behaviour

The three optional author-time hooks — loadOptions, resolveConfigSchema and resolveOutputs — that let a node offer live dropdowns and resolve its own fields and ports from a connected system.

Three optional methods on INode are what separate a node that asks an author to type a field name from one that offers them the real list. All three run while the workflow is being edited, never during a run.

HookResolves
loadOptionsThe options of a select or multiselect field — a live, dependent dropdown.
resolveConfigSchemaThe flat set of typed fields that replaces a dynamic-schema marker field.
resolveOutputsThe output ports of a port set marked as resolved rather than statically named.

Generic API Call is the shipped example that uses all three: pick a resource, and the operations for it appear; pick an operation, and that operation's parameters appear as real fields with a response port shaped like its response.

They run at author time, and the result is saved

This is the single most important property, and it explains most of the behaviour that surprises people:

  • The hooks are called while an author is editing the node.
  • What they return is captured into the workflow when the author saves.
  • Nothing is resolved again at run time.

So a saved workflow keeps executing the shape it was built against, even if the far system's schema shifts underneath it. That is deliberate — a workflow whose fields could change under it overnight is not something you could operate — and it means a change on the far side needs an author to re-open and re-save the node.

It also means these hooks must not have side effects. Read, do not write: they run every time somebody opens the node, including while they are still deciding.

What the hooks are given

An author-time context, close to but not the same as the runtime one:

  • config — the author's current, partial config values. This is how a dependent dropdown knows what has already been chosen.
  • secrets.get(key) and credentials.get(id) — the same resolvers as at run time, so a hook that has to authenticate against the far system uses the credential the author already picked.
  • signal and logger — as at run time. Honour the signal: an author who types quickly cancels a lot of in-flight resolutions.
  • search — set only for loadOptions: the author's type-to-search term. Pass it to the far system's search endpoint where there is one, or filter with it locally.
  • locale — the author's preferred locale for labels, when supplied.

dependsOn, and why a dependency cannot be an expression

A field declares which other config keys drive its resolution. When one of those changes, the editor re-resolves.

A key listed as a dependency must be a literal — it may not accept an expression. The reason is direct: its value has to be known while the author is editing, and an expression's value is only known at run time. So a dropdown can depend on "which resource did you pick", but it cannot depend on "whatever the previous node emitted".

Design for that. Put the choices that shape the node's own schema in literal fields, and let the data arrive through expression-capable fields — see Node configuration.

Failing well

An author-time hook that throws leaves somebody staring at an empty dropdown. Two habits:

  • Return an empty list rather than throwing when the far system answered but had nothing, and log why.
  • Say what is missing through the logger when a credential has not been chosen yet — the most common reason a hook cannot resolve anything is that the author has not filled in the field it depends on.

Where a resolution genuinely cannot happen yet, a statically declared fallback port keeps the canvas wireable until it can.

Where to go next

Was this page helpful?