Templates and expressions | Diaphora Docs | Diaphora

Templates and expressions

FML uses two expression systems, and mixing them up is the single most common source of bugs in a blueprint. The rule behind all of them is one sentence:

Go text templates always produce a string. Wrapped Expr $(...) preserves the real type.

This guide explains the three positions where expressions appear, why the string-vs-type distinction matters, and how to always pick the right one.

Prerequisites

Why there are two systems

A prompt is text, so interpolating a value into it should give you text, that's what Go templates do. But a tool argument might need a real array, object, or number, not a string that looks like one. Handing "[1, 2, 3]" (a string) to an argument that expects [1, 2, 3] (an array) is a type error waiting to happen. $(...) exists to pass the native typed value through untouched.

The three positions

Position Syntax Type Where
1. Text {{ ... }} Always string prePrompt/prompt text, context strings, call string args, set values, parameter defaults
2. Typed tool args $( ... ) Any (native) Only inside call argument values
3. Session conditions "..." (bare Expr) Bool / value expect="...", iterate="..."

1. Go text templates — {{ ... }}

Used anywhere the destination is text:

+ Research {{ .params.topic }} in the {{ .vars.region }} region.
- Summarize the {{ .params.max_results }} findings above.

Common patterns:

Pattern Meaning
{{ .params.x }} Parameter, as a string
{{ .vars.x }} Variable, as a string
{{ .context.session }} Full session output (Go struct notation)
`{{ .context.session json }}`
{{ .it }} Current iterator element, as a string

The | json filter is how you drop a whole structured object into prompt text — it serializes to a JSON string, which is exactly what you want inside text.

2. Wrapped Expr — $( ... )

Used exclusively inside call argument values, when the argument must receive a non-string value from scope:

call("process_items") {
    label = "Items for {{ .params.topic }}"   # string arg → template is correct
    items = $(context.gather.sources)          # array arg → Expr preserves the type
    limit = $(params.max_results)              # int arg   → Expr preserves the type
}
Pattern Returns Use case
$(context.session.field) Any Pass a nested object/array from a session
$(params.count) int Pass a number as a number
$(vars.myList) array Pass a variable holding an array
$(len(context.items)) int Pass a computed integer

3. Bare Expr in session arguments

expect and iterate take a plain quoted Expr string — no$(...) wrapper:

session("elaborate",
        after="gather",
        expect="len(context.gather.keyPoints) > 0",
        iterate="context.gather.keyPoints") {
    ...
}
Pattern Meaning
len(context.first) > 0 Array length check
context.overview.keyPoints != null Nil check
params.max_results Parameter value

The decision in one question

When you're about to interpolate a value, ask: is the destination text, or a tool argument?

The classic bug

You want to pass a session's array of sources to a tool:

# WRONG — the tool receives the string "[{...},{...}]", not an array
call("rank") {
    items = "{{ .context.gather.sources }}"
}

# RIGHT — the tool receives the actual array
call("rank") {
    items = $(context.gather.sources)
}

And the inverse, trying to use $(...) in prompt text, where it doesn't belong:

# WRONG — $(...) is only for call arguments
- Summarize these: $(context.gather.sources)

# RIGHT — serialize the structure into the text with | json
- Summarize these: {{ .context.gather.sources | json }}

Common mistakes

Mistake Fix
"{{ .context.items }}" for an array/object tool arg Use $(context.items) — templates only make strings
$( ... ) inside prompt or prePrompt text Use `{{ ...
Wrapping expect/iterate in $(...) They take bare Expr strings: expect="len(context.x) > 0"
Passing a number as "{{ .params.n }}" to a numeric arg Use $(params.n) to keep it an int

Next steps

Go templates always make strings; $(...) preserves real types. Learn the three expression positions and never hand a tool a stringified array again.