Procedural memory + REPL context package with DSPy 3.0 integration for autonomous agents
Project description
rec-praxis-rlm
Procedural Memory + REPL Context for Autonomous AI Agents
A Python package that provides persistent procedural memory and safe code execution capabilities for DSPy 3.0 autonomous agents, enabling experience-based learning and programmatic document manipulation.
Features
- Procedural Memory: Store and retrieve agent experiences with hybrid similarity scoring (environmental + goal embeddings)
- FAISS Indexing: 10-100x faster retrieval at scale (>10k experiences)
- RLM Context: Programmatic document inspection (grep, peek, head, tail) with ReDoS protection
- Safe Code Execution: Sandboxed Python REPL with AST validation and restricted builtins
- DSPy 3.0 Integration: Autonomous planning with ReAct agents and integrated tools
- MLflow Observability: Automatic tracing and experiment tracking
- Production Ready: 99.38% test coverage, comprehensive error handling, backward-compatible storage versioning
Quick Start
Installation
# Basic installation
pip install rec-praxis-rlm
# With all optional dependencies (FAISS, OpenAI, async support)
pip install rec-praxis-rlm[all]
# Development installation
pip install rec-praxis-rlm[dev]
Example 1: Procedural Memory
from rec_praxis_rlm.memory import ProceduralMemory, Experience
from rec_praxis_rlm.config import MemoryConfig
# Initialize memory
config = MemoryConfig(storage_path="./agent_memory.jsonl")
memory = ProceduralMemory(config)
# Store experiences
memory.store(Experience(
env_features=["web_scraping", "python", "beautifulsoup"],
goal="extract product prices from e-commerce site",
action="Used BeautifulSoup with CSS selectors for price elements",
result="Successfully extracted 1000 prices with 99% accuracy",
success=True
))
# Recall similar experiences
experiences = memory.recall(
env_features=["web_scraping", "python"],
goal="extract data from website",
top_k=5
)
for exp in experiences:
print(f"Similarity: {exp.similarity_score:.2f}")
print(f"Action: {exp.action}")
print(f"Result: {exp.result}\n")
Example 2: RLM Context for Document Inspection
from rec_praxis_rlm.rlm import RLMContext
from rec_praxis_rlm.config import ReplConfig
# Initialize context
config = ReplConfig()
context = RLMContext(config)
# Add documents
with open("application.log", "r") as f:
context.add_document("app_log", f.read())
# Search for patterns
matches = context.grep(r"ERROR.*database", doc_id="app_log")
for match in matches:
print(f"Line {match.line_number}: {match.match_text}")
print(f"Context: ...{match.context_before}{match.match_text}{match.context_after}...")
# Extract specific ranges
error_section = context.peek("app_log", start_char=1000, end_char=2000)
# Get first/last N lines
recent_logs = context.tail("app_log", n_lines=50)
Example 3: Safe Code Execution
from rec_praxis_rlm.rlm import RLMContext
context = RLMContext()
# Execute safe code
result = context.safe_exec("""
total = 0
for i in range(10):
total += i * 2
total
""")
if result.success:
print(f"Output: {result.output}")
print(f"Execution time: {result.execution_time_seconds:.3f}s")
else:
print(f"Error: {result.error}")
# Prohibited operations are blocked
result = context.safe_exec("import os; os.system('rm -rf /')")
# Result: ExecutionError - Import statements not allowed
Example 4: Autonomous Planning with DSPy
from rec_praxis_rlm.dspy_agent import PraxisRLMPlanner
from rec_praxis_rlm.memory import ProceduralMemory
from rec_praxis_rlm.config import PlannerConfig, MemoryConfig
# Initialize memory and planner
memory = ProceduralMemory(MemoryConfig())
planner = PraxisRLMPlanner(
memory=memory,
config=PlannerConfig(lm_model="openai/gpt-4o-mini")
)
# Add context for document inspection
from rec_praxis_rlm.rlm import RLMContext
context = RLMContext()
context.add_document("logs", open("server.log").read())
planner.add_context(context, "server_logs")
# Autonomous planning
answer = planner.plan(
goal="Analyze server errors and suggest fixes",
env_features=["production", "high_traffic", "database"]
)
print(answer)
Architecture
┌─────────────────────────────────────────┐
│ PraxisRLMPlanner (DSPy ReAct) │
│ Autonomous decision-making layer │
├─────────────────┬───────────────────────┤
│ │ │
│ Tools │ Tools │
│ │ │
▼ ▼ ▼
┌─────────────┐ ┌──────────────┐ ┌─────────────┐
│ Procedural │ │ RLMContext │ │ External │
│ Memory │ │ (Facade) │ │ APIs │
├─────────────┤ ├──────────────┤ └─────────────┘
│ • recall() │ │ DocumentStore│
│ • store() │ │ DocSearcher │
│ • compact() │ │ CodeExecutor │
├─────────────┤ └──────────────┘
│ Embeddings │
│ ┌─────────┐ │
│ │ Local │ │ FAISS Index (optional)
│ │ API │ │ ┌──────────────┐
│ │ Jaccard │◄─┼──┤ 10-100x │
│ └─────────┘ │ │ faster search│
└─────────────┘ └──────────────┘
│
▼
Storage (JSONL)
• Append-only
• Versioned
• Crash-safe
Performance
| Operation | Without FAISS | With FAISS | Speedup |
|---|---|---|---|
| Recall (100 exp) | ~2ms | ~2ms | 1x |
| Recall (1,000 exp) | ~20ms | ~3ms | 6.7x |
| Recall (10,000 exp) | ~200ms | ~20ms | 10x |
| Recall (100,000 exp) | ~2000ms | ~20ms | 100x |
| Operation | Performance | Notes |
|---|---|---|
| Document grep (10MB) | <500ms | With ReDoS protection |
| Safe code execution | <100ms | Sandboxed environment |
| Memory loading (10k exp) | <1s | With lazy loading |
Configuration
Memory Configuration
from rec_praxis_rlm.config import MemoryConfig
config = MemoryConfig(
storage_path="./memory.jsonl",
top_k=6, # Number of experiences to retrieve
similarity_threshold=0.5, # Minimum similarity score
env_weight=0.6, # Weight for environmental features
goal_weight=0.4, # Weight for goal similarity
require_success=False, # Only retrieve successful experiences
embedding_model="sentence-transformers/all-MiniLM-L6-v2",
result_size_limit=50000 # Max result size in bytes
)
REPL Configuration
from rec_praxis_rlm.config import ReplConfig
config = ReplConfig(
max_output_chars=10000, # Max output capture
max_search_matches=100, # Max grep results
search_context_chars=200, # Context before/after match
execution_timeout_seconds=5.0, # Code execution timeout
enable_sandbox=True, # Use sandboxed execution
log_executions=True, # Log for audit trail
allowed_builtins=[ # Allowed built-in functions
"len", "range", "sum", "max", "min", "sorted", ...
]
)
Planner Configuration
from rec_praxis_rlm.config import PlannerConfig
config = PlannerConfig(
lm_model="openai/gpt-4o-mini", # Language model
temperature=0.0, # Sampling temperature
max_iters=10, # Max ReAct iterations
enable_mlflow_tracing=True, # MLflow observability
optimizer="miprov2", # DSPy optimizer
optimizer_auto_level="medium" # Automation level
)
Testing
# Run all tests
pytest
# Run with coverage
pytest --cov=rec_praxis_rlm --cov-report=html
# Run specific test suites
pytest tests/unit/ # Unit tests
pytest tests/integration/ # Integration tests
# Run performance tests
pytest tests/unit/test_memory.py -k "performance"
Current test coverage: 99.38% (327 passing tests)
Security
Sandboxed Code Execution
The SafeExecutor provides multiple layers of security:
- AST Validation: Blocks imports, eval, exec, file I/O, network access
- Restricted Builtins: Only safe functions allowed (configurable)
- Execution Timeout: Prevents infinite loops
- Output Limiting: Prevents memory exhaustion
- Code Hashing: Audit trail for all executed code
Blocked operations:
- All imports (
import,from ... import) - Dangerous builtins (
eval,exec,__import__,compile,open) - File system access
- Network access
- Privileged attributes (
__class__,__globals__,__dict__)
ReDoS Protection
The DocumentSearcher validates regex patterns to prevent Regular Expression Denial of Service attacks:
- Pattern length limits (<500 chars)
- Nested quantifier detection (
(a+)+) - Excessive wildcard detection (>3 instances of
.*or.+) - Overlapping alternation warnings
Advanced Features
Async Support
import asyncio
from rec_praxis_rlm.memory import ProceduralMemory
from rec_praxis_rlm.rlm import RLMContext
async def main():
memory = ProceduralMemory(config)
context = RLMContext(config)
# Async memory recall
experiences = await memory.arecall(
env_features=["python"],
goal="debug error"
)
# Async code execution
result = await context.asafe_exec("sum(range(1000000))")
asyncio.run(main())
Custom Embedding Providers
from rec_praxis_rlm.embeddings import APIEmbedding
from rec_praxis_rlm.memory import ProceduralMemory
# Use OpenAI embeddings
embedding_provider = APIEmbedding(
api_provider="openai",
api_key="sk-...",
model_name="text-embedding-3-small"
)
memory = ProceduralMemory(
config,
embedding_provider=embedding_provider
)
Memory Maintenance
# Compact memory (remove old/low-value experiences)
memory.compact(max_size=1000, min_similarity=0.7)
# Recompute embeddings (after changing embedding model)
new_provider = SentenceTransformerEmbedding("new-model")
memory.recompute_embeddings(new_provider)
Custom Metrics
from rec_praxis_rlm.metrics import memory_retrieval_quality, SemanticF1Score
# Memory retrieval quality metric
score = memory_retrieval_quality(
example={"env_features": [...], "goal": "...", "expected_success_rate": 0.8},
prediction=retrieved_experiences
)
# Semantic F1 scoring for DSPy optimization
f1_metric = SemanticF1Score(relevance_threshold=0.7)
score = f1_metric(example, prediction)
MLflow Integration
from rec_praxis_rlm.telemetry import setup_mlflow_tracing
# Enable automatic MLflow tracing
setup_mlflow_tracing(experiment_name="my-agent-experiment")
# All DSPy operations are now traced automatically
planner = PraxisRLMPlanner(memory, config)
result = planner.plan(goal="...", env_features=[...])
# View traces in MLflow UI
# mlflow ui --port 5000
Examples
See the examples/ directory for complete examples:
quickstart.py- Basic memory and context usagelog_analyzer.py- Log analysis with RLM contextweb_agent.py- Web scraping agent with procedural memoryoptimization.py- DSPy MIPROv2 optimizer usage
Contributing
Contributions welcome! Please see CONTRIBUTING.md for guidelines.
License
MIT License - see LICENSE for details.
Citation
If you use rec-praxis-rlm in your research, please cite:
@software{rec_praxis_rlm,
title = {rec-praxis-rlm: Procedural Memory and REPL Context for Autonomous Agents},
author = {Your Name},
year = {2025},
url = {https://github.com/your-org/rec-praxis-rlm}
}
Acknowledgments
- Built on DSPy 3.0 for autonomous agent capabilities
- Uses sentence-transformers for semantic embeddings
- Integrated with MLflow for experiment tracking
- FAISS for fast similarity search
Support
- Documentation: Full API docs
- Issues: GitHub Issues
- Discussions: GitHub Discussions
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file rec_praxis_rlm-0.1.1.tar.gz.
File metadata
- Download URL: rec_praxis_rlm-0.1.1.tar.gz
- Upload date:
- Size: 33.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9b40098fdd1abddb36f1a5d94cf751684610b0bd3c61c8a2a9fe66bd44851544
|
|
| MD5 |
7192468d4d3cddea6ac3a77c7d4b8816
|
|
| BLAKE2b-256 |
f8eeb472ccc262a170d2801f3afbfb57f4264d5d5bd78d5d5994a3e37edaaa8e
|
File details
Details for the file rec_praxis_rlm-0.1.1-py3-none-any.whl.
File metadata
- Download URL: rec_praxis_rlm-0.1.1-py3-none-any.whl
- Upload date:
- Size: 32.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6cc1208755fd2cc9bd0094b71031e6e02fe062923457465236e2d76b85bb576b
|
|
| MD5 |
17e1730db048e569277f2592305b2613
|
|
| BLAKE2b-256 |
f7a2f66aa8b358e175023f7a2465f8b5f2ea81b7bd02aed42c830588299c03d9
|