Skip to content

Prompt Templates

The prompts layer provides a template engine for managing, versioning, and composing prompts. Define reusable templates with typed variables, track versions, and compose complex prompts from smaller pieces.

const agent = await ReactiveAgents.create()
.withProvider("anthropic")
.withPrompts() // Enable prompt template engine
.build();

Templates use {{variable}} syntax for interpolation:

import { PromptService } from "@reactive-agents/prompts";
import { Effect } from "effect";
const program = Effect.gen(function* () {
const prompts = yield* PromptService;
// Register a template
yield* prompts.register({
id: "research-task",
name: "Research Task",
version: 1,
template: `You are a {{role}} researching {{topic}}.
Your goal is to {{objective}}.
Focus on these aspects:
{{#each aspects}}
- {{this}}
{{/each}}
Provide your findings in {{format}} format.`,
variables: [
{ name: "role", required: true, type: "string", description: "Agent's role" },
{ name: "topic", required: true, type: "string", description: "Research topic" },
{ name: "objective", required: true, type: "string", description: "Research goal" },
{ name: "aspects", required: false, type: "array", description: "Focus areas" },
{ name: "format", required: false, type: "string", description: "Output format", defaultValue: "markdown" },
],
metadata: {
author: "team",
description: "General-purpose research prompt",
tags: ["research", "analysis"],
maxTokens: 4096,
},
});
});

Compile a template by interpolating variables:

const compiled = yield* prompts.compile("research-task", {
role: "senior analyst",
topic: "quantum computing applications",
objective: "identify the top 5 commercial applications",
format: "bullet points",
});
console.log(compiled.content);
// "You are a senior analyst researching quantum computing applications..."
console.log(compiled.tokenEstimate);
// Estimated token count for the compiled prompt

Set a max token budget — the template engine truncates if the compiled prompt exceeds it:

const compiled = yield* prompts.compile("research-task", variables, {
maxTokens: 1000, // Truncate to fit within 1000 tokens
});

Combine multiple compiled prompts into one:

const systemPrompt = yield* prompts.compile("system-context", { agent: "researcher" });
const taskPrompt = yield* prompts.compile("research-task", { topic: "CRISPR" });
const formatPrompt = yield* prompts.compile("output-format", { format: "academic" });
const combined = yield* prompts.compose(
[systemPrompt, taskPrompt, formatPrompt],
{ separator: "\n\n---\n\n", maxTokens: 8000 },
);
console.log(combined.content); // All three prompts joined
console.log(combined.tokenEstimate); // Total token estimate

Templates are automatically versioned. Register a new version by using the same id:

// Version 1
yield* prompts.register({
id: "research-task",
name: "Research Task",
version: 1,
template: "Original template...",
variables: [...],
});
// Version 2 (improved)
yield* prompts.register({
id: "research-task",
name: "Research Task v2",
version: 2,
template: "Improved template with better instructions...",
variables: [...],
});
// Get specific version
const v1 = yield* prompts.getVersion("research-task", 1);
// Get all versions
const history = yield* prompts.getVersionHistory("research-task");
// Sorted by version number

The framework includes templates for internal reasoning strategies:

TemplateUsed By
reactReAct reasoning strategy
plan-executePlan-Execute-Reflect strategy
reflexionReflexion self-improvement strategy
tree-of-thoughtTree-of-Thought exploration strategy
fact-checkVerification layer

These are used internally by the reasoning and verification layers — you don’t need to register them manually.

Run statistically-tracked prompt experiments to find the best-performing template variant for a task:

import { ExperimentService } from "@reactive-agents/prompts";
import { Effect } from "effect";
const program = Effect.gen(function* () {
const experiments = yield* ExperimentService;
// Register two prompt variants as an experiment
const experimentId = yield* experiments.register({
name: "research-prompt-ab",
variants: [
{
id: "variant-a",
templateId: "research-task",
variables: { tone: "formal", depth: "comprehensive" },
weight: 0.5,
},
{
id: "variant-b",
templateId: "research-task",
variables: { tone: "concise", depth: "focused" },
weight: 0.5,
},
],
metric: "user_satisfaction",
});
// Get the next variant to run (weighted random selection)
const variant = yield* experiments.nextVariant(experimentId);
const compiled = yield* prompts.compile(variant.templateId, variant.variables);
// ... run the agent with compiled.content as the system prompt ...
// Record outcome (0.0–1.0 score, or pass/fail)
yield* experiments.recordOutcome(experimentId, variant.id, {
score: 0.87,
metadata: { responseTime: 1200, userRating: 4 },
});
// Query results to see which variant is winning
const results = yield* experiments.getResults(experimentId);
console.log(results.variants);
// [
// { id: "variant-a", runs: 45, avgScore: 0.82, p95: 0.90 },
// { id: "variant-b", runs: 47, avgScore: 0.87, p95: 0.93 },
// ]
console.log(results.winner); // "variant-b"
});
const agent = await ReactiveAgents.create()
.withProvider("anthropic")
.withPrompts({ experiments: true })
.build();
MethodDescription
register(config)Create a new experiment with two or more weighted variants
nextVariant(id)Select the next variant to run (respects weights + exploration)
recordOutcome(id, variantId, outcome)Record a score for a completed variant run
getResults(id)Get aggregate statistics per variant with a winner field
pause(id)Pause variant selection (all calls get variant A)
archive(id)Archive a completed experiment

Outcomes are persisted to SQLite for cross-session aggregation, so experiments can run over thousands of agent invocations and still converge.

Each variable has a type and can be required or optional:

TypeDescription
stringText value
numberNumeric value
booleanTrue/false
arrayList of values
objectKey-value map

Optional variables can have a defaultValue that’s used when the variable isn’t provided during compilation.