-
Notifications
You must be signed in to change notification settings - Fork 0
Schemas and Components
FML features a declarative type system to guarantee that LLM session outputs conform to strict JSON schemas. These schemas drive Gemini's structured output generation and are validated in Phase 4 of the session execution lifecycle before being published to the context namespace.
Every session must define a schema block specifying the shape of the data it generates:
session("extract_product_info") {
- Extract product details from the document.
schema {
product_id: string # Unique SKU or ID
name: string # Commercial product name
price: float # Retail price in USD
in_stock: bool # Availability flag
tags: string[] # Associated category tags
status: active|draft|discontinued # Product lifecycle state
warranty_months?: int # Optional warranty length
}
}
FML supports a rich set of primitives, complex types, and constraints:
| Type Expression | Description | Example |
|---|---|---|
string |
UTF-8 text string | title: string |
int |
Signed integer | item_count: int |
float |
Floating-point number | confidence: float |
bool |
Boolean flag | verified: bool |
type[] |
Array of elements | tags: string[] |
opt_field?: type |
Optional field (nullable or omitted) | notes?: string |
val1|val2|val3 |
Enum / String union constraint | risk: low|medium|high |
val1|val2[] |
Array of union choices | roles: user|admin[] |
$ComponentName |
Reference to global component | author: $UserProfile |
$ComponentName[] |
Array of component references | team: $UserProfile[] |
{ sub: type } |
Anonymous nested object | address: { city: string, zip: string } |
In FML, inline comments placed after schema fields are not discarded. The FML compiler extracts these comments and converts them directly into JSON Schema description properties:
schema {
score: float # Quality metric between 0.0 and 1.0 (higher is better)
severity: low|medium|high|critical # Impact assessment based on CVE guidelines
remediation?: string # Specific command or configuration fix if available
}
Tip
Always provide concise, explanatory inline comments on schema fields. The LLM relies on these descriptions during Phase 3 to understand the expected semantics, ranges, and formatting of each field.
When multiple sessions produce or consume identical data models, define them inside a top-level components block:
components {
schema("Contact") {
name: string # Full legal name
email: string # Primary contact email
phone?: string # Optional direct line
}
schema("Organization") {
company_name: string
domain: string
primary_contact: $Contact # Nested component reference
advisors: $Contact[] # Array of component references
}
}
Reference declared components by prefixing their name with a dollar sign ($):
session("extract_leads") {
- Extract lead information.
schema {
leads: $Contact[]
lead_count: int
}
}
session("audit_company", after="extract_leads") {
- Summarize company structure.
schema $Organization
}
For sessions that return a list of items rather than a dictionary object—especially sessions utilizing iterate—FML provides an array shorthand syntax:
session("list_keywords") {
- Extract top 5 search keywords.
schema string[]
}
# Produces: ["kubernetes", "docker", "containers"]
session("scrape_all_profiles", iterate=context.user_urls) {
+ Scrape URL: {{ .it.url }}
- Format profile.
schema $Contact[]
}
Important
Mandatory for iterate Sessions:
Any session that uses the iterate attribute must define its schema as an array (e.g. schema type[], schema $Component[], or schema { ... }[]). The runtime collects each iteration's output and sequentially appends it to the final array.
Avoid wrapping your schema properties inside a redundant parent object named after the session. FML schemas should be declared flat at the root of the schema block.
# ❌ INCORRECT (Redundant Nesting):
session("extract_user") {
schema {
extract_user: { # Redundant!
name: string
email: string
}
}
}
# Output becomes: context.extract_user.extract_user.name
# ✅ CORRECT (Flat Root Schema):
session("extract_user") {
schema {
name: string
email: string
}
}
# Output becomes: context.extract_user.name
sequenceDiagram
participant LLM as Frontier Model (Gemini)
participant Engine as FML Runtime
participant Bus as Context Bus (context.*)
Note over LLM,Engine: Phase 3: Final Prompt (-)
Engine->>LLM: Prompt text + Strict JSON Schema definition
LLM-->>Engine: Raw JSON Response string
Note over Engine: Phase 4: Schema Validation
Engine->>Engine: Validate JSON against FML Schema types & enums
alt Validation Succeeded
Engine->>Bus: Store under context.<session_name>
else Validation Failed
Engine->>Engine: Halt plan execution & emit validation error
end
FML (Frags Modeling Language) | Getting Started | Cheat Sheet | Examples
Documentation for FML & Gemini Agent Workflows — Maintained by Frags HQ