Workflow expressions
Workflow fields that accept a formula use double curly braces around an expression:
{{ workflow_inputs.query }} Inside {{ … }}, A1KnowHow evaluates Expr — a small expression language (not Python, JavaScript, or Jinja). As soon as you type {{ in the editor, suggestions appear for workflow inputs and earlier step outputs.
For a plain-language overview of chaining steps, see Workflow authoring. For formula-heavy transforms between steps, see Data preparation.
Try it: open the Expr playground to experiment with built-in functions. For the full language reference, see the Expr language definition.
Where expressions appear
| Location | Example | Notes |
|---|---|---|
| Step input (From expression) | {{ steps.search.outputs.results }} | Whole value is one expression |
| Agent / tool prompts and config | Hello {{ name }} | Mix literal text with inline expressions |
| Condition choice | {{ len(steps.search.outputs.results) > 0 }} | Must evaluate to true or false |
| Data preparation formula | {{ sum(numbers) }} | One expression per output mapping |
| Loop input mapping | {{ context.loop_item }} | Per-iteration values in the parent loop |
On agent prompts, prefer bare step-input names ({{ content }}) after you wire earlier outputs into Inputs — see wiring values into agent steps.
Values you can read
| Source | Example |
|---|---|
| Workflow inputs | {{ workflow_inputs.title }} |
| Earlier step outputs | {{ steps.summarize.outputs.summary }} |
| Current step inputs (short name) | {{ content }} after you add an input named content |
| Loop iteration (parent loop mappings only) | {{ context.loop_item }}, {{ context.loop_index }} |
Names use letters, digits, and underscores (for example step_1, not spaces).
Practical recipes
Pass search results into an agent
- Add a step input on the agent (for example
content, type string, From expression). - Set the expression to
{{ steps.search_workspace.outputs.results }}. - In the prompt, write
{{ content }}where the results should appear.
Join a list into readable text
{{ join(steps.search.outputs.results, '
') }} With a field per item (objects):
{{ join(map(steps.rag.outputs.chunks, .content ?? ''), '
') }} # is the current element inside map / filter. For objects, use .field.
Clean up strings
{{ trim(workflow_inputs.email) }}
{{ lower(workflow_inputs.email) }}
{{ replace(steps.draft.outputs.text, '
', ' ') }}
{{ split(steps.import.outputs.csv_line, ',') }} You can chain methods with |:
{{ workflow_inputs.name | lower() | trim() }} Branch when a list is non-empty
{{ len(steps.search.outputs.results) > 0 }} {{ workflow_inputs.mode == 'deep' ? 'detailed' : 'brief' }} Parse agent or tool JSON, then read a field
Agent/tool outputs with JSON format are still text until you parse them:
{{ parse_json(steps.extract.outputs.raw_json).title }} Turn a value back into JSON text:
{{ json(steps.collect.outputs.data) }} Prefer parse_json and json in A1KnowHow. Avoid filter-style | tojson — that is not how Expr works here.
Safe access when a value might be missing
{{ steps.search.outputs.results[0].title ?? 'No title' }}
{{ steps.agent.outputs.user?.name ?? 'Anonymous' }} Use ?. when a middle value may be empty, and ?? for a fallback.
Dates (YYYY-MM-DD)
Date strings should use layout 2006-01-02 (year-month-day). Common patterns:
| Goal | Expression |
|---|---|
| Today | {{ now().Format("2006-01-02") }} |
| Days between two dates | {{ floor((date(end_date, "2006-01-02") - date(start_date, "2006-01-02")).Hours() / 24) }} |
| Days until due (negative if overdue) | {{ floor((date(due_date, "2006-01-02") - date(now().UTC().Format("2006-01-02"))).Hours() / 24) }} |
See Data preparation for full step examples with inputs and outputs.
Useful functions
A1KnowHow helpers
| Function | Purpose |
|---|---|
parse_json(text) | JSON text → value (object, array, or scalar) |
json(value) | Value → JSON text string |
Strings
| Function | Example |
|---|---|
trim / trimPrefix / trimSuffix | {{ trim(text) }} |
lower / upper | {{ lower(email) }} |
split / join / replace | {{ join(labels, ', ') }} |
hasPrefix / hasSuffix | {{ hasPrefix(url, 'https://') }} |
indexOf / lastIndexOf | {{ indexOf(text, ',') }} |
repeat | {{ repeat('-', 3) }} |
Lists and numbers
| Function | Example |
|---|---|
len | {{ len(items) }} |
first / last | {{ first(items) ?? 'none' }} |
map / filter | {{ filter(items, len(#) > 1) }} |
sum / min / max | {{ sum(scores) }} |
all / any | {{ any(errors, len(#) > 0) }} |
Dates
| Function | Notes |
|---|---|
now | Current time; often .UTC().Format("2006-01-02") for a date string |
date | Parse a date string with a layout |
floor | Whole calendar days when dividing duration hours by 24 |
Many more built-ins (sort, keys, values, reduce, and others) are documented in the Expr language definition. Practice them in the Expr playground.
Lists in MCP tool arguments
MCP tools often expect a list (for example urls). In the visual editor:
- Enter a JSON array such as
["https://a.example", "https://b.example"], or a list with expression elements like["{{ join(['https://a.example/', symbol]) }}"]. The editor stores a real list (not a quoted string). - Or enter a whole expression that evaluates to a list, such as
{{ steps.select.outputs.urls }}or{{ [join(['https://a.example/', symbol])] }}.
Do not wrap the whole field as a YAML string that looks like JSON (for example urls: "[\"{{ … }}\"]"). That sends a string to the tool and fails list validation.
Common pitfalls
- Wrong root name — use
workflow_inputs, notworkflowInputs. - Missing braces on step inputs — From expression values need a full
{{ … }}expression. - Referencing a later step — only earlier steps’ outputs are available.
- Empty list index —
arr[0]on an empty list is empty; preferfirst(arr) ?? 'default'. - Condition must be boolean — wrap lists with
len(...) > 0(or similar); a bare list is not true/false. - Loop context —
context.loop_itemonly works in the parent loop step’s input mappings, unless you map those values into the child workflow. - Backslashes in YAML — for a newline separator in YAML, escape carefully (for example
join(phrases, '\\n')in a double-quoted string). - MCP list args as quoted JSON — store a real list or a whole
{{ … }}list expression; a string like"['a','b']"is not a list.
Related guides
- Workflow authoring — steps, chaining, conditions
- Data preparation — formula outputs between steps
- Loop steps — per-item mappings and
context.loop_* - Expr language definition — full built-in list
- Expr playground — try expressions interactively