datamongus
08/27/2025, 9:10 PMMarvin
08/27/2025, 9:10 PMMarvin
08/27/2025, 9:15 PMmem.get_prompt() to retrieve the user’s stored preferences and condition your SQL generation. Use mem.add() to update preferences and mem.delete() to remove a specific entry.
Here’s a concrete pattern you can copy:
- Namespacing: user:{user_id}:sql-prefs
- Provider: use a persistent provider (e.g., Postgres) for cross-process persistence, or stick with the default if you don’t need persistence
- Keep auto_use=False and explicitly fetch memory within the tool so it only impacts this tool’s behavior
Example: SQL generation tool that recalls user preferences
from marvin import fn, generate, Memory
from marvin.memory.providers.postgres import PostgresMemory
# Helper: build a memory for this user's SQL preferences
def user_sql_memory(user_id: str) -> Memory:
return Memory(
key=f"user:{user_id}:sql-prefs",
instructions="User-specific SQL style and access preferences.",
# Use a persistent provider for multi-instance deployment.
# You can omit 'provider=' to use the default from settings (chroma-ephemeral).
provider=PostgresMemory(),
auto_use=False, # keep it opt-in for this tool only
)
# Optional helpers to write/update preferences
def add_sql_preference(user_id: str, preference_text: str) -> str:
"""
Store a new preference (returns a memory_id for later deletion).
Example content:
- "Prefer snake_case identifiers"
- "Only use tables in the 'analytics' schema"
- "Target dialect: postgres"
"""
mem = user_sql_memory(user_id)
return mem.add(preference_text)
def delete_sql_preference(user_id: str, memory_id: str) -> None:
mem = user_sql_memory(user_id)
mem.delete(memory_id)
# The tool: it fetches the user's preferences and applies them to SQL generation
@fn(instructions="Generate SQL queries; respect any user-specific preferences when present.")
def generate_sql(user_id: str, task: str) -> str:
mem = user_sql_memory(user_id)
prefs_snippet = mem.get_prompt().strip() # textual summary of stored prefs
base_guidance = (
"Return only valid SQL. If preferences are present, conform to them "
"(dialect, naming, schemas, CTE style, etc.)."
)
conditioning = f"{base_guidance}\n\n{prefs_snippet}" if prefs_snippet else base_guidance
# Drive the LLM with Marvin's generate and the recalled memory
return generate(
f"{conditioning}\n\nTask: {task}\n\nOutput: SQL only."
)
Notes and best practices
- Stable keys: Use a deterministic, namespaced key (e.g., user:{user_id}:sql-prefs). This makes it trivial to recall the right memory in any tool or agent.
- Keep preferences concise: Store small, focused facts or a short policy. It makes get_prompt() cleaner and easier for the LLM to apply.
- Structured preferences: If you want programmatic handling, store a single JSON blob as the canonical preference and update it in-place (delete older entries). Then parse that JSON in your tool after get_prompt() extraction. Otherwise, let the LLM consume the plain-text summary.
- Provider choice:
- Default (chroma-ephemeral): great for quick experiments, not persistent across processes.
- PostgresMemory: recommended for persistence and multi-instance use.
- You can also set the default via env (e.g., MARVIN_MEMORY_PROVIDER=postgres) if you don’t want to pass provider= everywhere.
- Auto-use vs. explicit: Use auto_use=False and fetch explicitly in tools if you only want these preferences to affect SQL generation, not all agent turns.
Getting the user id in context
- Easiest and most reliable is to pass user_id as a parameter to the tool (as shown).
- If you already have it in your app/session, you can centralize the memory-construction helper.Marvin
08/27/2025, 9:15 PMmarvin.agents.actor.get_current_actor() or marvin.thread.get_current_thread() and derive a key from available metadata. Passing it explicitly is clearer and test-friendly.
API references and docs
- Memory class: API: marvin.memory
- Concepts: Concepts: Memory
- Patterns: Patterns: Memory usage
- Providers (Postgres, Chroma, etc.):
- PostgresMemory
- ChromaMemory
Would you like an example that maintains a single JSON preference blob per user (and how to update/parse it safely), or is the plain-text preference style sufficient for your use case?