Templates & Prompts
Working with templates and prompts in elizaOS for consistent AI interactions
Templates & Prompts
Templates and prompts are the foundation of AI interactions in elizaOS. They provide structured, consistent ways to communicate with AI models while maintaining flexibility for different contexts and use cases.
Overview
elizaOS uses templates to:
- Standardize interactions: Ensure consistent AI behavior across different contexts
- Context injection: Dynamically insert relevant information into prompts
- Personalization: Adapt responses based on character traits and settings
- Modularity: Reuse prompt components across different scenarios
- Maintainability: Update AI behavior without changing code
Template System
Template Types
elizaOS supports several template types for different use cases:
String Templates
Simple text templates with placeholder substitution:
const template = "Hello {{name}}, how can I help you today?";
Function Templates
Dynamic templates that generate content based on state:
const template = ({ state }) => {
const timeOfDay = new Date().getHours() < 12 ? "morning" : "evening";
return `Good ${timeOfDay}, ${state.senderName}!`;
};
Conditional Templates
Templates that adapt based on conditions:
const template = ({ state }) => {
if (state.isFirstMessage) {
return "Welcome! I'm {{characterName}}, nice to meet you.";
} else {
return "How can I help you today?";
}
};
Template Configuration
Templates are configured in the character file:
const character = {
name: "MyAgent",
templates: {
// Message handling template
messageHandlerTemplate: `
You are {{characterName}}.
{{bio}}
{{lore}}
Recent conversation:
{{recentMessages}}
Respond to: {{message}}
`,
// Evaluation template
evaluationTemplate: `
Evaluate if you should respond to this message:
{{message}}
Context: {{context}}
Respond with YES or NO:
`,
// Custom template
customTemplate: ({ state }) => {
return `Custom response for ${state.senderName}`;
},
},
};
Core Templates
Message Handler Template
Controls how the agent responds to messages:
const messageHandlerTemplate = `
# Character
You are {{characterName}}, {{bio}}
# Personality
{{adjectives}}
# Knowledge
{{knowledge}}
# Recent Messages
{{recentMessages}}
# Response Instructions
{{messageDirections}}
# Current Message
{{senderName}}: {{message}}
Respond as {{characterName}}:
`;
Should Respond Template
Determines when the agent should respond:
const shouldRespondTemplate = `
# Context
You are {{characterName}} in a conversation.
# Recent Messages
{{recentMessages}}
# Current Message
{{senderName}}: {{message}}
# Decision
Should {{characterName}} respond to this message?
Consider:
- Is the message directed at you?
- Is it relevant to the conversation?
- Would a response add value?
Respond with YES or NO:
`;
Evaluation Template
Used for evaluating actions and responses:
const evaluationTemplate = `
# Evaluation Task
Evaluate the following interaction:
# Character: {{characterName}}
{{bio}}
# Message: {{message}}
# Response: {{response}}
# Criteria
- Appropriateness
- Consistency with character
- Helpfulness
- Engagement level
# Rating
Rate from 1-10 and explain:
`;
Platform-Specific Templates
Twitter Templates
// elizaOS uses unified templates across platforms for consistency
const twitterTemplates = {
// Tweet generation - uses the same messageHandlerTemplate but with platform-specific context
twitterPostTemplate: messageHandlerTemplate,
// Twitter response - uses the same messageHandlerTemplate
twitterMessageHandlerTemplate: messageHandlerTemplate,
// Twitter engagement decision - uses the same shouldRespondTemplate
twitterShouldRespondTemplate: shouldRespondTemplate,
};
// Note: elizaOS provides platform-specific context through providers
// rather than maintaining separate templates for each platform
Discord Templates
const discordTemplates = {
// Discord message handler - uses the same messageHandlerTemplate
discordMessageHandlerTemplate: messageHandlerTemplate,
// Discord auto-post - uses the same postCreationTemplate
discordAutoPostTemplate: postCreationTemplate,
};
Telegram Templates
const telegramTemplates = {
// Telegram message handler - uses the same messageHandlerTemplate
telegramMessageHandlerTemplate: messageHandlerTemplate,
// Telegram auto-post - uses the same postCreationTemplate
telegramAutoPostTemplate: postCreationTemplate,
};
Template Variables
Standard Variables
Available in all templates:
const standardVariables = {
// Character information
characterName: "Agent name",
bio: "Character biography",
lore: "Character background",
adjectives: "Character traits",
topics: "Known topics",
style: "Communication style",
// Context information
senderName: "Message sender",
message: "Current message",
recentMessages: "Recent conversation",
// Platform information
channelName: "Channel/room name",
serverName: "Server name",
chatName: "Chat name",
// Dynamic content
timestamp: "Current time",
context: "Additional context",
knowledge: "Relevant knowledge",
};
Custom Variables
Add custom variables through providers:
const customProvider = {
name: "CUSTOM_PROVIDER",
get: async (runtime, message, state) => {
return {
values: {
customVariable: "Custom value",
dynamicData: await fetchDynamicData(),
processedContent: processContent(message.content),
},
};
},
};
Template Processing
Variable Substitution
Templates use {{variable}}
syntax for substitution:
const template = "Hello {{name}}, today is {{date}}";
const processed = template.replace("{{name}}", "Alice").replace("{{date}}", "2024-01-15");
Function Template Processing
Function templates receive state and return strings:
const functionTemplate = ({ state }) => {
const greeting = state.isFirstMessage ? "Welcome" : "Hello again";
return `${greeting}, ${state.senderName}!`;
};
const processed = functionTemplate({ state: currentState });
Template Compilation
elizaOS compiles templates for performance:
// Template compilation (internal)
const compiledTemplate = compileTemplate(templateString);
const result = compiledTemplate(variables);
Advanced Template Features
Conditional Content
const conditionalTemplate = ({ state }) => {
let content = "You are {{characterName}}.";
if (state.isFirstMessage) {
content += "\nThis is our first conversation.";
}
if (state.hasKnowledge) {
content += "\nRelevant knowledge: {{knowledge}}";
}
return content;
};
Template Inheritance
const baseTemplate = `
You are {{characterName}}.
{{bio}}
{{specificInstructions}}
`;
const chatTemplate = baseTemplate.replace(
"{{specificInstructions}}",
"Respond conversationally to: {{message}}"
);
const postTemplate = baseTemplate.replace(
"{{specificInstructions}}",
"Create an engaging post about: {{topic}}"
);
Template Composition
const composeTemplate = (parts) => {
return parts.filter(Boolean).join("\n\n");
};
const composedTemplate = composeTemplate([
"# Character\n{{characterName}}",
"# Bio\n{{bio}}",
state.hasLore ? "# Lore\n{{lore}}" : null,
"# Message\n{{message}}",
"# Response\nRespond as {{characterName}}:",
]);
Template Management
Template Registry
class TemplateRegistry {
private templates = new Map();
register(name: string, template: string | Function) {
this.templates.set(name, template);
}
get(name: string) {
return this.templates.get(name);
}
process(name: string, variables: any) {
const template = this.get(name);
if (typeof template === "function") {
return template(variables);
}
return this.substituteVariables(template, variables);
}
private substituteVariables(template: string, variables: any) {
return template.replace(/\{\{(\w+)\}\}/g, (match, key) => {
return variables[key] || match;
});
}
}
Template Versioning
const templateVersions = {
v1: {
messageHandler: "Simple template",
shouldRespond: "Basic decision logic",
},
v2: {
messageHandler: "Enhanced template with context",
shouldRespond: "Improved decision logic",
},
};
const getTemplate = (name: string, version = "v2") => {
return templateVersions[version][name];
};
Template Validation
const validateTemplate = (template: string) => {
const issues = [];
// Check for required variables
const requiredVars = ["characterName", "message"];
for (const req of requiredVars) {
if (!template.includes(`{{${req}}}`)) {
issues.push(`Missing required variable: ${req}`);
}
}
// Check for unclosed variables
const unclosed = template.match(/\{\{[^}]*$/);
if (unclosed) {
issues.push("Unclosed template variable");
}
return issues;
};
Performance Optimization
Template Caching
class TemplateCache {
private cache = new Map();
private maxSize = 100;
get(key: string) {
return this.cache.get(key);
}
set(key: string, value: string) {
if (this.cache.size >= this.maxSize) {
const firstKey = this.cache.keys().next().value;
this.cache.delete(firstKey);
}
this.cache.set(key, value);
}
}
Pre-compilation
const precompileTemplates = (templates: Record<string, string>) => {
const compiled = {};
for (const [name, template] of Object.entries(templates)) {
compiled[name] = compileTemplate(template);
}
return compiled;
};
Best Practices
1. Template Organization
// Group related templates
const messageTemplates = {
handler: "Message handling template",
shouldRespond: "Response decision template",
evaluation: "Message evaluation template",
};
const postTemplates = {
twitter: "Twitter post template",
discord: "Discord post template",
telegram: "Telegram post template",
};
2. Variable Naming
// Use descriptive, consistent names
const template = `
Character: {{characterName}}
Sender: {{senderName}}
Message: {{messageContent}}
Context: {{conversationContext}}
Time: {{currentTimestamp}}
`;
3. Template Documentation
/**
* Message Handler Template
*
* Variables:
* - characterName: The agent's name
* - bio: Character biography
* - message: Current message content
* - senderName: Message sender
* - recentMessages: Recent conversation history
*
* Purpose: Generate contextual responses to messages
*/
const messageHandlerTemplate = `...`;
4. Error Handling
const safeTemplateProcessing = (template: string, variables: any) => {
try {
return processTemplate(template, variables);
} catch (error) {
console.error("Template processing failed:", error);
return "I'm sorry, I encountered an error processing your message.";
}
};
Testing Templates
Unit Testing
describe("Template Processing", () => {
it("should substitute variables correctly", () => {
const template = "Hello {{name}}";
const variables = { name: "Alice" };
const result = processTemplate(template, variables);
expect(result).toBe("Hello Alice");
});
it("should handle missing variables", () => {
const template = "Hello {{name}} {{missing}}";
const variables = { name: "Alice" };
const result = processTemplate(template, variables);
expect(result).toBe("Hello Alice {{missing}}");
});
});
Integration Testing
describe("Template Integration", () => {
it("should generate appropriate responses", async () => {
const runtime = createTestRuntime();
const template = "You are {{characterName}}. Respond to: {{message}}";
const response = await runtime.useModel(ModelType.TEXT_LARGE, {
prompt: processTemplate(template, {
characterName: "TestAgent",
message: "Hello",
}),
});
expect(response).toContain("TestAgent");
});
});
Troubleshooting
Common Issues
-
Variable not substituted
// Check variable name spelling const template = "Hello {{name}}"; // Correct const template = "Hello {{Name}}"; // Wrong case
-
Template function errors
const template = ({ state }) => { // Always check if state exists if (!state || !state.senderName) { return "Default response"; } return `Hello ${state.senderName}`; };
-
Performance issues
// Use caching for expensive operations const expensiveTemplate = ({ state }) => { const cached = templateCache.get(state.key); if (cached) return cached; const result = expensiveOperation(state); templateCache.set(state.key, result); return result; };
Debug Mode
const debugTemplate = (template: string, variables: any) => {
console.log("Template:", template);
console.log("Variables:", variables);
const result = processTemplate(template, variables);
console.log("Result:", result);
return result;
};
Migration Guide
From Static to Dynamic Templates
// Old static template
const oldTemplate = "Hello user, how can I help?";
// New dynamic template
const newTemplate = ({ state }) => {
const greeting = getTimeBasedGreeting();
const name = state.senderName || "user";
return `${greeting} ${name}, how can I help?`;
};
Template Versioning
const migrateTemplates = (oldTemplates: any) => {
const newTemplates = {};
for (const [name, template] of Object.entries(oldTemplates)) {
newTemplates[name] = upgradeTemplate(template);
}
return newTemplates;
};
Templates and prompts are essential for creating consistent, context-aware AI interactions in elizaOS. By leveraging the template system effectively, you can build agents that provide personalized, relevant responses while maintaining consistent behavior across different platforms and scenarios.