Skip to content

Schemas and Components

theirish81 edited this page Sep 3, 2026 · 1 revision

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.


Schema Declaration Syntax

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
    }
}

Type System Reference

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 }

Inline Comments as Schema Descriptions

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.


Reusable Components (components)

When multiple sessions produce or consume identical data models, define them inside a top-level components block:

Defining Components

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
    }
}

Referencing Components in Sessions

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
}

Array Shorthand Schemas

For sessions that return a list of items rather than a dictionary object—especially sessions utilizing iterate—FML provides an array shorthand syntax:

Primitive Array Shorthand

session("list_keywords") {
    - Extract top 5 search keywords.
    schema string[]
}
# Produces: ["kubernetes", "docker", "containers"]

Component Array Shorthand

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.


Best Practices & Anti-Patterns

Anti-Pattern: Redundant Top-Level Object Nesting

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

Schema Validation Lifecycle

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
Loading

Clone this wiki locally