-
Notifications
You must be signed in to change notification settings - Fork 0
Variables and Namespaces
FML enforces strict isolation across its variable system. Instead of maintaining a single global state dictionary, FML divides data into four isolated namespaces, each with distinct lifecycles, access rules, and scoping behaviors.
| Namespace | Origin / Declaration | Go Template Access ({{ ... }}) |
Antonmedv Expr Access ($( ... ) / Attrs) |
Lifecycle |
|---|---|---|---|---|
params |
Defined via parameter(...)
|
{{ .params.name }} |
params.name |
Immutable throughout plan execution |
vars |
Defined via set or PreCall -> vars:name
|
{{ .vars.name }} |
vars.name |
Mutable; supports global & session shadowing |
context |
Generated by completed session outputs |
{{ .context.session_name }} |
context.session_name |
Appended as sessions complete |
it |
Current item in an iterate session |
{{ .it }} or {{ .it.field }}
|
it or it.field
|
Scoped strictly to current loop iteration |
The params namespace contains all read-only values supplied to the plan at runtime.
parameter("api_endpoint", type="string", default="https://api.example.com")
parameter("concurrency", type="int", default=5)
parameter("dry_run", type="bool", default=false)
-
Inside a Go Template (Prompt or String Call Arg):
+ Sending requests to {{ .params.api_endpoint }} with concurrency {{ .params.concurrency }}. -
Inside an Antonmedv Expression (Wrapped Call Arg or Condition):
call("batch_processor") { max_threads = $(params.concurrency) } session("execute", expect="!params.dry_run") { # Runs only if dry_run is false }
Note
Values in params cannot be mutated or shadowed. They remain constant for the entire duration of the plan.
The vars namespace stores intermediate values, computation results, and static variables created by the developer.
set max_retries = 3
set user_agent = "FML-Bot/1.0"
# Explicit vars routing
call("query_user") -> vars:user_profile {
user_id = "{{ .params.user_id }}"
}
# Implicit routing (omitting namespace prefix defaults to vars)
call("query_settings") -> app_settings {
env = "production"
}
session("send_notification") {
# In template
+ Notify user {{ .vars.user_profile.email }} using agent {{ .vars.user_agent }}.
# In wrapped expr
call("deliver_email") {
recipient = "{{ .vars.user_profile.email }}"
retry_limit = $(vars.max_retries)
}
}
The context namespace acts as the primary bus for passing validated artifacts between sessions.
When a session completes successfully, its validated schema output is published under its session name:
session("gather_metrics") {
- Format metrics.
schema {
cpu_load: float
memory_mb: int
}
}
# Result published to: context.gather_metrics = { cpu_load: 0.72, memory_mb: 4096 }
If a session declares target="custom_key", the output is saved under context.custom_key instead of its session name:
session("fetch_user_records_v3", target="users") {
- Format user list.
schema string[]
}
# Result published to: context.users = ["alice", "bob"]
session("analyze", after="gather_metrics") {
# Full context JSON serialization
context "System Metrics: {{ .context.gather_metrics | json }}"
# Specific property interpolation
+ Analyzing CPU load: {{ .context.gather_metrics.cpu_load }}
# In conditional expressions
expect = "context.gather_metrics.cpu_load > 0.5"
}
When a session defines iterate=array_expr, the runtime loops over the array, executing the session once per element. During each execution, the current element is placed into the it namespace.
session("process_items", after="fetch_items", iterate=context.fetch_items.records) {
# In template
+ Processing item ID: {{ .it.id }} (Name: {{ .it.name }})
- Generate summary for {{ .it.name }}.
schema {
item_id: string
status: string
}
}
- If iterating over an array of primitives (
["apple", "banana"]), access the value directly with{{ .it }}. - If iterating over an array of objects (
[{ "id": 1 }, { "id": 2 }]), access properties using dot notation:{{ .it.id }}orit.id.
FML implements lexical scoping with shadowing for the vars namespace:
graph TD
subgraph Global["Global Scope"]
GV["set retries = 3<br/>(vars.retries = 3)"]
end
subgraph S1["Session: download_file"]
GV --> S1V["set retries = 5<br/>(vars.retries shadowed to 5)"]
end
subgraph S2["Session: notify_user"]
GV --> S2V["vars.retries is 3<br/>(Global value unaffected)"]
end
-
Local Declarations: A
setstatement or PreCall output routing (-> vars:name) inside a session creates or modifies a variable exclusively within that session's scope. - Non-Destructive Mutation: Modifying or shadowing a variable locally never mutates the global variable in other sessions.
-
Session Isolation: Session A cannot read or modify the local
varsof Session B. The only way to share data between sessions is through the validatedcontextnamespace.
When routing tool or PreCall outputs to namespaces, FML requires the colon (:) separator:
# CORRECT:
call("get_data") -> vars:my_var { ... }
call("get_data") -> context:my_key { ... }
call("get_data") -> my_var { ... } # Defaults to vars:my_var
# INCORRECT (Syntax Error):
call("get_data") -> vars.my_var { ... } # INVALID: Do not use dots!
call("get_data") -> context.my_key { ... } # INVALID: Do not use dots!
Caution
Always use a colon (:) to separate the namespace prefix from the identifier name (-> vars:identifier). Using a period will cause a syntax parse failure.
| Common Mistake | Error Symptoms | Solution |
|---|---|---|
| Missing dot in Go Template |
{{ params.id }} outputs empty or causes error |
Add leading dot: {{ .params.id }}
|
| Adding dot in Antonmedv Expr |
$(.vars.id) causes parse failure |
Remove leading dot: $(vars.id)
|
| Dot in call target routing |
-> vars.output causes syntax error |
Use colon: -> vars:output
|
Reading unpopulated local call in context
|
context "Data: {{ .vars.local }}" is empty |
Move variable reference to + or - prompt |
Accessing context.foo without after="foo"
|
Execution failure or null reference | Add after="foo" attribute to session |
FML (Frags Modeling Language) | Getting Started | Cheat Sheet | Examples
Documentation for FML & Gemini Agent Workflows — Maintained by Frags HQ