JqField component, the
Studio host injects the design system and installs the evaluation worker, and the
flow editor renders that field directly. The same editor serves every jq field on
every Studio surface — a host field, another plugin’s field, a flow’s field — with
nothing to register and no gating.
The editor itself — its node vocabulary, the faithfulness guarantee, the theming
contract, and the worker model — is documented with jq-studio
and in its open-source repository. This page
covers what is specific to authoring a flow: the field’s tabs and what each field
seeds the editor with.
Inline or Template
A jq field in the flow editor is a two-tab control — Inline and Template — and the two are mutually exclusive: the wire carries exactly one.- Inline is the SDK’s
JqField: a resting text control holding the jq, plus a Visual editor button that opens the visual canvas in a modal dialog. Edit the jq as text in the control, or open the dialog to build it as a node graph; on save the dialog writes the jq back to the same control. Adescriptionand anerrorhelper slot render under the control, wired to it for screen readers. - Template picks a stored template and edits its kwargs through a schema-assisted form.
What each field seeds
Every jq field follows one rule for what it reads:. holds only the data the
expression is about, and everything the platform adds beside it — the state
documents, the run identity, the loop context — arrives as a named jq variable
(the platform-wide rule). So each field names what . is
at its site, and the editor’s Test panel seeds a sample of that shape plus a
skeleton for each variable the site binds; where the engine exposes a matching
validator, the Validate action checks the same shape server-side:
- a node expression and a conditional or branch condition see the node
envelope — the run’s inputs and the upstream nodes’ outputs, with this node’s
.resultstill null (a condition must return true or false); - an On Error condition or expression sees the error envelope — the failed
node’s error on
.upstream_outputs(.error,.error_type,.error_kind,.additional); - the flow-level On Error’s Reply sees the same error envelope, with the handler’s
outcome under
.upstream_outputs.additional(.handler_result, or.handler_errorwhen the handler failed), and must return text ornull(the participant reply); - a node’s return expression sees the narrow return namespace — only
.result,.outputs, and.flow_graph_kwargs; here.upstream_outputsis a hard build error, not a null; - a binding’s input injection jq runs after the node’s input is assembled, before the node runs: a
template
inputprogram sees the record (.is the subject’s document at the attach path) with its declaredparamsbound as the single object$params; a custom injection reads the bound record as.with$inputthe node’s input so far, and its value is placed into the input at the injection’sintofield; - a binding’s update jq runs after the node completes and reads the node’s
output as
.: a templateupdatepicks a named update program and shapes its declared input through an adapter (.the node output,$inputthe run input), while a custom update reads.the node output with$recordthe bound record and$inputthe run input and returns the template-relative op batch ([{op, path, value}]), where a per-op compare-and-set guard rides an op as{path, expected}; - an update’s op-id jq reads the node’s output as
.with$inputthe run input, and returns the key the write dedupes on; - a binding’s subject and scope expressions see the bare flow inputs document
(
.isflow_graph_kwargs, no envelope;scope_exprmust return true or false); - a holder node’s Cancel, Resume, Start, and warm-start jqs see the
node envelope with the held target’s parked interactions bound as
$parked; - a loop’s
whilecondition sees the node envelope with$iteratepresent —$iterate.itemis always null there, while$iterate.prior_outputsholds the per-iteration results the condition tests; - a loop’s
foreachexpression and a string loopcountsee the node envelope — for aforeachdriver$iterateis the enclosing loop, not this one; acountruns jq only when the count is a string (a literal number bypasses it); - a map item argument sees the loop-body envelope, where
$iterate.itemis the current item (never null here) and$iterate.iterationits zero-based position.
.outputs.<node> and .inputs.<node> hold a node’s results in order,
newest last, for each node some expression of the flow names there; the run state keeps no
history of a node no expression reads that way (see Run state). An
expression that reads .outputs or .inputs as a whole — .outputs | keys, getpath(...),
.., a function over the channel — or uses a construct the engine does not analyse (an inline
def, an assignment, label, destructuring) makes the flow keep every node’s full history;
Validate reports it as a state_read_unbounded warning naming the expression, and the
flow still saves and runs. At run time each expression receives only the .outputs /
.inputs entries it names (a channel it reads as a whole, it receives whole), so its result
is the same, and its evaluation’s trace record shows just those entries.
The variables beside the input
Beside., every flow jq binds the run’s context as named variables, reachable
anywhere in the expression — inside a map(...) or select(...) too, where . is
rebound. The editor lists them on each field and seeds a sample for each in the Test
panel:
A holder node’s start, cancel, resume and warm-start jqs add
$parked — the
parked interactions on the held target, a list of {id, status, …} (status asking,
running, finished, or failed). A state-binding jq adds $input (the run
input) and, on a custom update, $record (the subject’s committed record). A read of
an undeclared variable is a compile-time refusal at save, never a silent null. A
call to a template jq (tjq_<name>({…})) is checked at save against the templates
attached to the flow’s bound states where the flow is validated by name (the editor’s
save, a route bind), and admitted on a preset write, which carries no environment; a
run where the template is not attached refuses it loudly. The names the platform binds
cannot be rebound with ... as $name.
Autocomplete from a state’s template jq
A jq field that can reach a bound state offers autocomplete from the template jq of the templates attached to that state. Typing offers eachpurpose: "input" template jq by name and inserts its call
handle — tjq_<name>({…}), or tjq_<template>__<name>({…}) when a name is
shared across the state’s attachments — so an expression reads a template’s value
through the prelude without hand-writing the def. The suggestions come from the
served state-template document’s template_jq for the
bound state’s templates, so they track whatever the attachment declares.
See also
- jq variables — the one rule for a jq’s input and its named variables, across every platform surface.
- The jq editor — jq-studio, the built-in editor the flow editor renders, and how to embed it in your own app.
- The visual jq editor — the editor as it appears in the flow canvas: its node vocabulary, the faithfulness guarantee, and the editor shell.
- Babelfish Flows — the flow engine whose fields author through this editor.
- Author a Studio plugin — the SDK re-export every plugin field renders the same editor from.

