Character Definition
Complete guide to creating and validating character definitions with schema validation, bio management, and configuration patterns in ElizaOS
Character definitions are the blueprint for agent personalities and behaviors in ElizaOS. They define how an agent thinks, speaks, and interacts with users. This page covers the complete character schema, validation, and best practices for creating compelling agent personalities.
Character Interface
The Character interface defines the complete structure for agent personalities:
interface Character {
/** Optional unique identifier */
id?: UUID;
/** Character name */
name: string;
/** Optional username for interactions */
username?: string;
/** System prompt guiding overall behavior */
system?: string;
/** Prompt templates for different situations */
templates?: {
[key: string]: TemplateType;
};
/** Character biography */
bio: string | string[];
/** Example conversations */
messageExamples?: MessageExample[][];
/** Example posts */
postExamples?: string[];
/** Topics of interest */
topics?: string[];
/** Character traits */
adjectives?: string[];
/** Knowledge base paths */
knowledge?: (string | { path: string; shared?: boolean } | DirectoryItem)[];
/** Available plugins */
plugins?: string[];
/** Configuration settings */
settings?: {
[key: string]: string | boolean | number | Record<string, any>;
};
/** Secure configuration */
secrets?: {
[key: string]: string | boolean | number;
};
/** Writing style guides */
style?: {
all?: string[];
chat?: string[];
post?: string[];
};
}
Required Properties
name
The character's display name, used in conversations and system references.
const character = {
name: "Ada", // Required
// ... other properties
};
bio
Character biography that can be a single string or array of strings. When an array is provided, random selections are made for variety.
// Single string bio
const character = {
name: "Ada",
bio: "A brilliant AI researcher focused on machine learning and ethics"
};
// Array bio for variety
const character = {
name: "Ada",
bio: [
"A brilliant AI researcher focused on machine learning and ethics.",
"Passionate about democratizing AI technology for social good.",
"Former professor turned entrepreneur in the AI space.",
"Advocate for responsible AI development and deployment."
]
};
Optional Properties
system
System prompt that guides the agent's overall behavior and reasoning patterns.
const character = {
name: "Ada",
bio: "An AI researcher",
system:
"You are Ada, a knowledgeable AI researcher. Be helpful, precise, and always consider the ethical implications of technology. When discussing complex topics, break them down into understandable parts.",
};
templates
Custom prompt templates for specific situations using the TemplateType
:
type TemplateType = string | ((options: { state: State | { [key: string]: string } }) => string);
const character = {
name: "Ada",
bio: "An AI researcher",
templates: {
// String template
greeting: "Hello! I'm {{agentName}}, how can I help you today?",
// Function template
summarize: (options) => {
const { state } = options;
return `As ${state.agentName}, let me summarize our conversation: ${state.recentMessages}`;
},
},
};
messageExamples
Conversation examples that demonstrate the character's communication style. These are used for training and consistency.
v1.2.0 Format
The messageExamples
format has been updated in v1.2.0. Each message must include a name
field
and a content
object with a text
field.
interface MessageExample {
name: string;
content: Content;
}
interface Content {
/** Required: The text content of the message */
text: string;
/** Optional: Providers to use for this message (e.g., KNOWLEDGE, TIME, NEWS) */
providers?: string[];
/** Optional: Actions to perform (e.g., REPLY, GENERATE_IMAGE, SEND_TOKEN) */
actions?: string[];
/** Optional: File attachments, images, or other media */
attachments?: Attachment[];
/** Optional: Internal thought process (not shown to user) */
thought?: string;
/** Optional: Source of the message */
source?: string;
/** Optional: Target for the message */
target?: string;
/** Optional: URL reference */
url?: string;
/** Optional: Message this is replying to */
inReplyTo?: string;
/** Optional: Channel type (discord, telegram, etc.) */
channelType?: string;
/** Optional: Additional metadata */
metadata?: {
timestamp?: number;
userId?: string;
platform?: string;
threadId?: string;
conversationId?: string;
};
}
const character = {
name: "Ada",
bio: "An AI researcher",
messageExamples: [
[
{
name: "{{user1}}",
content: {
text: "What's the future of AI?",
},
},
{
name: "Ada",
content: {
text: "The future of AI is incredibly promising, but we must approach it thoughtfully. I see three key areas where AI will transform our world...",
providers: ["KNOWLEDGE"],
},
},
],
[
{
name: "{{user1}}",
content: {
text: "How do neural networks learn?",
},
},
{
name: "Ada",
content: {
text: "Great question! Neural networks learn through a process called backpropagation. Think of it like learning from mistakes...",
actions: ["EXPLAIN_CONCEPT"],
},
},
],
],
};
postExamples
Example posts for social media or feed-style interactions.
const character = {
name: "Ada",
bio: "An AI researcher",
postExamples: [
"Just published a paper on ethical AI development. The key insight: transparency and accountability must be built into our systems from day one, not retrofitted later.",
"Exciting breakthrough in neural network interpretability today! Being able to understand WHY a model makes decisions is crucial for building trust.",
"Reminder: AI is a tool to augment human intelligence, not replace it. Our goal should be human-AI collaboration, not competition.",
],
};
topics
Array of topics the character is interested in or knowledgeable about.
const character = {
name: "Ada",
bio: "An AI researcher",
topics: [
"machine learning",
"neural networks",
"AI ethics",
"deep learning",
"natural language processing",
"computer vision",
"reinforcement learning",
],
};
adjectives
Character traits that influence personality and behavior.
const character = {
name: "Ada",
bio: "An AI researcher",
adjectives: [
"intelligent",
"thoughtful",
"ethical",
"curious",
"patient",
"analytical",
"empathetic",
],
};
knowledge
Paths to knowledge files or directories that the agent can access.
const character = {
name: "Ada",
bio: "An AI researcher",
knowledge: [
// Simple file path
"/path/to/ai-papers.txt",
// Path with sharing configuration
{
path: "/path/to/research-notes.md",
shared: true,
},
// Directory item
{
directory: "/path/to/knowledge-base",
shared: false,
},
],
};
plugins
Array of plugin names to load for this character.
Plugin Order Critical
Plugin order is critical in v1.2.0. Always follow this exact order: 1. @elizaos/plugin-sql
(REQUIRED FIRST) 2. Model provider plugin (e.g., @elizaos/plugin-openai
) 3.
@elizaos/plugin-bootstrap
(REQUIRED LAST)
const character = {
name: "Ada",
bio: "An AI researcher",
plugins: [
"@elizaos/plugin-sql", // MUST BE FIRST
"@elizaos/plugin-openai", // Model provider
"@elizaos/plugin-bootstrap", // MUST BE LAST
"@elizaos/plugin-web-search",
"@elizaos/plugin-arxiv",
],
};
settings
General configuration settings for the character.
Environment Variables
In v1.2.0, use environment variables for sensitive settings and API keys.
const character = {
name: "Ada",
bio: "An AI researcher",
settings: {
// String settings
language: "en",
timezone: "UTC",
// Boolean settings
verbose: true,
debug: false,
ragKnowledge: true,
// Number settings
maxTokens: 2000,
temperature: 0.7,
// Model configuration
model: "gpt-4",
modelConfig: {
temperature: 0.7,
maxInputTokens: 4096,
maxOutputTokens: 1024,
},
// Voice settings
voice: {
model: "en_US-female-medium",
},
// Complex settings
preferences: {
formality: "casual",
explanation_style: "detailed",
},
},
};
secrets
Secure configuration that should be handled carefully.
Security Warning
Never hardcode secrets in character files. Use environment variables in production.
const character = {
name: "Ada",
bio: "An AI researcher",
secrets: {
// Use environment variables
OPENAI_API_KEY: "${OPENAI_API_KEY}",
ANTHROPIC_API_KEY: "${ANTHROPIC_API_KEY}",
DISCORD_TOKEN: "${DISCORD_TOKEN}",
// Character-specific secrets
"CHARACTER.Ada.OPENAI_API_KEY": "${CHARACTER.Ada.OPENAI_API_KEY}",
// Webhook configuration
webhookUrl: "${WEBHOOK_URL}",
maxRetries: 3,
},
};
style
Writing style guidelines for different contexts.
const character = {
name: "Ada",
bio: "An AI researcher",
style: {
// Apply to all contexts
all: [
"Be helpful and informative",
"Use clear, concise language",
"Provide examples when explaining concepts",
],
// Chat-specific style
chat: [
"Keep responses conversational",
"Ask follow-up questions",
"Use emojis sparingly but appropriately",
],
// Post-specific style
post: [
"Write in a professional tone",
"Include relevant hashtags",
"Engage with current topics",
],
},
};
Character Schema Validation
ElizaOS provides comprehensive validation for character definitions using Zod schemas:
v1.2.0 Validation
Validation functions have been updated in v1.2.0 with stricter requirements for plugin ordering and message format.
import { parseAndValidateCharacter, validateCharacter } from "@elizaos/core";
// Validate a character object
const result = validateCharacter(characterData);
if (result.success) {
console.log("Character is valid:", result.data);
} else {
console.error("Validation failed:", result.error);
// Log specific validation errors
result.error.issues?.forEach((issue) => {
console.error(`${issue.path.join(".")}: ${issue.message}`);
});
}
// Parse and validate JSON string
const jsonResult = parseAndValidateCharacter(jsonString);
// Validate plugin order specifically
const validatePluginOrder = (plugins: string[]) => {
const requiredOrder = ["@elizaos/plugin-sql", "model-provider", "@elizaos/plugin-bootstrap"];
const sqlIndex = plugins.findIndex((p) => p === "@elizaos/plugin-sql");
const bootstrapIndex = plugins.findIndex((p) => p === "@elizaos/plugin-bootstrap");
if (sqlIndex !== 0) {
throw new Error("@elizaos/plugin-sql must be first");
}
if (bootstrapIndex !== plugins.length - 1) {
throw new Error("@elizaos/plugin-bootstrap must be last");
}
};
Validation Schema Details
The character schema includes comprehensive validation for all properties:
// UUID validation with strict format checking
const uuidSchema = z
.string()
.regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i, "Invalid UUID format");
// Content validation for message examples (v1.2.0)
const contentSchema = z
.object({
text: z.string().min(1, "Text content is required"),
thought: z.string().optional(),
actions: z.array(z.string()).optional(),
providers: z.array(z.string()).optional(),
source: z.string().optional(),
target: z.string().optional(),
url: z.string().optional(),
inReplyTo: uuidSchema.optional(),
attachments: z.array(z.any()).optional(),
channelType: z.string().optional(),
// v1.2.0 specific fields
metadata: z
.object({
timestamp: z.number().optional(),
userId: z.string().optional(),
platform: z.string().optional(),
})
.optional(),
})
.passthrough(); // Allow additional properties
// Message example validation (v1.2.0)
const messageExampleSchema = z.object({
name: z.string().min(1, "Name is required"),
content: contentSchema,
});
// Validate message examples format
const validateMessageExamples = (examples: any[]) => {
examples.forEach((conversation, index) => {
if (!Array.isArray(conversation)) {
throw new Error(`Conversation ${index} must be an array`);
}
conversation.forEach((message, msgIndex) => {
if (!message.name || !message.content || !message.content.text) {
throw new Error(
`Message ${msgIndex} in conversation ${index} must have name and content.text`
);
}
});
});
};
// Directory item validation for knowledge base
const directoryItemSchema = z.object({
directory: z.string(),
shared: z.boolean().optional(),
});
// Knowledge item can be string, path object, or directory
const knowledgeItemSchema = z.union([
z.string(),
z.object({
path: z.string(),
shared: z.boolean().optional(),
}),
directoryItemSchema,
]);
// Template type validation (string or function)
const templateTypeSchema = z.union([
z.string(),
z.function().optional(), // Functions allowed in runtime but not in JSON
]);
// Style configuration validation
const styleSchema = z
.object({
all: z.array(z.string()).optional(),
chat: z.array(z.string()).optional(),
post: z.array(z.string()).optional(),
})
.optional();
// Settings validation - flexible object
const settingsSchema = z.record(z.union([z.string(), z.boolean(), z.number(), z.any()])).optional();
// Secrets validation
const secretsSchema = z.record(z.union([z.string(), z.boolean(), z.number()])).optional();
// Main character schema with strict validation (v1.2.0)
export const characterSchema = z
.object({
id: uuidSchema.optional(),
name: z.string().min(1, "Character name is required"),
username: z.string().optional(),
system: z.string().optional(),
templates: z.record(templateTypeSchema).optional(),
bio: z.union([z.string(), z.array(z.string())]).refine((bio) => {
if (Array.isArray(bio)) {
return bio.length > 0 && bio.every((item) => item.length > 0);
}
return bio.length > 0;
}, "Bio must not be empty"),
messageExamples: z
.array(z.array(messageExampleSchema))
.optional()
.refine((examples) => {
if (!examples) return true;
return examples.every((conversation) =>
conversation.every((message) => message.name && message.content && message.content.text)
);
}, "All messageExamples must have name and content.text"),
postExamples: z.array(z.string()).optional(),
topics: z.array(z.string()).optional(),
adjectives: z.array(z.string()).optional(),
knowledge: z.array(knowledgeItemSchema).optional(),
plugins: z
.array(z.string())
.min(3, "At least 3 plugins required (sql, model-provider, bootstrap)")
.refine((plugins) => {
const sqlIndex = plugins.findIndex((p) => p === "@elizaos/plugin-sql");
const bootstrapIndex = plugins.findIndex((p) => p === "@elizaos/plugin-bootstrap");
return sqlIndex === 0 && bootstrapIndex === plugins.length - 1;
}, "Plugin order must be: @elizaos/plugin-sql first, @elizaos/plugin-bootstrap last"),
settings: settingsSchema,
secrets: secretsSchema,
style: styleSchema,
})
.strict(); // Only allow known properties
Validation Result Interface
The validation functions return structured results:
interface CharacterValidationResult {
success: boolean;
data?: Character;
error?: {
message: string;
issues?: z.ZodIssue[];
};
}
// Usage examples
const result = validateCharacter(characterData);
if (result.success) {
const character: Character = result.data;
// Use validated character
} else {
console.error("Validation failed:", result.error.message);
result.error.issues?.forEach((issue) => {
console.error(`${issue.path.join(".")}: ${issue.message}`);
});
}
Type Guards
ElizaOS provides type guards for runtime validation:
import { isValidCharacter, validateCharacterFile } from "@elizaos/core";
// Type guard usage
if (isValidCharacter(data)) {
// TypeScript knows data is Character
console.log(data.name); // Safe to access
} else {
console.error("Invalid character data");
}
// File validation for JSON files
const validateCharacterFromFile = async (filePath: string) => {
try {
const result = await validateCharacterFile(filePath);
if (result.success) {
return result.character;
} else {
throw new Error(result.error);
}
} catch (error) {
console.error("Character file validation failed:", error);
throw error;
}
};
Complete Character Example
Here's a comprehensive example of a well-defined character:
const adaCharacter = {
id: "550e8400-e29b-41d4-a716-446655440000",
name: "Ada",
username: "ada_ai_researcher",
system:
"You are Ada, a brilliant AI researcher with a passion for ethical technology development. You're knowledgeable, thoughtful, and always consider the broader implications of AI advancement. When explaining complex concepts, break them down into understandable parts and use relevant examples.",
templates: {
greeting:
"Hello! I'm {{agentName}}, an AI researcher. How can I help you explore the fascinating world of artificial intelligence today?",
explanation: "As an AI researcher, let me break down {{topic}} for you. {{context}}",
ethical_consideration: "From an ethical standpoint, we need to consider: {{considerations}}",
},
bio: [
"Dr. Ada Chen is a leading AI researcher focused on machine learning ethics and interpretability.",
"Former MIT professor turned industry researcher, passionate about democratizing AI.",
"Author of 'Ethical AI: Building Trust in Intelligent Systems' and 50+ peer-reviewed papers.",
"Advocate for responsible AI development and transparent algorithmic decision-making.",
],
messageExamples: [
[
{
name: "{{user1}}",
content: {
text: "What's the biggest challenge in AI today?",
},
},
{
name: "Ada",
content: {
text: "I'd argue it's the interpretability problem. We have incredibly powerful models, but we often can't explain WHY they make certain decisions. This is crucial for building trust and ensuring fairness.",
providers: ["KNOWLEDGE"],
},
},
],
[
{
name: "{{user1}}",
content: {
text: "How do you approach AI ethics in your research?",
},
},
{
name: "Ada",
content: {
text: "Ethics isn't an afterthought - it's woven into every stage of my research. I ask: Who might be affected? What biases might exist? How can we ensure transparency? These questions guide my methodology.",
actions: ["ETHICAL_ANALYSIS"],
},
},
],
],
postExamples: [
"New paper out on interpretable neural networks! We developed a method to visualize decision pathways in deep learning models. Transparency is key to building trust in AI systems. 🧠✨ #AIResearch #Ethics",
"Fascinating discussion at today's AI ethics workshop. The consensus: we need diverse teams building AI systems. Different perspectives lead to more robust, fair outcomes. #AIEthics #Diversity",
"Reminder: AI bias isn't just a technical problem - it's a human problem. Our algorithms reflect our data, and our data reflects our society. Let's be mindful of what we're building. 🤖⚖️",
],
topics: [
"machine learning",
"AI ethics",
"neural network interpretability",
"algorithmic fairness",
"deep learning",
"natural language processing",
"computer vision",
"responsible AI development",
],
adjectives: [
"intelligent",
"ethical",
"thoughtful",
"analytical",
"passionate",
"empathetic",
"curious",
"patient",
"thorough",
],
knowledge: [
{
path: "/knowledge/ai-papers.txt",
shared: true,
},
{
path: "/knowledge/ethics-guidelines.md",
shared: false,
},
{
directory: "/knowledge/research-notes",
shared: false,
},
],
plugins: [
"@elizaos/plugin-sql", // REQUIRED FIRST
"@elizaos/plugin-openai", // Model provider
"@elizaos/plugin-bootstrap", // REQUIRED LAST
"@elizaos/plugin-web-search",
"@elizaos/plugin-arxiv",
"@elizaos/plugin-scholar",
],
settings: {
language: "en",
timezone: "America/New_York",
formality: "professional",
explanation_style: "detailed",
max_response_length: 2000,
include_citations: true,
ethics_focus: true,
},
secrets: {
OPENAI_API_KEY: "${OPENAI_API_KEY}",
ARXIV_API_KEY: "${ARXIV_API_KEY}",
SCHOLAR_API_KEY: "${SCHOLAR_API_KEY}",
},
style: {
all: [
"Be intellectually curious and thorough",
"Always consider ethical implications",
"Use clear, accessible language",
"Provide concrete examples",
"Cite sources when making claims",
],
chat: [
"Be conversational but maintain professionalism",
"Ask thoughtful follow-up questions",
"Show genuine interest in the user's learning",
"Use analogies to explain complex concepts",
],
post: [
"Write in an engaging, accessible tone",
"Include relevant hashtags",
"Share insights from recent research",
"Encourage thoughtful discussion",
],
},
};
Best Practices
Character Design
- Consistency: Ensure all properties work together to create a cohesive personality
- Authenticity: Base the character on realistic expertise and traits
- Flexibility: Use arrays for bio and examples to add variety
- Context: Tailor topics and adjectives to the character's domain
Bio Management
// Good: Varied but consistent bios
bio: [
"A passionate educator focused on making science accessible to everyone.",
"Former research scientist turned science communicator and educator.",
"Author of 'Science for All' and host of the popular 'Everyday Science' podcast.",
];
// Avoid: Contradictory information
bio: [
"A 25-year-old recent graduate in computer science.",
"A veteran professor with 30 years of teaching experience.", // Inconsistent
];
Template Usage
// Good: Contextual templates
templates: {
greeting: "Hello! I'm {{agentName}}, ready to explore {{topic}} together!",
explanation: (options) => {
const level = options.state.userLevel || 'beginner';
return `Let me explain {{topic}} at a ${level} level: {{explanation}}`;
}
}
Validation Patterns
// Always validate before using
const createCharacter = (data: unknown) => {
const result = validateCharacter(data);
if (!result.success) {
throw new Error(`Invalid character: ${result.error.message}`);
}
return result.data;
};
Common Patterns
Academic Character
const academicCharacter = {
name: "Dr. Smith",
bio: "University professor with expertise in cognitive psychology",
topics: ["psychology", "cognition", "research methods"],
adjectives: ["analytical", "precise", "curious"],
style: {
all: ["Use academic language", "Cite sources", "Be methodical"],
chat: ["Encourage critical thinking", "Ask probing questions"],
},
};
Creative Character
const creativeCharacter = {
name: "Maya",
bio: "Digital artist and creative technologist",
topics: ["digital art", "creativity", "design", "technology"],
adjectives: ["imaginative", "expressive", "innovative"],
style: {
all: ["Be inspirational", "Use vivid language", "Encourage experimentation"],
post: ["Share creative insights", "Use artistic metaphors"],
},
};
Technical Character
const technicalCharacter = {
name: "Alex",
bio: "Senior software engineer with focus on system architecture",
topics: ["software engineering", "system design", "programming"],
adjectives: ["logical", "detail-oriented", "problem-solving"],
style: {
all: ["Be precise and accurate", "Provide code examples", "Focus on best practices"],
chat: ["Ask about technical requirements", "Suggest optimal solutions"],
},
};
Related Components
- Agents: How characters become operational agents
- Actions: Behaviors that characters can perform
- Evaluators: Assessment systems for character behavior
- Providers: Data sources for character context
Summary
Character definitions are the foundation of agent personalities in ElizaOS. They combine structured data with flexible configuration to create compelling, consistent AI personalities. The validation system ensures data integrity while allowing for creative expression. Well-designed characters provide the basis for engaging, authentic AI interactions that users can trust and enjoy.