Overview
SystemPromptBuilder implements a fluent API pattern for building comprehensive system prompts. It collects configuration for agent identity, capabilities, tools, constraints, communication style, and output formatting.
When you call .build(), it generates a structured markdown document that serves as the system prompt for your AI agent.
Constructor
Do not instantiate directly. Use the createPromptBuilder() factory function instead.
import { createPromptBuilder } from "promptsmith-ts";
const builder = createPromptBuilder();
Core Configuration Methods
withIdentity()
Sets the agent’s core identity or purpose.
withIdentity(text: string): this
Description of the agent’s identity. Should be written in second person (“You are…”) or third person (“The assistant is…”).
Example:
builder.withIdentity("You are an expert travel assistant specializing in European destinations");
withCapability()
Adds a single capability to the agent’s skillset.
withCapability(cap: string): this
A single capability description. Should be action-oriented and specific.
Example:
builder
.withCapability("Search and analyze research papers")
.withCapability("Generate literature reviews");
withCapabilities()
Adds multiple capabilities at once.
withCapabilities(caps: string[]): this
An array of capability descriptions. Empty strings are filtered out automatically.
Example:
builder.withCapabilities([
"Analyze financial data and trends",
"Calculate investment returns",
"Provide risk assessments"
]);
Registers a tool that the agent can use.
withTool<T extends ZodType>(def: ExecutableToolDefinition<T>): this
withTool(def: MastraToolDefinition): this
Unique identifier for the tool (snake_case recommended)
Human-readable description of what the tool does and when to use it
Zod schema defining the tool’s input parameters
def.execute
(args: T) => Promise<unknown> | unknown
Optional execution function for runtime tool usage
Example:
import { z } from "zod";
// With execution logic
builder.withTool({
name: "get_weather",
description: "Retrieves current weather for a location",
schema: z.object({
location: z.string().describe("City name or ZIP code"),
units: z.enum(["celsius", "fahrenheit"]).optional()
}),
execute: async ({ location, units }) => {
const response = await fetch(`https://api.weather.com/${location}?units=${units}`);
return response.json();
}
});
// Documentation-only tool (no execute function)
builder.withTool({
name: "search_database",
description: "Search the knowledge database",
schema: z.object({
query: z.string()
})
});
The withTool() method automatically detects and converts Mastra tools created with createTool() from @mastra/core/tools.
Registers multiple tools at once.
withTools(defs: ExecutableToolDefinition[]): this
defs
ExecutableToolDefinition[]
required
An array of tool definitions
Conditionally registers a tool based on a condition.
withToolIf(condition: boolean, def: ExecutableToolDefinition): this
Boolean condition that determines if the tool is added
def
ExecutableToolDefinition
required
Tool definition to add if condition is true
Example:
const hasDatabase = config.databaseEnabled;
builder.withToolIf(hasDatabase, {
name: "query_db",
description: "Query the database",
schema: z.object({ query: z.string() }),
execute: async ({ query }) => await db.execute(query)
});
Constraint Methods
withConstraint()
Adds a behavioral constraint or guideline.
withConstraint(type: ConstraintType, rule: string): this
type
'must' | 'must_not' | 'should' | 'should_not'
required
The constraint severity level
The constraint rule text. Should be clear, specific, and actionable.
Constraint Types:
must: Absolute requirements that cannot be violated
must_not: Absolute prohibitions
should: Strong recommendations to follow when possible
should_not: Strong recommendations to avoid
Example:
builder
.withConstraint("must", "Always verify user authentication before accessing personal data")
.withConstraint("must_not", "Never store or log sensitive information")
.withConstraint("should", "Provide concise responses unless detail is requested");
withConstraints()
Adds one or more constraints with the same type.
withConstraints(type: ConstraintType, rules: string | string[]): this
The constraint severity level
rules
string | string[]
required
Single rule string or array of rule strings
withConstraintIf()
Conditionally adds a constraint based on a condition.
withConstraintIf(condition: boolean, type: ConstraintType, rule: string): this
withOutput()
Sets the output format guidelines for the agent’s responses.
withOutput(format: string): this
Output format description or template. Can include examples, numbered steps, or structural guidelines.
Example:
builder.withOutput(`
Use the following structure:
- Brief overview (2-3 sentences)
- Bullet points for key information
- Code examples when relevant
- Concluding recommendation
`);
withTone()
Sets the communication tone and style.
withTone(tone: string): this
Description of the desired communication style
Example:
builder.withTone("Be friendly, enthusiastic, and encouraging. Use a conversational tone.");
Sets the output format for the generated prompt.
withFormat(format: PromptFormat): this
format
'markdown' | 'toon' | 'compact'
required
The desired output format
Format Options:
markdown: Standard markdown format (default, human-readable)
toon: TOON format (Token-Oriented Object Notation) - 30-60% token reduction
compact: Minimal whitespace variant of markdown
Example:
builder.withFormat('toon'); // Optimize for token efficiency
Security & Safety Methods
withGuardrails()
Enables standard anti-prompt-injection security guardrails.
Activates:
- Input Isolation: Treats all user inputs as untrusted data
- Role Protection: Prevents identity override attempts
- Instruction Separation: System instructions take precedence
- Output Safety: Prevents prompt revelation
Example:
builder
.withIdentity("You are a customer service assistant")
.withGuardrails();
Always enable guardrails for production applications where user input cannot be fully trusted or where the agent has access to sensitive operations.
withForbiddenTopics()
Specifies topics that the agent must not discuss.
withForbiddenTopics(topics: string[]): this
Array of topic descriptions that should be off-limits
Example:
builder.withForbiddenTopics([
"Medical diagnosis or treatment advice",
"Legal advice or interpretation of laws",
"Financial investment recommendations"
]);
Context & Learning Methods
withContext()
Provides domain-specific context and background knowledge.
withContext(text: string): this
Contextual information for the agent. Can be multi-line.
Example:
builder.withContext(`
Our clinic operates Monday-Friday, 9 AM to 5 PM.
We have three doctors:
- Dr. Smith specializes in general medicine
- Dr. Jones specializes in cardiology
- Dr. Lee specializes in pediatrics
`);
withExamples()
Provides examples of desired agent behavior through few-shot learning.
withExamples(examples: Example[]): this
Array of example objects showing input-output pairs
Example Type:
type Example = {
user?: string; // User input (conversational style)
assistant?: string; // Agent response (conversational style)
input?: string; // Input (functional style)
output?: string; // Output (functional style)
explanation?: string; // Why this example is good
}
Example:
builder.withExamples([
{
user: "What's the weather in Paris?",
assistant: "I'll check the weather for you. *calls get_weather tool*",
explanation: "Shows proper tool invocation for weather queries"
},
{
user: "Book me a table for 2 at 7pm",
assistant: "I'll help you make a reservation. What restaurant would you like?",
explanation: "Shows how to ask for missing required information"
}
]);
withErrorHandling()
Defines how the agent should handle uncertainty and errors.
withErrorHandling(instructions: string): this
Guidelines for handling uncertainty and errors. Can be multi-line.
Example:
builder.withErrorHandling(`
Error Handling Guidelines:
- If a request is ambiguous, ask specific clarifying questions
- If you lack required information, explicitly list what's needed
- If uncertain about facts, acknowledge uncertainty rather than guessing
- For tool errors, explain the issue in user-friendly terms
`);
Advanced Methods
extend()
Creates a new builder instance based on this one.
extend(): SystemPromptBuilder
Returns: A new SystemPromptBuilder instance with copied state
Example:
const baseSupport = createPromptBuilder()
.withIdentity("You are a helpful support assistant")
.withGuardrails();
const technicalSupport = baseSupport.extend()
.withIdentity("You are a technical support specialist")
.withCapability("Debug technical issues");
merge()
Merges another builder’s configuration into this one.
merge(source: SystemPromptBuilder): this
source
SystemPromptBuilder
required
The builder to merge into this one
Merge Rules:
- Identity: Uses this builder’s identity (not overridden)
- Capabilities: Combines both lists (removes duplicates)
- Tools: Combines both lists (throws error if duplicate names)
- Constraints: Combines both lists
- Guardrails: Enabled if either has it enabled
Example:
const securityBuilder = createPromptBuilder()
.withGuardrails()
.withConstraint("must", "Always verify user identity");
const customerService = createPromptBuilder()
.withIdentity("You are a customer service assistant")
.merge(securityBuilder);
validate()
Validates the current builder configuration.
validate(config?: ValidatorConfig): ValidationResult
Optional validator configuration to customize validation rules
Returns: ValidationResult object containing validation status and issues
Example:
const result = builder.validate();
if (!result.valid) {
console.error("Validation errors:", result.errors);
}
if (result.warnings.length > 0) {
console.warn("Warnings:", result.warnings);
}
withValidatorConfig()
Sets the default validator configuration.
withValidatorConfig(config: ValidatorConfig): this
Inspection Methods
Returns the list of registered tools.
getTools(): ExecutableToolDefinition[]
getSummary()
Returns a summary of the builder’s current state.
getSummary(): {
hasIdentity: boolean;
capabilitiesCount: number;
toolsCount: number;
constraintsCount: number;
constraintsByType: {
must: number;
must_not: number;
should: number;
should_not: number;
};
examplesCount: number;
hasGuardrails: boolean;
forbiddenTopicsCount: number;
hasContext: boolean;
hasTone: boolean;
hasOutputFormat: boolean;
hasErrorHandling: boolean;
format: PromptFormat;
}
debug()
Outputs detailed debug information to console.
Example:
builder
.withIdentity("Assistant")
.withCapability("Answer questions")
.debug(); // Logs detailed information
Boolean Check Methods
hasTools(): boolean
hasConstraints(): boolean
hasIdentity(): boolean
hasCapabilities(): boolean
hasExamples(): boolean
hasGuardrails(): boolean
hasForbiddenTopics(): boolean
getConstraintsByType()
Returns constraints of a specific type.
getConstraintsByType(type: ConstraintType): Constraint[]
Output Methods
build()
Builds and returns the complete system prompt as a string.
build(format?: PromptFormat): string
format
'markdown' | 'toon' | 'compact'
Optional format override. If not provided, uses the format set via withFormat() (defaults to ‘markdown’)
Returns: Formatted system prompt string ready for use with AI models
Example:
const prompt = builder.build();
const toonPrompt = builder.build('toon'); // Override to TOON format
toAiSdk()
Exports a complete AI SDK configuration object.
Returns:
{
system: string; // The complete system prompt
tools: Record<string, {
description: string;
parameters: ZodType;
execute?: (args: unknown) => Promise<unknown> | unknown;
}>;
}
Example:
import { generateText } from "ai";
import { openai } from "@ai-sdk/openai";
const response = await generateText({
model: openai("gpt-4"),
...builder.toAiSdk(),
prompt: "What's the weather in Paris?"
});
Exports tools in Vercel AI SDK format.
toAiSdkTools(): Record<string, {
description: string;
parameters: ZodType;
execute?: (args: unknown) => Promise<unknown> | unknown;
}>
toMastra()
Exports configuration for Mastra agents.
toMastra(): {
instructions: string;
tools: Record<string, {
id: string;
description: string;
inputSchema: ZodType;
outputSchema?: ZodType;
execute?: (args: { context: unknown }) => Promise<unknown> | unknown;
}>;
}
Example:
import { Agent } from "@mastra/core/agent";
const { instructions, tools } = builder.toMastra();
const agent = new Agent({
name: "weather-agent",
instructions,
model: "openai/gpt-4o",
tools
});
toJSON()
Exports the builder’s configuration as a plain JavaScript object.
Example:
const config = builder.toJSON();
fs.writeFileSync('agent-config.json', JSON.stringify(config, null, 2));
Complete Example
import { createPromptBuilder } from "promptsmith-ts";
import { generateText } from "ai";
import { openai } from "@ai-sdk/openai";
import { z } from "zod";
const builder = createPromptBuilder()
.withIdentity("You are a professional customer service assistant")
.withCapabilities([
"Answer product questions",
"Process returns and refunds",
"Track order status"
])
.withTool({
name: "lookup_order",
description: "Look up order details by order ID",
schema: z.object({
orderId: z.string().describe("The order ID to look up")
}),
execute: async ({ orderId }) => {
return await database.orders.findById(orderId);
}
})
.withConstraint("must", "Always verify customer identity before discussing order details")
.withConstraint("must_not", "Never process refunds over $500 without manager approval")
.withTone("Be empathetic, professional, and solution-oriented")
.withGuardrails()
.withErrorHandling("If uncertain, ask clarifying questions rather than making assumptions")
.withFormat('toon'); // Use token-optimized format
// Validate before using
const validation = builder.validate();
if (!validation.valid) {
console.error("Configuration errors:", validation.errors);
}
// Use with AI SDK
const response = await generateText({
model: openai("gpt-4"),
...builder.toAiSdk(),
prompt: "I want to return my order #12345"
});