Skip to main content

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.

PyPI version Python 3.10+ Tests Test Coverage Code Style: Black License: MIT

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:

  1. AST Validation: Blocks imports, eval, exec, file I/O, network access
  2. Restricted Builtins: Only safe functions allowed (configurable)
  3. Execution Timeout: Prevents infinite loops
  4. Output Limiting: Prevents memory exhaustion
  5. 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 usage
  • log_analyzer.py - Log analysis with RLM context
  • web_agent.py - Web scraping agent with procedural memory
  • optimization.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

Support

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

rec_praxis_rlm-0.1.1.tar.gz (33.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

rec_praxis_rlm-0.1.1-py3-none-any.whl (32.4 kB view details)

Uploaded Python 3

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

Hashes for rec_praxis_rlm-0.1.1.tar.gz
Algorithm Hash digest
SHA256 9b40098fdd1abddb36f1a5d94cf751684610b0bd3c61c8a2a9fe66bd44851544
MD5 7192468d4d3cddea6ac3a77c7d4b8816
BLAKE2b-256 f8eeb472ccc262a170d2801f3afbfb57f4264d5d5bd78d5d5994a3e37edaaa8e

See more details on using hashes here.

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

Hashes for rec_praxis_rlm-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 6cc1208755fd2cc9bd0094b71031e6e02fe062923457465236e2d76b85bb576b
MD5 17e1730db048e569277f2592305b2613
BLAKE2b-256 f7a2f66aa8b358e175023f7a2465f8b5f2ea81b7bd02aed42c830588299c03d9

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page