Anatomy of a session | Diaphora Docs | Diaphora
Anatomy of a session
A session is the core unit of an FML blueprint. Each one runs its own LLM interaction with its own isolated context, and produces a single typed JSON object stored under context.<session_name>. A blueprint is just a set of sessions plus the declarations that wire them together.
This guide walks through every part of a session, in the order they appear in the body, and explains the one rule that trips people up most: the difference between a prePrompt and a prompt.
Prerequisites
- The hello-world blueprint guide — you should have written at least one session and seen its output.
The shape of a session
session("overview") {
use search # 1. tools this session may use
call("searchDocuments") -> docs # 2. deterministic PreCall(s)
context "..." # 3. context transferred in from other sessions
set threshold = 10 # 4. session-scoped variables
+ Search for background on the topic. # 5. prePrompt(s) — may call tools
- Summarize what you found. # 6. exactly one prompt — produces output
schema { # 7. the typed output shape
summary: string
}
}
Only two parts are strictly required: the name and a prompt. Everything else is optional and depends on what the session needs to do.
1. The name
The first positional argument is the session's name:
session("overview") { ... }
That name is doing double duty. It's the key the session's output appears under in both the context namespace (context.overview) and the blueprint's final output object. It's also what other sessions reference in after, expect, and iterate. Use target if you want to publish under a different key see Control the flow of a blueprint.
2. Each session has its own context
This is the mental model that makes the rest click: a session does not automatically see other sessions' work. Every session starts with a fresh LLM context. It only knows about:
params,vars, and anything you explicitly pull in,- the output of its own PreCalls and prePrompts,
- whatever you transfer in with a
contextdirective (which requiresafter).
That isolation keeps each session focused on one job with a small, relevant context, which is far more reliable than one giant prompt trying to do everything. To hand one session's result to another, you route it explicitly (covered in Data flow: params, vars & context).
3. use — declaring tools
Before a prePrompt can call a tool, the session has to declare it:
use mcp salesforce
use collection postgres
use search # special — no name follows
This mirrors the root-level require, but scoped to the session. search is the one exception: it's declared only as use search, never with require.
4. prePrompt (+) vs prompt (-) — the key distinction
Every session ends with instructions to the model, and there are two kinds. Getting them straight is the single most important thing about a session.
A prePrompt starts with +. It enriches the context and runs with tools available. This is where the model searches, fetches, and gathers. You can have as many as you need.
+ Search for recent information about {{ .params.topic }}.
Focus on the most relevant sources.
The prompt starts with -. It's the single final instruction that turns the gathered context into the structured output. A prompt is tool-free — it does not call tools, it only produces the JSON the schema describes. There is exactly one prompt per session.
- Using the information above, extract the summary and key points
required by the schema.
prePrompt + |
prompt - |
|
|---|---|---|
| Purpose | Gather / enrich context | Produce the final output |
| Tools | Allowed | Never |
| How many | Zero or more | Exactly one |
| Produces | Context for the prompt | The session's typed JSON |
The most common beginner mistake is asking the - prompt to "search for X and summarize it." Split it: a + prePrompt searches, the - prompt summarizes. (See Call MCP servers and databases for tool-driven prePrompts.)
Both + and - support Go text templates ({{ .params.x }}, {{ .context.y | json }}) and span multiple lines via indentation.
5. The schema
The schema declares the JSON shape the prompt must produce:
schema {
summary: string # a concise paragraph
keyPoints: string[] # the most important points
}
The session name is already the outer wrapper, so keep fields flat at the root rather than re-nesting them under an object named after the session. Schemas have their own depth — optional fields, arrays, nested objects, reusable $Component refs, and scalar shorthand like schema string[] — all covered in Design your output schemas.
6. The supporting cast
Three more optional directives round out a session:
context— transfers prior session output into this session's context, either wholesale (context true) or formatted (context "Overview: {{ .context.overview | json }}"). Requiresafter.set— a session-scoped variable, merged with globals and read asvars.<name>.call— a PreCall: a deterministic tool or code invocation that runs before the prompts fire. Use it when you know the exact tool signature; otherwise let a prePrompt call the tool. See PreCalls deep-dive.
Putting it together
A complete, realistic session using most of the parts:
require mcp knowledge_base
session("gather") {
use search
use mcp knowledge_base
# Deterministic fetch before the model runs
call("searchDocuments") -> rawDocs {
query = "{{ .params.topic }}"
limit = 5
}
+ Search the web and the knowledge base for {{ .params.topic }}.
Prefer recent, primary sources.
- Using the results above, extract the summary and key points
required by the schema.
schema {
summary: string # concise paragraph summarising the topic
keyPoints: string[] # the most important points
sources: string[] # URLs or titles used
}
}
Read top to bottom: declare tools, fetch deterministically, gather with a prePrompt, then produce the typed output with the one prompt.
Next steps
- Learn how data moves between sessions in Data flow: params, vars & context.
- Shape richer output in Design your output schemas.
- Sequence and gate sessions in Control the flow of a blueprint.
- Full reference: Sessions on the Frags wiki.
Every part of a session, top to bottom — name, tools, PreCalls, context, and the key prePrompt (+) vs prompt (-) distinction that turns gathered context into typed output.