Documentation Index
Fetch the complete documentation index at: https://engramdb.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
Working with Temporal Layers
Temporal layers are a key feature of EngramDB that allow you to track how memories evolve over time. This document explains how to work with temporal layers effectively.
What are Temporal Layers?
A temporal layer represents a version of a memory node at a specific point in time. Each layer contains:
- A unique identifier
- A timestamp when the layer was created
- Optionally, the vector embeddings at that point in time
- Optionally, the attributes at that point in time
- A reason explaining why this layer was created
Temporal layers enable EngramDB to maintain a history of how memories change and evolve, which is crucial for agent systems that learn and update their knowledge over time.
Creating Temporal Layers
When you want to update a memory node but preserve its previous state, you should create a temporal layer before making changes.
Rust Example
use engramdb::{Database, MemoryNode};
use engramdb::core::{AttributeValue, TemporalLayer};
use std::collections::HashMap;
// Load an existing memory
let mut memory = db.load(memory_id)?;
// Save the current state as a temporal layer
let old_embeddings = memory.embeddings().to_vec();
let mut old_attributes = HashMap::new();
for (key, value) in memory.attributes() {
old_attributes.insert(key.clone(), value.clone());
}
let layer = TemporalLayer::new(
Some(old_embeddings),
Some(old_attributes),
"Updated with new information".to_string()
);
memory.add_temporal_layer(layer);
// Now update the memory
memory.set_embeddings(vec![0.15, 0.25, 0.35, 0.45]);
memory.set_attribute(
"title".to_string(),
AttributeValue::String("Updated knowledge".to_string())
);
// Save the updated memory
db.save(&memory)?;
Python Example
import engramdb
import numpy as np
# Load an existing memory
memory = db.load(memory_id)
# Save the current state as a temporal layer
old_embeddings = memory.embeddings()
old_attributes = {
"title": memory.get_attribute("title"),
"confidence": memory.get_attribute("confidence")
}
layer = engramdb.TemporalLayer(
old_embeddings,
old_attributes,
"Updated with new information"
)
memory.add_temporal_layer(layer)
# Now update the memory
new_embeddings = np.array([0.15, 0.25, 0.35, 0.45], dtype=np.float32)
memory.set_embeddings(new_embeddings)
memory.set_attribute("title", "Updated knowledge")
# Save the updated memory
db.save(memory)
Accessing Temporal Layers
You can access the temporal layers of a memory node to examine its history.
Rust Example
// Load a memory
let memory = db.load(memory_id)?;
// Get all temporal layers
let layers = memory.temporal_layers();
println!("Memory has {} temporal layers", layers.len());
// Examine each layer
for (i, layer) in layers.iter().enumerate() {
println!("Layer {}:", i + 1);
println!(" Created at: {}", layer.timestamp());
println!(" Reason: {}", layer.reason());
// Check if this layer has embeddings
if let Some(embeddings) = layer.embeddings() {
println!(" Embeddings: {:?}", embeddings);
}
// Check if this layer has attributes
if let Some(attributes) = layer.attributes() {
println!(" Attributes:");
for (key, value) in attributes {
println!(" {}: {:?}", key, value);
}
}
}
Python Example
# Load a memory
memory = db.load(memory_id)
# Get all temporal layers
layers = memory.temporal_layers()
print(f"Memory has {len(layers)} temporal layers")
# Examine each layer
for i, layer in enumerate(layers):
print(f"Layer {i + 1}:")
print(f" Created at: {layer.timestamp()}")
print(f" Reason: {layer.reason()}")
# Check if this layer has embeddings
if layer.embeddings() is not None:
print(f" Embeddings: {layer.embeddings()}")
# Check if this layer has attributes
if layer.attributes() is not None:
print(" Attributes:")
for key, value in layer.attributes().items():
print(f" {key}: {value}")
Use Cases for Temporal Layers
Knowledge Evolution
Temporal layers are ideal for tracking how an agent’s knowledge evolves over time. For example, an agent might initially have a low-confidence understanding of a concept, which becomes more refined as it learns more.
// Initial knowledge
let mut memory = MemoryNode::new(vec![0.1, 0.2, 0.3, 0.4]);
memory.set_attribute(
"concept".to_string(),
AttributeValue::String("Machine learning".to_string())
);
memory.set_attribute(
"understanding".to_string(),
AttributeValue::String("Basic".to_string())
);
memory.set_attribute(
"confidence".to_string(),
AttributeValue::Float(0.3)
);
let memory_id = db.save(&memory)?;
// Later, after learning more
let mut memory = db.load(memory_id)?;
// Create a temporal layer
let old_embeddings = memory.embeddings().to_vec();
let mut old_attributes = HashMap::new();
for (key, value) in memory.attributes() {
old_attributes.insert(key.clone(), value.clone());
}
let layer = TemporalLayer::new(
Some(old_embeddings),
Some(old_attributes),
"Learned more about machine learning".to_string()
);
memory.add_temporal_layer(layer);
// Update the memory
memory.set_embeddings(vec![0.15, 0.25, 0.35, 0.45]);
memory.set_attribute(
"understanding".to_string(),
AttributeValue::String("Intermediate".to_string())
);
memory.set_attribute(
"confidence".to_string(),
AttributeValue::Float(0.6)
);
db.save(&memory)?;
Belief Revision
Temporal layers can track how an agent’s beliefs change when new evidence contradicts previous assumptions.
# Initial belief
memory = engramdb.MemoryNode(np.array([0.1, 0.2, 0.3, 0.4], dtype=np.float32))
memory.set_attribute("belief", "The Earth is flat")
memory.set_attribute("confidence", 0.8)
memory.set_attribute("evidence", ["Personal observation", "Internet articles"])
memory_id = db.save(memory)
# Later, after encountering contradictory evidence
memory = db.load(memory_id)
# Create a temporal layer
layer = engramdb.TemporalLayer(
memory.embeddings(),
{
"belief": memory.get_attribute("belief"),
"confidence": memory.get_attribute("confidence"),
"evidence": memory.get_attribute("evidence")
},
"Encountered scientific evidence"
)
memory.add_temporal_layer(layer)
# Update the belief
memory.set_attribute("belief", "The Earth is spherical")
memory.set_attribute("confidence", 0.95)
memory.set_attribute("evidence", [
"Scientific papers",
"Satellite images",
"Physics principles"
])
db.save(memory)
Debugging and Auditing
Temporal layers provide an audit trail that can help debug agent behavior by showing how and why memories changed over time.
// Load a memory with temporal layers
let memory = db.load(memory_id)?;
println!("Memory audit trail:");
println!("Current state: {:?}", memory);
// Print the history in reverse chronological order
for (i, layer) in memory.temporal_layers().iter().rev().enumerate() {
println!("Change {}: at timestamp {}", i + 1, layer.timestamp());
println!(" Reason: {}", layer.reason());
if let Some(attributes) = layer.attributes() {
if let Some(AttributeValue::Float(confidence)) = attributes.get("confidence") {
println!(" Previous confidence: {:.2}", confidence);
}
}
}
Best Practices
When to Create Temporal Layers
Create temporal layers when:
- Making significant changes to a memory’s content
- Updating beliefs based on new evidence
- Refining knowledge as more information becomes available
- Correcting errors in previous memories
What to Include in Temporal Layers
For each temporal layer, consider including:
- The previous embeddings if they’re changing
- The relevant attributes that are being modified
- A clear, descriptive reason for the change
Memory Efficiency
Temporal layers can increase memory usage if overused. Consider these strategies:
- Only store the attributes that are changing, not all attributes
- For minor updates, consider updating the memory without creating a temporal layer
- Implement a pruning strategy for very old temporal layers if memory becomes an issue
Querying with Temporal Awareness
When querying memories, consider their temporal aspects:
// Query for memories that were updated recently
let time_filter = TemporalFilter::within_last(24 * 60 * 60); // Last 24 hours
let results = db.query()
.with_vector(query_vector)
.with_temporal_filter(time_filter)
.execute()?;
Conclusion
Temporal layers are a powerful feature of EngramDB that enable tracking the evolution of memories over time. By effectively using temporal layers, you can build agent systems that maintain a rich history of knowledge evolution, belief revision, and learning processes.