.prompt files inside a prompts/ folder — version-controlled, reviewable, and deployed with your code. No more strings scattered across your codebase or prompts locked in external dashboards.
generate_summary@v1.prompt
File Naming
Prompt files use the patternname@version.prompt:
generate_summary@v1.promptjudge_summary@v1.promptclassify_lead@v2.prompt
.prompt extension:
File Organization
Place prompt files in aprompts/ subfolder within your workflow directory:
prompts/ folder at a higher level.
Frontmatter
The YAML frontmatter configures the LLM call.Required Fields
Optional Fields
All fields use camelCase. Unknown top-level keys throw. A snake_case alias of a known field fails with a suggestion (
max_tokens -> use maxTokens). Provider-specific keys such as effort, reasoningEffort, and topP belong under providerOptions, not at the top level.
Configuration Structure
Prompt configurations have two layers: 1. Top-level config — Standard AI SDK options:- Provider-specific options that aren’t standard across all providers
- Special AI SDK extensions like
thinkingororder(AI Gateway) - Multi-provider configurations (Vertex with multiple model types)
- Shared top-level fields:
temperature,maxTokens,maxSteps,skills,tools,messageOptions, and the image fields (n,size,aspectRatio,seed,maxImagesPerCall) - These go at the top level alongside
providerandmodel
Provider Options
UseproviderOptions for provider-specific configuration.
Anthropic-specific options:
Google Vertex Provider Namespace Guide:
When using
provider: google-vertex (or the legacy alias vertex), the providerOptions namespace depends on the model:
- Gemini models → Use
google:namespace - Claude models → Use
anthropic:namespace - Vertex-specific options → Use
vertex:namespace
Prompt Body Modes
After rendering the template, Output determines how to parse the body from its first meaningful token. Leading whitespace and HTML comments (<!-- ... -->) do not affect this decision:
- If the first meaningful token is plain text, the whole trimmed body becomes
instructionsandmessagesis empty. Tags later in the body stay part of the instruction text. - If the first meaningful token is a tag, Output enters message mode and validates the body as role-tagged markup.
instructionsisnull.
loadPrompt() results directly. generateText, generateTextWithStreaming, streamText, and Agent require message mode.
- Top-level tags must be
<system>,<user>, or<assistant>. - Between top-level blocks, only whitespace and HTML comments are allowed.
- Top-level self-closing tags and closing tags without an opening block are invalid.
- Every top-level block needs a matching closing tag.
- Tags with a different name inside a message are preserved as message content. This includes semantic tags, HTML-like examples, and code such as
Array<string>. - A nested non-self-closing tag with the same name as its message is ambiguous and throws. Escape literal examples, including both brackets, such as
<user>example</user>.
Message Blocks
Message blocks use XML-style tags to define the conversation structure.<system>
The system message sets the persona and constraints. It defines who the LLM is and how it should behave. This stays constant across requests.
<user>
The user message is the actual request — what you want right now. This typically contains your variables.
<assistant>
The assistant block is for conversation history or response prefilling. Use it when you want to prime the model’s response format. generateText, generateTextWithStreaming, and streamText send it as part of the prompt thread. Agent drops authored <assistant> blocks; it only seeds <user> turns (system goes to instructions). For Agent few-shot or prefills, put examples in <system> or <user>, or use generateText.
<tool> blocks are not supported. AI SDK tool results use structured message parts tied to a preceding tool call; AI SDK creates these during tool execution, and Agent callers may supply them through messages or messageStore.
options
The only supported attribute on a role tag is options, a space-separated list of names from frontmatter messageOptions. At load, those sets are merged from left to right onto the message as providerOptions; later sets win when the same provider option is repeated.
Give options an explicit quoted or unquoted value, such as options="cached fast" or options=cached. Bare options throws, while options="" is treated as absent. Every referenced name must exist in messageOptions, and any other role-tag attribute throws. See Prompt Caching.
System vs User
A common mistake is putting everything in the user message. The split matters: System message (constant):- Who the LLM is (“You are a sales research assistant”)
- Behavioral constraints (“Never make up information”)
- Output format requirements (“Respond in JSON”)
- The specific request
- The data to process
- Dynamic instructions based on input
Using Prompts
Call prompts from your steps using the generate functions from@outputai/llm.
With generateText
For single-shot LLM calls, usegenerateText:
steps.ts
generateText also supports skills for on-demand instruction loading. List skill paths in the prompt frontmatter. Set maxSteps in the same frontmatter when the default of 10 is wrong.
With Agent
For multi-step tool loops and stateful conversations, use theAgent class:
steps.ts
generateText for single-shot LLM calls. Use Agent when you need multi-step tool execution, conversation history, or a reusable agent instance. See the Agents section for the full API.
The variables object maps to the {{ variable }} placeholders in your prompt. For dynamic content like conditionals and loops, see Templating.