Templates
Structured prompt blueprints — how they are written, how one is chosen per request, and everything downstream that reads them.
Overview
Read this first — it explains what a template is and why selection is the interesting part.
A Template is a structured prompt blueprint. Instead of one long instruction glued to an agent, you write the behaviour once as named fields — persona, context, task, constraints, examples, output format — and the agent adopts it for the requests it fits.
That structure buys two things a raw prompt cannot. First, editability: a non-technical team member can change what the agent says by editing one field, with no configuration or deployment. Second, and less obvious, machine readability: because the parts are named, the platform can use them individually. The task field becomes a scoring rubric. The output format becomes a JSON schema — and the field names inside it become extra retrieval queries. None of that is possible when the prompt is one opaque string.
An agent can hold many templates. It does not run them all — for each incoming message exactly one is chosen, or none at all. That selection is the heart of this module: a vector search, a relevance floor, an LLM re-rank, and a confidence override, each of which can decide that no template fits and let the turn proceed template-agnostic rather than force a bad match onto the agent's persona.
What a template feeds
The authored fields on the left; everything in the platform that reads them on the right.
Modules
Anatomy & Authoring
A template is a document with named fields. Three are required and the rest are optional, but the optional ones are where most of the leverage sits — outputFormat in particular does far more than describe the answer.
The authored fieldsA template can declare variables so the UI can collect values for them. Each carries an id, a name, an optional description, a type — Text, Number or Select — an options string for select lists, and an isManual flag marking it as supplied by hand rather than derived.
Research skip flagsFour booleans on the template switch off parts of the research stage for requests it matches. This is per-template, not per-agent: an agent can have one template that needs the knowledge base and another that must never touch it.
Semantic Selection
An agent lists the templates it may use. For each request exactly one is applied, or none — never two. Concatenating several would blur the persona, so the candidate list is deliberately truncated to a single winner at the end.
What actually gets embeddedOnly three fields are embedded: templateName, context and task, joined by newlines as plain label-free text. The labels (TemplateName:, Context:) were deliberately removed — they are tokens a user query never contains, so they only added noise to the document vector and widened the gap between how a query reads and how a template reads.
Every template also stores embeddingModel, the id of the model that produced its vector. That is what makes staleness detectable: querying with a vector from one model against documents embedded by another silently degrades relevance instead of failing.
Selection is a sequence of filters, each able to return nothing:
- Single-template shortcut. If the agent maps exactly one template, no search runs at all. It is used — but only if its status is active. A draft or inactive template is deliberately not used even when mapped one-to-one. It is stamped with a maximum vector score so downstream gates treat it as a definite match.
- Vector search. With two or more templates, a shared search path fetches the top candidates — the same code the Vector Tester uses, so the tester mirrors execution rather than approximating it. Templates whose stored embedding dimensions no longer match the query are excluded and reported, because Atlas would otherwise drop them silently and the template would simply vanish from the candidate set with no signal.
- Relevance floor. Scores are Atlas cosine normalised to 0–1, where 0.5 means orthogonal — unrelated. Anything below the configured floor is dropped. If nothing clears it, the turn proceeds with no template at all.
- LLM re-rank, with a confidence override. A model re-ranks the surviving candidates and is allowed to abstain. If it abstains, the top vector match is used only when it clears an absolute floor and beats the runner-up by a clear margin. A clustered band such as 0.80 against 0.78 is treated as ambiguous lexical overlap, not relevance — so the turn proceeds template-agnostic.
Template-Aware Retrieval
Retrieval used to see only the raw user message — whatever the template said it needed was never passed along. A matched template now produces a lightweight retrieval intent, built deterministically with no extra model round-trip.
Where the target fields come fromFields are extracted only from outputFormat, because that is the one machine-readable statement of what must be populated. Extraction tries three strategies in order: parse it as strict JSON and take the keys (top level plus one nested level); otherwise scrape "key": patterns from loose JSON-ish text; otherwise, only if the spec is short and comma-separated, treat it as a plain field list.
Free text in context and task is deliberately not scraped for field names — verb and NLP extraction proved noisy and produced bogus tokens. Instead the raw context and task are preserved in an intent text that the MCP tool planner reads as natural language.
Candidates are filtered so noise cannot leak through: at most eight fields, each no longer than 48 characters and at most five words, and each must contain a letter. Anything longer is a sentence, not a field name.
Why this produces better retrievalThe extracted fields fan out into multiple RAG queries. Query zero is always the raw user message, which preserves existing recall. Each additional query appends one required field to the user's topic, biasing that vector toward the field. A template that needs five things gets field-specific coverage instead of one top-K blob that happens to be dominated by whichever field the user phrased most strongly.
Workflow Consumers
Workflow steps can inherit from the matched template rather than repeating its content. Two sentinel values do the work, and both mean "whatever template won this turn":
A workflow can also be bound to a single template by id, so it runs only on turns the classifier routed to that template — one agent, several pipelines, no manual switching.
The llm_generate action has its own instructionMode: in template mode it drives generation from a saved template's persona, context, task, constraints and output format; in custom mode you write the instruction inline.
Prompt Enhancement
Writing eight good fields from scratch is work, so the studio can generate them. Give it a one-line prompt and an enhancement model expands it into the full structure — name, category, persona, context, task, reasoning, constraints, examples and output format — returning every value as a string. Or hand it a partially filled template and it enhances the fields already there instead of replacing them.
The enhancer is explicitly told to keep things tight: the persona stays within about 30 words, constraints are bulleted never/always rules, reasoning is a single short line, and examples are one realistic case with no nested JSON. The output format field is where it is told to be maximally specific, since that is the field the rest of the platform parses.
You pick the provider and model per enhancement run, so drafting can use a cheaper model than production traffic.
Every run is metered- Model name and id recorded per run
- Input, output and total tokens
- USD cost, frozen at write time from model pricing
- Re-enhance count per template
- Running token and cost totals
- Timestamp of the last enhancement
Lifecycle & Governance
A template's status is active, inactive or draft, and only active templates are ever eligible for selection. Separately, isActive is a soft-delete flag — deleting sets it false and excludes the template from listings, but the document is retained.
When the system default embedding model changes, existing vectors become incomparable to new queries. A maintenance pass scans every live template whose recorded embedding model is missing or differs from the current default and re-embeds it, reporting how many were scanned and how many were rewritten. Until that runs, affected templates are the ones the dimension check excludes from search.
Sharing and audit- Share with named users
- Share with whole roles
- Creator and last modifier tracked
- Created and updated timestamps
- System fields cannot be set by clients
- Per-template and global analytics views
How Templates Work — Flow Examples
Four diagrams tracing the real paths. Each box is a stage that exists in the runtime; dashed arrows are alternative outcomes.
Example 1 — Choosing one template Selection
From an incoming message to exactly one template, or none. Every gate can end the path early, and the single-template case skips the search entirely.
Example 2 — Output format becomes retrieval queries Retrieval
The matched template's output spec is parsed for field names, and each field becomes an extra RAG query biased toward it. No model call is involved.
Example 3 — Skip flags gate the research stage Control
Each flag on the matched template switches off one research source for the requests that template handles — per template, not per agent.
Example 4 — Authoring and lifecycle Lifecycle
From a one-line idea to a live template, and what happens when the embedding model changes or an agent is still using it.
Reference Tables
Every stored field, and the constants that tune selection.
Template fields
| Field | Required | Purpose |
|---|---|---|
| Authored content | ||
| templateName | Yes | Short name — also embedded for matching |
| category | Yes | Grouping label for filtering and listing |
| persona | Yes | The expert role the agent adopts |
| context | Yes | Background — embedded, and part of the retrieval intent |
| task | Yes | What to do — embedded, retrieval intent, and score rubric |
| reasoning | No | How the model should think it through |
| constraints | No | Never / always rules |
| examples | No | Worked examples matching the output format |
| outputFormat | No | Output structure — parsed for target field names |
| variables | No | Declared inputs: name, type, description, options, isManual |
| Research control | ||
| skipRag | Default false | Disable knowledge-base retrieval |
| skipMcpTools | Default false | Disable MCP tool loading and invocation |
| skipApiRegistry | Default false | Disable registered REST calls |
| skipWeb | Default false | Disable web loading |
| System-managed | ||
| embedding | Generated | Vector of name + context + task, label-free |
| embeddingModel | Generated | Id of the model that produced the vector — staleness detection |
| summary | Disabled | Present on the model; generation is currently switched off |
| status | Default active | active / inactive / draft — only active is selectable |
| isActive | Default true | Soft-delete flag; false hides it from listings |
| sharedWithUsers | No | Users granted access |
| sharedWithRoles | No | Roles granted access |
| createdBy / modifiedBy | Yes | Audit trail; not settable by clients |
Selection tuning constants
| Constant | Default | Effect |
|---|---|---|
| templateRerankCandidates | 5 | How many vector candidates are fetched for the LLM to re-rank |
| templateMinRelevanceScore | 0.50 | Relevance floor. Cosine normalised 0–1 where 0.5 is orthogonal, so this is effectively "must be better than unrelated" |
| templateConfidentScore | 0.75 | Absolute floor the top match must clear to override an LLM abstention |
| templateConfidentMargin | 0.05 | How far the top match must beat the runner-up before it counts as unambiguous |