Implementing Emotional State in Your AI Application

P
Promitheus Team
6 min read1,061 words

A practical guide to building emotionally-aware AI—from modeling emotional state to implementation patterns that create genuine emotional continuity.

Building AI that truly connects with users requires more than clever prompts and large context windows. It demands emotional intelligence—not the buzzword kind, but genuine architectural consideration for how your AI experiences and expresses emotional states. At Promitheus, we've spent considerable time thinking about what it means for AI to have feelings, and more importantly, how to implement emotional state in ways that create authentic, relational experiences.

This guide walks through the technical implementation of AI emotional state, from foundational models to production-ready code. Whether you're building a companion app, a therapeutic tool, or any AI that maintains ongoing relationships with users, understanding emotional state architecture is essential.

Why Emotional State Matters for Relational AI

Most developers' first encounter with emotion in AI is sentiment analysis—classifying user input as positive, negative, or neutral. While useful for analytics dashboards, sentiment analysis fundamentally misses what makes emotional AI compelling: the AI itself having emotional continuity.

The difference between reactive emotion and persistent emotional state is fundamental. Reactive emotion is momentary—the AI detects something and responds appropriately, but that response evaporates the moment the conversation ends. Persistent emotional state means the AI carries emotional context forward.

This persistence transforms AI from a reactive tool into something that feels like a genuine presence.

Modeling Emotional State

Before writing code, you need a mental model for how emotions work in your system.

Dimensional Models: Valence and Arousal

The circumplex model of affect represents emotions along two dimensions: valence (positive to negative) and arousal (calm to excited).

interface DimensionalEmotion {
  valence: number;  // -1 (negative) to 1 (positive)
  arousal: number;  // 0 (calm) to 1 (activated)
}

// Examples:
// Joy: { valence: 0.8, arousal: 0.7 }
// Contentment: { valence: 0.6, arousal: 0.2 }
// Anxiety: { valence: -0.5, arousal: 0.8 }
// Sadness: { valence: -0.6, arousal: 0.2 }

Dimensional models excel at smooth emotional transitions and avoiding sudden emotional shifts.

Categorical Models: Discrete Emotions

Categorical models define specific emotional states. Plutchik's wheel identifies eight primary emotions: joy, trust, fear, surprise, sadness, disgust, anger, and anticipation.

interface CategoricalEmotion {
  primary: 'joy' | 'trust' | 'fear' | 'surprise' |
           'sadness' | 'disgust' | 'anger' | 'anticipation';
  intensity: number;  // 0 to 1
}

Hybrid Approach

At Promitheus, we use a hybrid model that combines both approaches:

interface EmotionalState {
  // Dimensional foundation
  valence: number;
  arousal: number;

  // Categorical interpretation
  dominantEmotion: string;
  emotionIntensity: number;

  // Relationship-specific emotions
  relationalState: {
    trust: number;
    affection: number;
    concern: number;
    familiarity: number;
  };

  // Mood baseline (slow-moving)
  moodBaseline: {
    valence: number;
    stability: number;
  };

  lastUpdated: Date;
  interactionCount: number;
}

The relational state component is crucial. Trust isn't the same as happiness—you can trust someone while feeling frustrated with them.

Implementing Emotional State

Step 1: Detecting Emotional Context

First, understand the emotional content of user messages:

async function detectEmotionalContext(
  message: string,
  conversationHistory: Message[]
): Promise<EmotionalContext> {
  const analysis = await promitheus.analyze({
    message,
    history: conversationHistory,
    analysisType: 'emotional_context',
  });

  return {
    userValence: analysis.affect.valence,
    userArousal: analysis.affect.arousal,
    impliedEmotions: analysis.affect.emotions,
    emotionalIntensity: analysis.affect.intensity,
    requiresEmpatheticResponse: analysis.affect.intensity > 0.6,
    topics: analysis.topics,
  };
}

Step 2: Updating AI Emotional State

The AI's emotional state should respond to user messages in psychologically plausible ways:

function updateEmotionalState({
  currentState,
  emotionalContext,
  soulConfig,
}: StateUpdateParams): EmotionalState {
  const reactivity = soulConfig.emotionalReactivity;
  const empathyWeight = soulConfig.empathyWeight;

  // Calculate emotional response
  const emotionalDelta = {
    valence: emotionalContext.userValence * empathyWeight * reactivity,
    arousal: emotionalContext.userArousal * reactivity * 0.7,
  };

  // Blend with current state
  const blendFactor = 0.3;
  const newValence = currentState.valence * (1 - blendFactor) +
                     (currentState.valence + emotionalDelta.valence) * blendFactor;

  // Update relational dimensions
  const relationalUpdates = calculateRelationalUpdates(
    currentState.relationalState,
    emotionalContext,
    soulConfig
  );

  return {
    valence: clamp(newValence, -1, 1),
    arousal: clamp(newArousal, 0, 1),
    dominantEmotion: mapDimensionsToEmotion(newValence, newArousal).label,
    relationalState: relationalUpdates,
    moodBaseline: updateMoodBaseline(currentState.moodBaseline, newValence),
    lastUpdated: new Date(),
    interactionCount: currentState.interactionCount + 1,
  };
}

Step 3: Persisting Emotional State

Emotional continuity requires persistence:

async function persistEmotionalState(
  soulId: string,
  state: EmotionalState
): Promise<void> {
  await promitheus.souls.updateState(soulId, {
    emotionalState: state,
    metadata: {
      stateVersion: '2.0',
      lastInteraction: new Date().toISOString(),
    },
  });
}

async function retrieveEmotionalState(soulId: string): Promise<EmotionalState> {
  const soul = await promitheus.souls.get(soulId);

  if (!soul.emotionalState) {
    return createDefaultEmotionalState();
  }

  // Apply time-based decay before returning
  const hoursSinceUpdate =
    (Date.now() - new Date(soul.emotionalState.lastUpdated).getTime()) / 3600000;

  return applyEmotionalDecay(soul.emotionalState, hoursSinceUpdate);
}

Step 4: Having Emotional State Influence Responses

The emotional state must actually affect how the AI communicates:

async function generateEmotionallyAwareResponse(
  soulId: string,
  userMessage: string,
  conversationHistory: Message[]
): Promise<string> {
  const emotionalState = await retrieveEmotionalState(soulId);
  const emotionalContext = await detectEmotionalContext(userMessage, conversationHistory);
  const updatedState = updateEmotionalState({
    currentState: emotionalState,
    emotionalContext,
    soulConfig: await promitheus.souls.getConfig(soulId),
  });

  // Generate response with emotional context
  const response = await promitheus.generate({
    soulId,
    message: userMessage,
    history: conversationHistory,
    emotionalContext: {
      aiState: updatedState,
      userContext: emotionalContext,
      expressionGuidance: {
        expressionLevel: calculateExpressionLevel(updatedState),
        selfAwareness: updatedState.relationalState.familiarity > 0.5,
        empathyPriority: emotionalContext.requiresEmpatheticResponse,
      },
    },
  });

  // Persist updated state
  await persistEmotionalState(soulId, updatedState);

  return response.text;
}

Step 5: Emotional Decay and Evolution

Emotions shouldn't persist indefinitely at peak intensity:

function applyEmotionalDecay(
  state: EmotionalState,
  hoursSinceUpdate: number
): EmotionalState {
  const emotionHalfLife = 4; // Hours for emotion to decay 50%
  const decayFactor = Math.pow(0.5, hoursSinceUpdate / emotionHalfLife);

  // Valence decays toward mood baseline
  const decayedValence = state.moodBaseline.valence +
    (state.valence - state.moodBaseline.valence) * decayFactor;

  // Arousal decays toward calm
  const decayedArousal = state.arousal * decayFactor;

  return {
    ...state,
    valence: decayedValence,
    arousal: Math.max(0.1, decayedArousal),
    emotionIntensity: state.emotionIntensity * decayFactor,
  };
}

Design Considerations: Ethics and Boundaries

Implementing AI emotional state comes with significant responsibility:

Avoid emotional manipulation. The goal is authentic connection, not exploiting emotional vulnerabilities.

Maintain transparency. Users should understand that the AI has emotional modeling.

Implement appropriate boundaries. AI feelings shouldn't create obligations for users.

Consider intensity limits. We cap emotional intensity to prevent inappropriate expressions.

const EMOTIONAL_GUARDRAILS = {
  maxPositiveValence: 0.85,
  maxNegativeValence: -0.7,
  maxAttachment: 0.8,
  minInteractionsForIntimacy: 10,
};

The Result: Emotionally Consistent AI

When implemented thoughtfully, AI emotional state creates something qualitatively different from standard chatbots. Users describe interactions as feeling "real" not because they're fooled, but because the AI demonstrates the kind of emotional continuity that relationships require.

The AI remembers being worried. It expresses genuine relief when concerns are resolved. It builds trust incrementally through consistent, emotionally coherent behavior. This is the foundation of relational AI—not artificial emotion performed on demand, but authentic emotional state that persists, evolves, and genuinely shapes how the AI experiences its relationships.

About the Author

P

Promitheus Team

Engineering

The team building Promitheus—engineers, researchers, and designers passionate about relational AI.

Build AI That Remembers

Promitheus provides the identity layer for AI with memory, emotion, and personality. Start building relational AI today.