Configure the Automatic Memory Wrapper Agent#
Configure the NVIDIA NeMo Agent Toolkit automatic memory wrapper agent as a workflow or a function.
Requirements#
The automatic memory wrapper agent works with any memory backend that implements the MemoryEditor interface. The following memory plugins are available:
nvidia-nat-zep-cloud- Zep Cloud memory backend (Zep NVIDIA NeMo documentation)nvidia-nat-mem0ai- Mem0 memory backendnvidia-nat-memmachine- MemMachine memory backend (Experimental; not recommended for production use) (MemMachine documentation)nemo-agent-toolkit-redis- Redis memory backend
Configuration#
The automatic memory wrapper agent may be utilized as a workflow or a function.
Example 1: Automatic Memory Wrapper Agent as a Workflow#
To use the automatic memory wrapper agent as a workflow:
memory:
zep_memory:
_type: nat.plugins.zep_cloud/zep_memory
functions:
my_react_agent:
_type: react_agent
llm_name: nim_llm
tool_names: [calculator]
workflow:
_type: auto_memory_agent
inner_agent_name: my_react_agent
memory_name: zep_memory
llm_name: nim_llm
Example 2: Automatic Memory Wrapper Agent as a Function#
To use the automatic memory wrapper agent as a function:
memory:
zep_memory:
_type: nat.plugins.zep_cloud/zep_memory
functions:
my_agent_with_memory:
_type: auto_memory_agent
inner_agent_name: my_react_agent
memory_name: zep_memory
llm_name: nim_llm
description: 'A ReAct agent with automatic memory'
Configurable Options#
Required Parameters:
Parameter |
Description |
|---|---|
|
Name of the agent to wrap with automatic memory |
|
Name of the memory backend (from |
|
LLM to use (required by |
Optional Feature Flags (all default to true):
Parameter |
Default |
Description |
|---|---|---|
|
|
Automatically save user messages before agent processing |
|
|
Automatically retrieve and inject memory context |
|
|
Automatically save agent responses after generation |
Memory Backend Parameters:
search_params: Passed tomemory_editor.search()for memory retrieval configurationsearch_params: mode: "summary" # Zep: "basic" or "summary" top_k: 10 # Maximum memories to retrieve
add_params: Passed tomemory_editor.add_items()for memory storage configurationadd_params: ignore_roles: ["assistant"] # Zep: Exclude roles from graph memory
Other Options:
description: Defaults to"Auto Memory Agent Wrapper". When configured as a function, this allows control over the tool description.verbose: Defaults toFalse(useful to prevent logging of sensitive data). If set toTrue, the wrapper will log memory operations and intermediate steps.
How the Automatic Memory Wrapper Agent Works#
The automatic memory wrapper agent intercepts agent invocations and automatically handles memory operations:
Step-by-Step Execution Flow#
User Message Reception – The wrapper receives the user’s input message
Memory Retrieval (if
retrieve_memory_for_every_responseistrue)Searches the memory backend for relevant context
Injects retrieved memories into the agent’s context
User Message Storage (if
save_user_messages_to_memoryistrue)Stores the user’s message in the memory backend
Agent Invocation – The wrapped agent processes the request with memory context
Response Storage (if
save_ai_messages_to_memoryistrue)Stores the agent’s response in the memory backend
Response Return – Returns the agent’s response to the user
Example Walkthrough#
Consider a conversation with automatic memory enabled:
First Interaction:
User: "My name is Alice and I prefer Python for data analysis."
Agent: "Nice to meet you, Alice! I'll remember your preference for Python."
The wrapper automatically:
Stores the user message
Invokes the inner agent
Stores the agent response
Later Interaction:
User: "What programming language should I use for my data project?"
Agent: "Based on what you told me earlier, I recommend Python for your data analysis project since that's your preferred language."
The wrapper automatically:
Retrieves relevant memories (Alice’s name and Python preference)
Injects them into the agent’s context
Agent can reference past conversations naturally
Multi-Tenant Memory Isolation#
The automatic memory wrapper agent provides multi-tenant support through runtime user ID extraction. Configure user IDs
through the front end or session runtime, not the auto_memory_agent workflow block.
User ID Resolution#
The wrapper reads only the user ID resolved by the runtime session. It does not read request headers directly and does not use a shared fallback identity. If a memory operation is enabled and the runtime has not resolved an identity, the request fails instead of sharing memory across unauthenticated users.
Resolve identity with authenticated front-end credentials, SessionManager.session(user_id=...), or the console front
end user_id (which defaults to "nat_run_user_id" for nat run).
Conversation-aware memory backends can also use conversation_id to isolate separate conversations for the same user.
For Zep Cloud, if no conversation ID is supplied, the integration uses a deterministic per-user default thread.
Production: Custom Middleware#
Create middleware that extracts user ID from your authentication system:
from nat.runtime.session import SessionManager
class AuthenticatedUserManager:
def __init__(self, user_id: str):
self._user_id = user_id
def get_id(self) -> str:
return self._user_id
# In your request handler
async def handle_request(request):
# Extract from JWT, OAuth, API key, etc.
user_id = extract_user_from_jwt(request.headers["authorization"])
async with session_manager.session(user_id=user_id, http_connection=request) as session:
result = await session.run(user_input)
return result
Local Testing or a Trusted Upstream Identity Header#
The FastAPI front end can explicitly trust one upstream identity header:
general:
front_end:
_type: fastapi
identity_header: X-User-ID
Use this setting only for local testing or behind an authenticating reverse proxy. It is secure only when all of the following are true:
Clients cannot connect to
nat servedirectly; only the trusted proxy can reach its listening port.The proxy authenticates every request and overwrites
X-User-IDwith the authenticated principal. It must not preserve, append, or forward a client-supplied value.nat serveis network isolated in such a way that all incoming network traffic is from the proxy.
When configured, the header is authoritative for HTTP and WebSocket requests. A missing, empty, or repeated header is rejected. Other connection credentials and WebSocket auth messages cannot replace it. The setting cannot be combined
with accepted_identity_credentials or identity_authentication.
For local testing, this can be simulated with:
curl -X POST http://localhost:8000/chat \
-H "Content-Type: application/json" \
-H "X-User-ID: test_user_123" \
-H "conversation-id: test_conv_001" \
-d '{"messages": [{"role": "user", "content": "Hello!"}]}'
Local Development: Console User and Conversation IDs#
For nat run, set --user_id to control memory isolation and --conversation_id to isolate a specific conversation:
nat run --config_file examples/agents/auto_memory_wrapper/configs/config_zep.yml \
--user_id test_user_123 \
--conversation_id test_conv_001
Advanced Configuration Example#
Here’s a comprehensive configuration showing all available options:
memory:
zep_memory:
_type: nat.plugins.zep_cloud/zep_memory
llms:
nim_llm:
_type: nim
model_name: nvidia/nemotron-3-super-120b-a12b
temperature: 0.7
function_groups:
calculator:
_type: calculator
functions:
my_react_agent:
_type: react_agent
llm_name: nim_llm
tool_names: [calculator]
verbose: true
workflow:
_type: auto_memory_agent
inner_agent_name: my_react_agent
memory_name: zep_memory
llm_name: nim_llm
verbose: true
description: "A ReAct agent with automatic Zep memory"
# Feature flags (optional - all default to true)
save_user_messages_to_memory: true
retrieve_memory_for_every_response: true
save_ai_messages_to_memory: true
# Memory retrieval configuration (optional)
search_params:
mode: "summary" # Zep: "basic" (fast) or "summary" (comprehensive)
top_k: 5 # Maximum number of memories to retrieve
# Memory storage configuration (optional)
add_params:
ignore_roles: ["assistant"] # Zep: Exclude assistant messages from graph
Wrapping Different Agent Types#
The automatic memory wrapper works with any agent type:
Wrapping a ReAct Agent#
functions:
my_react_agent:
_type: react_agent
llm_name: nim_llm
tool_names: [calculator]
workflow:
_type: auto_memory_agent
inner_agent_name: my_react_agent
memory_name: zep_memory
llm_name: nim_llm
Wrapping a ReWOO Agent#
functions:
my_rewoo_agent:
_type: rewoo_agent
llm_name: nim_llm
tool_names: [wikipedia_search, calculator]
workflow:
_type: auto_memory_agent
inner_agent_name: my_rewoo_agent
memory_name: zep_memory
llm_name: nim_llm
Wrapping a Tool Calling Agent#
functions:
my_tool_calling_agent:
_type: tool_calling_agent
llm_name: nim_llm
tool_names: [weather_tool, calculator]
workflow:
_type: auto_memory_agent
inner_agent_name: my_tool_calling_agent
memory_name: zep_memory
llm_name: nim_llm
Important Notes#
User ID is runtime/front-end scoped - Set through authenticated front-end identity resolution,
SessionManager.session(user_id=...), an explicitly configured trustedidentity_header, ornat run --user_id. Memory operations fail when no identity is available.Memory backends are interchangeable - Works with any implementation of
MemoryEditorinterfaceNo memory tools needed - The wrapped agent does not need explicit memory tools configured
Transparent to inner agent - The wrapped agent is unaware of memory operations
Trusted identity headers are opt-in - Never enable
identity_headeron a server that untrusted clients can reach directly.
Examples#
For complete working examples, refer to:
examples/agents/auto_memory_wrapper- Full example with Zep Cloud integrationexamples/memory/memmachine- MemMachine server setup and example notebook
For additional information on memory backends and configuration, see: