Build a hello-world plan
A plan is a Frags program written in FML — the Frags Modeling Language. A plan 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 plan 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 plan
The smallest plan is a single session with one prompt and an output schema. Save this as hello.fml:
Run it with the CLI:
Frags executes the hello session and returns an object keyed by the session name, matching the schema:
Three pieces are doing the work:
session("hello") { … }— a session is one isolated LLM task. Every plan has at least one, and its name becomes the key in the output.- …— the prompt (the-line). It's the main instruction and produces the structured output. There's exactly one per session.schema { greeting: string }— the output schema. Frags validates the model's response against it, so you always get agreetingstring back.
Add a system prompt and a parameter
Real plans take input and set the assistant's persona. system(...) sets a global system prompt, and 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> }}:
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 — 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.
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
Plans 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> }}:
Frags runs greet first, then translate, wiring the output of one session into the next. Each session contributes its key to the final object:
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
- Explore ready-made plans in the plan marketplace.
- Read the Frags reference on Plans, Sessions, and Flow Control.
- Run a finished plan over HTTP with the API reference, or call it from your app with the Python or TypeScript SDK.
Write your first FML plan from scratch — a single session with a schema — then grow it with parameters, prompt phases, and connected sessions.