Conversation Memory & State Management

Version: 6.0.0

Overview

Conversation Memory (IConversationMemory) is the heart of EDDI's stateful architecture. It's a Java object that represents the complete state of a conversation, including history, user data, context, and intermediate processing results. This object is passed through the entire Lifecycle Pipeline, with each task reading from and writing to it.

What is Conversation Memory?

Think of Conversation Memory as a living document that captures everything about a conversation:

  • Who: User ID and agent ID

  • What: All messages exchanged (both user inputs and agent outputs)

  • When: Timestamp of each interaction

  • Context: Data passed from external systems (user profile, session info, etc.)

  • State: Current processing stage (READY, IN_PROGRESS, ENDED, etc.)

  • Properties: Extracted and stored data (user preferences, entities, variables)

  • History: Complete record of all previous conversation steps

Key Concepts

1. Conversation Steps

A conversation is divided into steps, where each step represents one complete interaction cycle:

Each step contains:

  • Input: What the user said

  • Actions: Actions triggered by behavior rules

  • Data: Results from lifecycle tasks (parsed expressions, API responses, LLM outputs)

  • Output: Agent's response

2. Current Step vs Previous Steps

  • Current Step: Writable, being built during lifecycle execution

  • Previous Steps: Read-only, provides conversation history

3. Memory Scopes

EDDI supports different scopes for storing data:

Scope
Lifetime
Use Case

step

Single interaction

Temporary data needed only for this response

conversation

Entire conversation

User preferences, extracted entities (persists across steps)

longTerm

Across conversations

User profile data that should persist between sessions

4. Undo/Redo Support

Conversation Memory supports undo/redo operations:

This enables scenarios like:

  • User makes a mistake and wants to go back

  • Testing different conversation paths

  • Debugging agent behavior

Conversation Memory Structure

Core Properties

Conversation States

How Lifecycle Tasks Use Memory

Each lifecycle task follows this pattern:

Example: Behavior Rules Task

Example: LangChain Task

Example: HTTP Calls Task

Accessing Memory in Configurations

In Output Templates (Qute)

In HTTP Call Body Templates

In Behavior Rule Conditions

Memory Persistence

Storage Mechanism

  1. During Processing: Memory resides in Java heap (fast access)

  2. After Each Step: Memory is serialized and saved to MongoDB

  3. On Next Request: Memory is loaded from MongoDB and cached

Caching Strategy

EDDI uses Caffeine for in-process caching:

  • Fast retrieval of frequently accessed conversations

  • Reduced MongoDB load

  • Size-based eviction with configurable maximum entries

MongoDB Structure

Best Practices

1. Use Appropriate Scopes

2. Clean Up Large Data

If you store large API responses, consider cleaning them after use:

Extract only what you need instead of storing the entire response.

3. Leverage History for Context

When calling LLMs, you can control how much history is sent:

4. Use Context for External Data

Pass data from your application via context instead of hardcoding:

Then access in agent logic:

Memory Flow Example

Let's trace how memory flows through a complete conversation step:

1. User Request

2. Memory Initialization

3. Parser Task Execution

4. Behavior Rules Execution

5. HTTP Call Execution

6. Output Generation

7. Memory Persistence

8. Response to User

Advanced Topics

Accessing Nested Data

Iterating Over History

Conditional Memory Access


Template Variable Reference

When tasks process templates (system prompts, HTTP call bodies, property instructions, output templates), MemoryItemConverter.convert(memory) produces a map with these top-level keys:

Key
Type
Source
Example Access

context

Map<String, Object>

Input context variables set per turn

{context.language}

properties

Map<String, Property>

All conversation properties — includes both session-scoped and longTerm properties loaded from persistent storage

{properties.preferred_language.valueString}

memory

Map with current, last, past

Conversation step data from the pipeline

{memory.current.output}, {memory.last.input}

userInfo

Map with userId

Authenticated user identity

{userInfo.userId}

conversationInfo

Map with conversationId, agentId, etc.

Conversation metadata

{conversationInfo.agentId}

conversationLog

String

Formatted conversation history

{conversationLog}

Key insight: longTerm properties are loaded into conversationProperties at conversation init and are immediately available via {properties.key} in any template. You do NOT need a separate template namespace for persistent data — properties IS the namespace.

When to Use Which

Need
Use
Why

Data from your application

{context.X}

Per-request, set by caller

Persistent user preferences

{properties.X.valueString}

Survives across conversations (scope=longTerm)

Current turn's input/output

{memory.current.X}

Step-level data from the pipeline

Previous turn's data

{memory.last.X}

One step back

Who the user is

{userInfo.userId}

Authenticated identity

Which agent/conversation

{conversationInfo.agentId}

Conversation metadata

Full conversation history

{conversationLog}

Formatted string of all turns


Conversation Lifecycle: Init and Teardown

Understanding what happens at conversation boundaries is critical for features that manage persistent state.

Initialization (Conversation.init())

When a conversation starts or continues:

Pipeline Execution

The LifecycleManager runs all configured tasks in sequence:

Teardown (postConversationLifecycleTasks())

After the pipeline completes:

Key insight: Persistent state is a session concern handled in Conversation.java init/teardown — NOT a pipeline task. If a feature needs to load/save cross-conversation state, it extends the Conversation init/teardown logic. The pipeline processes data for a single turn; session boundaries manage what persists between turns.

Last updated

Was this helpful?