Best Practices

Learn best practices for using the Memory Scope API in production. These guidelines will help you build secure, performant, and maintainable applications.

Security Best Practices

API Key Management

  • Never commit API keys to version control
  • Use environment variables for API keys
  • Rotate API keys regularly
  • Use different keys for different environments
  • Monitor API key usage for suspicious activity

User ID Consistency

  • Use consistent user_id format across all operations
  • Don't use personally identifiable information (PII) in user_id
  • Use a stable identifier that doesn't change

Revocation Token Security

  • Store revocation tokens securely
  • Associate tokens with user sessions
  • Never expose tokens in URLs or logs
  • Provide users with UI to revoke access
Data Organization

Choose the Right Scope

Select the scope that best fits your use case. This affects policy enforcement and merging behavior.

Scope Selection
# Good: Using appropriate scope client.create_memory( user_id="user123", scope="preferences", # Correct scope for user likes/dislikes domain="food", value_json={"likes": ["pizza"]} ) # Bad: Using wrong scope client.create_memory( user_id="user123", scope="constraints", # Wrong scope - constraints are for rules, not preferences domain="food", value_json={"likes": ["pizza"]} )

Use Domains for Organization

Domains help organize memories within a scope. Use them consistently.

Domain Organization
# Good: Using domains consistently client.create_memory( user_id="user123", scope="preferences", domain="food", # Consistent domain for food preferences value_json={"likes": ["pizza"]} ) client.create_memory( user_id="user123", scope="preferences", domain="music", # Different domain for music preferences value_json={"likes": ["jazz"]} )
Policy Enforcement

Use Descriptive Purposes

Write clear, descriptive purpose strings that accurately explain why you're accessing the memory.

Purpose Strings
# Good: Clear, descriptive purpose result = client.read_memory( user_id="user123", scope="preferences", domain="food", purpose="generate personalized food recommendations for user dashboard" ) # Bad: Vague purpose result = client.read_memory( user_id="user123", scope="preferences", domain="food", purpose="read data" # Too vague )

Handle Policy Denials Gracefully

Policy denials are expected in some cases. Always handle them gracefully.

Handling Policy Denials
from memory_scope.exceptions import PolicyDeniedError try: result = client.read_memory( user_id="user123", scope="preferences", domain="food", purpose="execute task to auto-order lunch" ) except PolicyDeniedError: # Handle gracefully - this is expected behavior # Use default values or ask user for permission result = {"likes": [], "dislikes": []} # Fallback
Performance Optimization

Use max_age_days Appropriately

Filter out stale memories to improve performance and relevance.

Using max_age_days
# Good: Filtering stale data result = client.read_memory( user_id="user123", scope="preferences", domain="food", purpose="generate food recommendations", max_age_days=30 # Only get recent preferences )

Cache Responses When Appropriate

Cache API responses to reduce the number of requests, but respect revocation tokens.

Caching Responses
# Cache responses with appropriate TTL cache_key = f"memory:{user_id}:{scope}:{domain}" cached_result = cache.get(cache_key) if cached_result is None: result = client.read_memory(...) # Cache for 5 minutes cache.set(cache_key, result, ttl=300) else: result = cached_result
Error Handling

Always Handle Errors

Implement comprehensive error handling for all API operations.

Error Handling
from memory_scope.exceptions import ( PolicyDeniedError, InvalidRequestError, AuthenticationError, RateLimitError ) try: result = client.read_memory(...) except PolicyDeniedError as e: # Handle policy denial logger.info(f"Policy denied: {e.message}") result = get_default_preferences() except RateLimitError as e: # Handle rate limit with retry logger.warning(f"Rate limit: {e.message}") time.sleep(60) result = client.read_memory(...) # Retry except AuthenticationError as e: # Handle auth error logger.error(f"Auth error: {e.message}") raise except Exception as e: # Handle unexpected errors logger.error(f"Unexpected error: {e}") raise
User Experience

Provide User Control

  • Always provide users with a way to revoke access
  • Show clear messages when data is unavailable
  • Handle empty results gracefully
  • Respect user privacy choices

Use Confidence Scores

Consider confidence scores when making decisions based on merged results. Low confidence may indicate incomplete data.

Using Confidence Scores
result = client.read_memory(...) if result.confidence < 0.5: # Low confidence - data may be incomplete # Ask user to provide more information show_preference_form() else: # High confidence - use the data use_preferences(result.summary_struct)