Build a hello-world blueprint | Diaphora Docs | Diaphora

Build a hello-world blueprint

A blueprint is a Frags program written in FML — the Frags Modeling Language. A blueprint decomposes a task into one or more sessions, each an isolated LLM interaction with its own output schema, so every session returns typed, validated JSON instead of freeform text. This guide builds the smallest possible blueprint and grows it one concept at a time.

Golden rule: FML looks imperative, but it's a description language. There's no branching, no loops (except iterate), and no return statements — every construct is declarative. You describe the sessions and their shapes; the runtime schedules and executes them.

Prerequisites

A working local Frags runtime. If you haven't set one up yet, start with Running Frags Locally — you'll need the frags CLI and a configured AI engine.

Your first blueprint

The smallest blueprint is a single session with one prompt and an output schema. Save this as hello.fml:

session("hello") {
    - Say hello to the world in one friendly sentence.

schema {
        greeting: string
    }
}

Run it with the CLI:

frags run hello.fml

Frags executes the hello session and returns an object keyed by the session name, matching the schema:

{
  "hello": {
    "greeting": "Hello, world — it's a great day to build something."
  }
}

Three pieces are doing the work:

Add a system prompt and a parameter

Real blueprints take input and set the assistant's persona. system(...) sets a global system prompt, one system prompt is allowed per blueprint and it takes in a plain string as the argument. parameter(...) declares a typed input, the type is a bare keyword (no quotes), and a default makes it optional. Reference a parameter anywhere with Go template syntax, {{ .params.<name> }}:

system("You are a friendly assistant who keeps things short.")

parameter("name", type=string, default="Rayna", title="Name to greet")

session("hello") {
    - Write a short, friendly one-sentence greeting to {{ .params.name }}.

schema {
        greeting: string   # The greeting to return
    }
}

Because name has a default, frags run hello.fml runs as-is and greets "World". Inline schema comments like # The greeting to return aren't just for you as the LLM reads them as field descriptions, so add them whenever a field name isn't self-explanatory.

Prompt phases: prepare, then answer

A session can run in phases. A + line is a prePrompt: it runs first, enriches the context, and is the only place allowed to call tools (MCP servers, collections, search). The - line is the main prompt that turns everything gathered into the schema — prompts themselves never call tools.

session("hello") {
    + Consider what makes a greeting feel warm and personal.
    - Using that, write a short, friendly greeting to {{ .params.name }}.

schema {
        greeting: string
    }
}

You can have several + prePrompts in a session, but only one - prompt. So the pattern is always: gather with prePrompts, then produce the output with the single prompt.

Connect sessions together

Blueprints get powerful when sessions build on one another. Add after="<session>" so a session waits for another to finish, then pull the earlier session's output into a prompt with {{ .context.<session>.<field> }}:

parameter("name", type=string, default="Rayna")
parameter("language", type=string, default="Italian")

session("greet") {
    - Write a one-sentence greeting to {{ .params.name }}.

schema {
        greeting: string
    }
}

session("translate", after="greet") {
    - Translate this greeting into {{ .params.language }}: "{{ .context.greet.greeting }}"

schema {
        greeting_fr: string
    }
}

Frags runs greet first, then translate, wiring the output of one session into the next. Each session contributes its key to the final object:

{
  "greet":     { "greeting": "Hello, World!" },
  "translate": { "greeting_fr": "Bonjour, World !" }
}

From here, a session can also depend on a condition (expect="..."), run once per item in a list (iterate="..."), or publish under a different key (target="...") — all declared as session arguments.

Next steps

Write your first FML blueprint from scratch — a single session with a schema — then grow it with parameters, prompt phases, and connected sessions.