Skip to content

elizaos-plugins/plugin-digitaltwin

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

13 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

@elizaos/plugin-digitaltwin

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.

Overview

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.

Features

  • πŸ€– 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

Quick Start

Installation

bun add @elizaos/plugin-digitaltwin

Basic Setup

  1. Add plugin to your character:
{
  "name": "MyAgent",
  "plugins": ["@elizaos/plugin-digitaltwin"]
}
  1. Configure batch size (optional):
# .env file
DIGITALTWIN_BATCH_SIZE=5  # Process every 5 messages (default: 1 = every message)
  1. Start your agent:
elizaos start

On 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.

Configuration

Environment Variables

Variable Default Description
DIGITALTWIN_BATCH_SIZE 1 Number of messages to batch before processing. 1 = process every message, 5 = process every 5th message

Character Settings

You can also set the batch size in your character file:

{
  "name": "MyAgent",
  "plugins": ["@elizaos/plugin-digitaltwin"],
  "settings": {
    "DIGITALTWIN_BATCH_SIZE": "5"
  }
}

How It Works

  1. Message Observation: The plugin's evaluator observes all messages from users
  2. Batching: Messages are counted in memory until the batch threshold is met
  3. LLM Processing: When threshold is reached, recent conversation is analyzed by LLM
  4. Profile Updates: Character profile is updated with new insights
  5. Storage: Profile stored as component with nested structure: { profile: {...}, _meta: {...} }

Architecture Highlights

  • Per-Source Profiles: Each platform (Discord, Telegram) gets its own digital twin
  • Shared Storage: Uses NIL_UUID for cross-agent shared components
  • Memory Caching: Counter cache reduces DB writes by ~80%
  • Cross-Agent Dedup: Set-based deduplication prevents duplicate processing

Public API

Other plugins can access digital twin data programmatically. See API.md for complete API documentation.

Quick Example

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
}

Available Functions

  • getDigitalTwin() - Get user's character profile
  • getDigitalTwinMeta() - Get metadata (timestamps, counts)
  • getDigitalTwinData() - Get complete data (profile + metadata)
  • hasDigitalTwin() - Check if twin exists
  • getAllDigitalTwinsForEntity() - Get all twins across platforms
  • updateDigitalTwinProfile() - Programmatically update profile
  • getBatchSize() - Get current batch size config
  • getCacheStats() - Get cache statistics for monitoring

See API.md for detailed usage examples and type definitions.

Use Cases

Enhanced Personalization

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
}

Cross-Platform Insights

Aggregate interests across platforms:

const twins = await getAllDigitalTwinsForEntity(userId, runtime);
const allTopics = twins.flatMap(t => t.data.profile.topics ?? []);
const uniqueTopics = [...new Set(allTopics)];

Analytics & Monitoring

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
}

Data Structure

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;
    }
  }
}

Performance Considerations

  • 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

Future Vision: Relationship-Aware Interaction Profiles

The next evolution of the Digital Twin plugin will create relationship-aware interaction profiles that combine:

  1. Agent Character + Digital Twin Profile β†’ Relationship Profile
  2. Pre-calculated Interaction Guidelines - How the agent should best interact with this specific user
  3. Response Generation Instructions - Tailored prompts that eliminate the need for separate character providers
  4. Singular Relationship Profile - A unified profile capturing the dynamic between agent and user

The Vision

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: { ... }
//   }
// }

Benefits

  • 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

Implementation Path

  1. Phase 1 (Current): Model users into digital twins βœ…
  2. Phase 2 (Next): Create relationship profiles combining agent + digital twin
  3. Phase 3: Generate pre-calculated interaction guidelines via LLM
  4. Phase 4: Create relationship-aware provider that replaces character provider
  5. 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.

Documentation

License

See main repository license.

About

character file generation for chatters (the abyss stares back)

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors