E2B Code Interpreter Agents + Persistent Memory
Free · Open source (MIT) · Works with LangChain, CrewAI, AutoGen · No signup
Your E2B code interpreter agent works perfectly in development, but every time it starts a new sandbox session, it forgets everything—previous calculations, user preferences, conversation context. This isn't a bug in your code; it's how E2B sandboxes are designed to work. Here's how to add persistent memory that survives between sandbox runs.
The Problem: E2B Sandboxes Reset Everything
E2B sandboxes are stateless by design. Each time your code interpreter agent spins up a new sandbox environment, it starts with a clean slate—no variables, no files, no memory of previous interactions. This creates a frustrating user experience:
# Session 1: User asks agent to calculate something
result = complex_calculation() # Takes 30 seconds
agent_memory["last_result"] = result
# Session 2: User asks follow-up question
# agent_memory is empty again! 😤
# Agent has to recalculate everything from scratch
Your agent might spend minutes re-deriving the same data, or worse, ask users to repeat context they've already provided. The e2b sandbox architecture makes this inevitable—without external persistence, your agent's memory dies with each sandbox.
This breaks the illusion of talking to an intelligent assistant and makes your code interpreter feel clunky compared to ChatGPT's seamless conversations.
The Fix: Add Persistent Memory
Install BotWire to give your E2B agent persistent memory that survives sandbox resets:
pip install botwire
from botwire import Memory
import e2b
# Initialize persistent memory for this user session
agent_memory = Memory("user-session-123")
# Your E2B code interpreter with memory
def run_code_with_memory(code: str, user_id: str):
# Check if we've seen this before
cached_result = agent_memory.get("last_calculation")
if cached_result:
print(f"Remembering: {cached_result}")
# Run code in E2B sandbox
sandbox = e2b.CodeInterpreter()
result = sandbox.notebook.exec_cell(code)
# Persist the result for next time
agent_memory.set("last_calculation", result.text)
agent_memory.set("user_context", user_id)
return result
How It Works
BotWire creates a persistent key-value store that lives outside your E2B sandbox. Each Memory("namespace") creates an isolated memory space—use unique namespaces per user or conversation thread.
The memory persists across processes, machines, and sandbox restarts. Your agent can now maintain context:
from botwire import Memory
# Different memory namespaces for different contexts
user_memory = Memory(f"user-{user_id}")
conversation_memory = Memory(f"chat-{session_id}")
global_memory = Memory("shared-knowledge")
# Store complex data structures
user_memory.set("preferences", {
"language": "python",
"difficulty": "advanced",
"last_topic": "data analysis"
})
# Retrieve across sandbox sessions
prefs = user_memory.get("preferences")
if prefs and prefs["last_topic"] == "data analysis":
# Continue where we left off
conversation_memory.set("context", "continuing data analysis discussion")
Memory operations work immediately—no async/await needed. Data is stored remotely at https://botwire.dev but feels local. You get 1000 writes per day per namespace on the free tier, which covers most agent use cases.
For cleanup, you can delete specific keys or check what's stored:
# Remove outdated data
agent_memory.delete("temporary_result")
# See what's in memory (useful for debugging)
all_keys = agent_memory.list_keys()
print(f"Stored keys: {all_keys}")
Integration with E2B Code Agents
Here's a complete pattern for E2B agents with persistent memory:
from botwire import Memory
import e2b
class PersistentCodeAgent:
def __init__(self, user_id: str):
self.user_id = user_id
self.memory = Memory(f"agent-{user_id}")
self.sandbox = e2b.CodeInterpreter()
def execute_code(self, code: str, context: str = None):
# Load previous context
session_context = self.memory.get("session_context") or {}
# Add current context
if context:
session_context["last_request"] = context
self.memory.set("session_context", session_context)
# Execute in sandbox
result = self.sandbox.notebook.exec_cell(code)
# Store results for future reference
self.memory.set("last_execution", {
"code": code,
"result": result.text,
"timestamp": time.time()
})
return result
def get_conversation_history(self):
return self.memory.get("session_context")
This pattern lets your agent remember user preferences, previous calculations, and conversation context across multiple E2B sandbox sessions.
When NOT to Use BotWire Memory
BotWire isn't the right tool for every use case. Avoid it for:
- Vector embeddings or semantic search — Use Pinecone, Weaviate, or Chroma for similarity search over large datasets
- High-throughput applications — The HTTP API adds ~50ms latency; use Redis for microsecond response times
- Large binary data — 50MB limit per namespace; use S3 or similar for files, images, or massive datasets
FAQ
Q: Why not just use Redis or a database? A: You could, but then you need to manage infrastructure, connections, and scaling. BotWire works instantly with zero setup—no Redis server, no connection strings, no auth.
Q: Is this actually free? A: Yes, 1000 writes/day per namespace forever. That covers most agent development and small production use cases. No credit card required.
Q: What about data privacy? A: Data is stored on BotWire's servers. For sensitive data, self-host the open-source version (it's a single FastAPI + SQLite service) or use your own Redis/database.
Get Started
BotWire turns your stateless E2B sandboxes into stateful agents that remember context across sessions. Install it in 30 seconds: pip install botwire. Full docs and examples at https://botwire.dev.