ElizaOS plugin that automatically models users into digital twin character profiles based on their interactions. Creates AI-powered audience modeling with configurable batching and caching for efficient LLM usage.
The Digital Twin plugin observes user interactions and automatically builds character profiles that capture:
- Personality traits (bio, adjectives, communication style)
- Interests & topics (what they talk about)
- Communication patterns (message examples, post examples)
- Behavioral characteristics (system prompts, style preferences)
These profiles can be used by other plugins to provide personalized experiences, context-aware recommendations, and enhanced agent interactions.
- π€ Automatic Modeling: Observes messages and builds character profiles automatically
- π Configurable Batching: Process messages in batches to reduce LLM costs (default: every message)
- β‘ Performance Optimized: In-memory caching reduces database writes by ~80%
- π Cross-Agent Deduplication: Multiple agents won't duplicate work on the same message
- π Per-Source Profiles: Separate digital twins for each platform (Discord, Telegram, etc.)
- π Public API: Other plugins can access digital twin data programmatically
- π¨ Beautiful Banner: Visual configuration display on plugin initialization
bun add @elizaos/plugin-digitaltwin- Add plugin to your character:
{
"name": "MyAgent",
"plugins": ["@elizaos/plugin-digitaltwin"]
}- Configure batch size (optional):
# .env file
DIGITALTWIN_BATCH_SIZE=5 # Process every 5 messages (default: 1 = every message)- Start your agent:
elizaos startOn startup, you'll see a banner showing the plugin configuration:
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Character: MyAgent β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ£
β βββββββ βββ βββββββ ββββββββββββ ββββββ βββ β Λ₯βΖβ₯IΧ€IβΈ ΠIΚκβ
β βββββββββββββββββββ βββββββββββββββββββββββ β ( reflection )β
β βββ βββββββββ βββββββ βββ βββββββββββ β N I W T β
β βββ βββββββββ ββββββ βββ βββββββββββ β β
β βββββββββββββββββββββββ βββ βββ βββββββββββ β β
β βββββββ βββ βββββββ βββ βββ βββ βββββββββββ β β
β βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ£
β β DIGITALTWIN_BATCH_SIZE 5 custom β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
The plugin will automatically start modeling users as they interact with your agent.
| Variable | Default | Description |
|---|---|---|
DIGITALTWIN_BATCH_SIZE |
1 |
Number of messages to batch before processing. 1 = process every message, 5 = process every 5th message |
You can also set the batch size in your character file:
{
"name": "MyAgent",
"plugins": ["@elizaos/plugin-digitaltwin"],
"settings": {
"DIGITALTWIN_BATCH_SIZE": "5"
}
}- Message Observation: The plugin's evaluator observes all messages from users
- Batching: Messages are counted in memory until the batch threshold is met
- LLM Processing: When threshold is reached, recent conversation is analyzed by LLM
- Profile Updates: Character profile is updated with new insights
- Storage: Profile stored as component with nested structure:
{ profile: {...}, _meta: {...} }
- Per-Source Profiles: Each platform (Discord, Telegram) gets its own digital twin
- Shared Storage: Uses
NIL_UUIDfor cross-agent shared components - Memory Caching: Counter cache reduces DB writes by ~80%
- Cross-Agent Dedup: Set-based deduplication prevents duplicate processing
Other plugins can access digital twin data programmatically. See API.md for complete API documentation.
import { getDigitalTwin } from '@elizaos/plugin-digitaltwin';
// In your action handler
const profile = await getDigitalTwin(
message.entityId,
message.content.source || 'unknown',
runtime
);
if (profile?.topics?.includes('gaming')) {
// Tailor response to gamer
}getDigitalTwin()- Get user's character profilegetDigitalTwinMeta()- Get metadata (timestamps, counts)getDigitalTwinData()- Get complete data (profile + metadata)hasDigitalTwin()- Check if twin existsgetAllDigitalTwinsForEntity()- Get all twins across platformsupdateDigitalTwinProfile()- Programmatically update profilegetBatchSize()- Get current batch size configgetCacheStats()- Get cache statistics for monitoring
See API.md for detailed usage examples and type definitions.
Use digital twin profiles to tailor agent responses:
const profile = await getDigitalTwin(entityId, 'discord', runtime);
if (profile?.topics?.includes('gaming')) {
// Adjust response style for gamers
}Aggregate interests across platforms:
const twins = await getAllDigitalTwinsForEntity(userId, runtime);
const allTopics = twins.flatMap(t => t.data.profile.topics ?? []);
const uniqueTopics = [...new Set(allTopics)];Track profile freshness:
const meta = await getDigitalTwinMeta(userId, 'discord', runtime);
const daysSinceUpdate = (Date.now() - meta.lastProcessedAt) / (1000 * 60 * 60 * 24);
if (daysSinceUpdate > 30) {
// Profile might be stale
}Digital twins are stored as components with this structure:
{
entityId: UUID, // User's entity ID
type: "DIGITAL_TWIN:discord", // Source-specific type
worldId: NIL_UUID, // Shared (not scoped to specific world)
roomId: NIL_UUID, // Shared (not scoped to specific room)
sourceEntityId: NIL_UUID, // Shared
data: {
profile: {
// Character data (what the LLM updates)
name: string;
bio: string[];
system: string;
topics: string[];
style: Record<string, string[]>;
adjectives: string[];
messageExamples: unknown[];
postExamples: string[];
},
_meta: {
// Tracking metadata (internal use)
lastProcessedAt: number;
messageCount: number;
}
}
}- Batch Size: Higher batch sizes reduce LLM calls but delay profile updates
- Caching: In-memory counter cache significantly reduces database operations
- Deduplication: Prevents multiple agents from processing the same message
- Memory Usage: Counter cache grows with unique users; cleared when size > 1000
The next evolution of the Digital Twin plugin will create relationship-aware interaction profiles that combine:
- Agent Character + Digital Twin Profile β Relationship Profile
- Pre-calculated Interaction Guidelines - How the agent should best interact with this specific user
- Response Generation Instructions - Tailored prompts that eliminate the need for separate character providers
- Singular Relationship Profile - A unified profile capturing the dynamic between agent and user
Instead of just modeling users, we'll model relationships:
// Future API (conceptual)
const relationshipProfile = await getRelationshipProfile(
agentId,
userId,
source,
runtime
);
// Returns:
// {
// agentCharacter: { ... },
// userDigitalTwin: { ... },
// relationship: {
// interactionStyle: 'formal' | 'casual' | 'technical',
// preferredTopics: ['gaming', 'crypto'],
// communicationGuidelines: [
// 'User prefers short, direct responses',
// 'Avoid technical jargon unless asked',
// 'Use gaming references when relevant'
// ],
// responseTemplate: '...', // Pre-calculated prompt template
// doNotMention: ['politics', 'religion'], // Topics to avoid
// conversationHistory: { ... }
// }
// }- No Character Provider Needed: The relationship profile contains all context needed for response generation
- Pre-calculated Guidelines: Interaction rules are computed once and reused, reducing LLM calls
- Relationship Memory: Captures how the agent-user relationship evolves over time
- Personalized Responses: Every response is tailored to the specific relationship dynamic
- Efficiency: Single profile replaces multiple providers and context assembly
- Phase 1 (Current): Model users into digital twins β
- Phase 2 (Next): Create relationship profiles combining agent + digital twin
- Phase 3: Generate pre-calculated interaction guidelines via LLM
- Phase 4: Create relationship-aware provider that replaces character provider
- Phase 5: Evolve relationship profiles based on interaction outcomes
This vision transforms digital twins from passive user models into active relationship managers that guide every interaction.
- API.md - Complete public API reference for developers
- DESIGN_DECISIONS.md - π₯ WHY we built it this way - Architectural rationale and design decisions
- src/services/digital-twin-service.ts - Service implementation
See main repository license.