diff --git a/assets/css/index.css b/assets/css/index.css
index 7cd6a3db8a..74e4768b98 100644
--- a/assets/css/index.css
+++ b/assets/css/index.css
@@ -1297,7 +1297,7 @@ a[href*="#no-click"], img[src*="#no-click"] {
}
.suggestion-chips {
- @apply flex flex-wrap gap-2 mt-3;
+ @apply grid grid-cols-2 gap-2 mt-3;
}
.suggestion-chip {
@@ -1368,7 +1368,7 @@ a[href*="#no-click"], img[src*="#no-click"] {
}
.suggestion-chips {
- @apply flex-col space-y-2;
+ @apply grid-cols-1;
}
.suggestion-chip {
diff --git a/content/develop/ai/agent-builder/_index.md b/content/develop/ai/agent-builder/_index.md
index 3239c2fa03..62ba5826fe 100644
--- a/content/develop/ai/agent-builder/_index.md
+++ b/content/develop/ai/agent-builder/_index.md
@@ -30,11 +30,12 @@ Redis powers these capabilities with fast, reliable data storage and retrieval t
## What you can build
-Choose from three types of intelligent agents:
+Choose from four types of intelligent agents:
- **Recommendation engines**: Personalized product and content recommendations
- **Conversational assistants**: Chatbots with memory and context awareness
- **Knowledge assistants**: RAG agents that ingest documents, answer questions with citations, and use semantic caching
+- **Redis Iris conversational assistants**: Conversational agents backed by managed [Redis Iris Agent Memory]({{< relref "/develop/ai/context-engine/agent-memory" >}}) — session and long-term memory with no vector index to build
The agent builder will generate complete, working code examples for your chosen agent type.
diff --git a/content/develop/ai/agent-builder/agent-concepts.md b/content/develop/ai/agent-builder/agent-concepts.md
index 408c54b497..0d0ee83e41 100644
--- a/content/develop/ai/agent-builder/agent-concepts.md
+++ b/content/develop/ai/agent-builder/agent-concepts.md
@@ -79,6 +79,7 @@ Redis is the **ideal foundation** for AI agents because it excels at the three t
- **Short-term**: Conversation context and session state
- **Long-term**: User preferences and learned patterns
- Flexible data structures (Hashes, Lists, Streams, JSON) for different memory types
+- **Managed option**: The [Redis Iris Context Engine]({{< relref "/develop/ai/context-engine/agent-memory" >}}) provides short-term (session) and long-term memory as a managed service — with semantic long-term search — so you don't have to build the vector index and storage yourself
- [Explore Redis data structures →](/develop/data-types/)
## Types of agents you can build
@@ -365,6 +366,7 @@ Ready to build your AI agent with Redis?
- [Redis quick start guide]({{< relref "/develop/get-started" >}}) for setting up Redis
**Learn more:**
+- [Redis Iris Context Engine — Agent Memory]({{< relref "/develop/ai/context-engine/agent-memory" >}}) for managed session and long-term agent memory
- [Redis Vector Search documentation]({{< relref "develop/ai/search-and-query/vectors" >}})
- [RedisVL Python library]({{< relref "develop/clients/redis-vl" >}}) for vector operations and AI workflows
- [Redis data structures guide](/develop/data-types/)
diff --git a/layouts/shortcodes/agent-builder.html b/layouts/shortcodes/agent-builder.html
index 0fd72ee6c6..3518699339 100644
--- a/layouts/shortcodes/agent-builder.html
+++ b/layouts/shortcodes/agent-builder.html
@@ -25,6 +25,7 @@
Build Your AI Agent
+
diff --git a/static/code/agent-templates/javascript/iris_agent.js b/static/code/agent-templates/javascript/iris_agent.js
new file mode 100644
index 0000000000..69ffa9c23b
--- /dev/null
+++ b/static/code/agent-templates/javascript/iris_agent.js
@@ -0,0 +1,202 @@
+/*
+ * Redis Iris Conversational Assistant (Agent Memory)
+ *
+ * A conversational agent whose memory is fully managed by the Redis Iris
+ * Context Engine on Redis Cloud. Instead of building your own vector index,
+ * embeddings, and session store, the agent calls the managed, store-scoped
+ * Agent Memory REST API directly:
+ *
+ * Features:
+ * - Session memory: every user and assistant turn is stored as a session event
+ * - Long-term memory: the service extracts and promotes important facts;
+ * the agent searches them semantically each turn
+ * - Session summaries: older turns are compacted into a summary the agent
+ * folds back into context, so long conversations don't lose their history
+ * - No embeddings, vector index, or Redis schema to manage
+ *
+ * Each turn the agent:
+ * 1. Searches long-term memory for facts relevant to the new message
+ * 2. Loads the session (recent events + compacted summary) for short-term context
+ * 3. Calls the LLM with that memory injected into the system prompt
+ * 4. Writes the user and assistant messages back as session events
+ * (long-term facts are extracted and promoted automatically)
+ *
+ * To run this code:
+ * Install dependencies:
+ * npm install openai dotenv
+ * (Node.js 18+ is required for the built-in fetch used to call the API.)
+ *
+ * Set environment variables (Agent Memory — from the Redis Cloud console):
+ * AGENT_MEMORY_URL=your_agent_memory_base_url
+ * STORE_ID=your_store_id
+ * AGENT_MEMORY_API_KEY=your_agent_memory_api_key
+ *
+ * Set environment variables (LLM):
+ * LLM_API_KEY=your_api_key_here
+ * LLM_API_BASE_URL=your_base_url (optional - default: ${CONFIG.models[formData.llmModel].baseUrl})
+ * LLM_MODEL=your_model (optional - default: ${CONFIG.models[formData.llmModel].defaultModel})
+ *
+ * Note: this template uses the OpenAI SDK with a configurable base URL, so you
+ * can point it at any OpenAI-compatible chat provider. Agent memory is handled
+ * entirely by the managed Agent Memory service — see
+ * https://redis.io/docs/latest/develop/ai/context-engine/agent-memory/
+ *
+ * To create an Agent Memory service and get the values above, follow the
+ * Redis Cloud Agent Memory quickstart in the documentation.
+ *
+ * Run:
+ * node iris_agent.js
+ */
+
+'use strict';
+
+require('dotenv').config();
+const OpenAI = require('openai');
+const readline = require('readline');
+const crypto = require('crypto');
+
+// How many long-term memories to inject as relevant background each turn.
+const MAX_LONG_TERM_RESULTS = 5;
+// How many recent session events to load for short-term context each turn.
+const MAX_SESSION_EVENTS = 12;
+
+class ${AgentClassName} {
+ constructor(sessionId, actorId = 'user') {
+ // Managed Agent Memory service (Redis Cloud). The service owns the
+ // vector index, embeddings, and storage; we call its store-scoped
+ // REST API directly with fetch.
+ this.baseUrl = (process.env.AGENT_MEMORY_URL || '').replace(/\/$/, '');
+ this.storeId = process.env.STORE_ID;
+ this.apiKey = process.env.AGENT_MEMORY_API_KEY;
+
+ // Chat LLM. Uses the OpenAI SDK with a configurable base URL so any
+ // OpenAI-compatible provider works.
+ this.llm = new OpenAI({
+ apiKey: process.env.LLM_API_KEY,
+ baseURL: process.env.LLM_API_BASE_URL || '${CONFIG.models[formData.llmModel].baseUrl}',
+ });
+ this.model = process.env.LLM_MODEL || '${CONFIG.models[formData.llmModel].defaultModel}';
+
+ // A session groups the events of one conversation. Long-term memory is
+ // shared across all of a user's sessions.
+ this.sessionId = sessionId || `session-${crypto.randomBytes(6).toString('hex')}`;
+ this.actorId = actorId;
+ }
+
+ // Call the store-scoped Agent Memory API. Returns parsed JSON, or null on
+ // 404 (e.g. a session that doesn't exist yet).
+ async memoryRequest(method, path, body) {
+ const res = await fetch(`${this.baseUrl}/v1/stores/${this.storeId}${path}`, {
+ method,
+ headers: {
+ Authorization: `Bearer ${this.apiKey}`,
+ 'Content-Type': 'application/json',
+ },
+ body: body ? JSON.stringify(body) : undefined,
+ });
+ if (res.status === 404) return null;
+ if (!res.ok) {
+ throw new Error(`Agent Memory ${method} ${path} -> ${res.status}: ${await res.text()}`);
+ }
+ return res.json();
+ }
+
+ // Semantic search over long-term memory for facts relevant to the query.
+ async relevantMemories(query) {
+ try {
+ const results = await this.memoryRequest('POST', '/long-term-memory/search', { text: query });
+ const items = (results && results.items) || [];
+ return items.slice(0, MAX_LONG_TERM_RESULTS).map(item => item.text);
+ } catch (err) {
+ console.error(`[memory] long-term search unavailable: ${err.message}`);
+ return [];
+ }
+ }
+
+ // Load the session: recent events for short-term context, plus the
+ // compacted summary of older turns the service has already summarized.
+ async loadSession() {
+ try {
+ const session = await this.memoryRequest('GET', `/session-memory/${this.sessionId}`);
+ if (!session) return { turns: [], summary: '' };
+ const events = (session.events || []).slice(-MAX_SESSION_EVENTS);
+ const turns = events.map(event => ({
+ role: String(event.role).toUpperCase() === 'ASSISTANT' ? 'assistant' : 'user',
+ content: (event.content || []).map(part => part.text || '').join(' '),
+ }));
+ return { turns, summary: (session.summary && session.summary.text) || '' };
+ } catch (err) {
+ console.error(`[memory] session load unavailable: ${err.message}`);
+ return { turns: [], summary: '' };
+ }
+ }
+
+ // Persist one turn as a session event. Long-term promotion is automatic.
+ async recordEvent(role, text) {
+ await this.memoryRequest('POST', '/session-memory/events', {
+ sessionId: this.sessionId,
+ actorId: this.actorId,
+ role,
+ content: [{ text }],
+ createdAt: new Date().toISOString(),
+ });
+ }
+
+ async ask(userInput) {
+ // 1. Relevant long-term facts and 2. this session's recent turns + summary.
+ const facts = await this.relevantMemories(userInput);
+ const { turns, summary } = await this.loadSession();
+
+ let systemPrompt =
+ 'You are a helpful assistant with persistent memory. ' +
+ 'Use the following remembered facts about the user when relevant. ' +
+ 'If nothing is relevant, answer normally.\n\n' +
+ (facts.length
+ ? 'Relevant memories:\n' + facts.map(f => `- ${f}`).join('\n')
+ : 'Relevant memories: (none yet)');
+ if (summary) {
+ systemPrompt += `\n\nSummary of earlier conversation:\n${summary}`;
+ }
+
+ const messages = [
+ { role: 'system', content: systemPrompt },
+ ...turns,
+ { role: 'user', content: userInput },
+ ];
+
+ // 3. Call the LLM.
+ const response = await this.llm.chat.completions.create({ model: this.model, messages });
+ const answer = response.choices[0].message.content;
+
+ // 4. Write both turns back as session events.
+ await this.recordEvent('USER', userInput);
+ await this.recordEvent('ASSISTANT', answer);
+
+ return answer;
+ }
+}
+
+async function main() {
+ const agent = new ${AgentClassName}();
+ console.log('Redis Iris Conversational Assistant — type "exit" to quit.');
+ console.log(`Session: ${agent.sessionId}\n`);
+
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
+ const prompt = () => new Promise(resolve => rl.question('You: ', resolve));
+
+ for (;;) {
+ const userInput = (await prompt()).trim();
+ if (!userInput || ['exit', 'quit'].includes(userInput.toLowerCase())) break;
+ console.log(`Agent: ${await agent.ask(userInput)}\n`);
+ }
+ rl.close();
+}
+
+if (require.main === module) {
+ main().catch(err => {
+ console.error('Fatal error:', err);
+ process.exit(1);
+ });
+}
+
+module.exports = ${AgentClassName};
diff --git a/static/code/agent-templates/python/iris_agent.py b/static/code/agent-templates/python/iris_agent.py
new file mode 100644
index 0000000000..93034323c6
--- /dev/null
+++ b/static/code/agent-templates/python/iris_agent.py
@@ -0,0 +1,181 @@
+'''
+Redis Iris Conversational Assistant (Agent Memory)
+
+A conversational agent whose memory is fully managed by the Redis Iris
+Context Engine. Instead of building your own vector index, embeddings, and
+session store, the agent calls the managed Agent Memory service:
+
+Features:
+- Session memory: every user and assistant turn is stored as a session event
+- Long-term memory: the service automatically promotes important facts from
+ session events; the agent searches them semantically each turn
+- Cross-session recall: relevant facts follow the user across conversations
+- No embeddings, vector index, or Redis schema to manage — the service does it
+
+Each turn the agent:
+ 1. Searches long-term memory for facts relevant to the new message
+ 2. Loads recent session events for short-term conversational context
+ 3. Calls the LLM with that memory injected into the system prompt
+ 4. Writes the user and assistant messages back as session events
+ (long-term facts are extracted and promoted automatically)
+
+To run this code:
+ Install dependencies:
+ pip install redis-agent-memory openai
+
+ Set environment variables (Agent Memory — from the Redis Cloud console):
+ export AGENT_MEMORY_URL=your_agent_memory_base_url
+ export STORE_ID=your_store_id
+ export AGENT_MEMORY_API_KEY=your_agent_memory_api_key
+
+ Set environment variables (LLM):
+ export LLM_API_KEY=your_api_key_here
+ export LLM_API_BASE_URL=your_${formData.llmModel.toLowerCase()}_api_base_url
+ (optional - default: ${CONFIG.models[formData.llmModel].baseUrl})
+ export LLM_MODEL=your_${formData.llmModel.toLowerCase()}_model
+ (optional - default: ${CONFIG.models[formData.llmModel].defaultModel})
+
+ Note: this template uses the OpenAI SDK with a configurable base URL, so you
+ can point it at any OpenAI-compatible chat provider. Agent memory is handled
+ entirely by the managed Agent Memory service — see
+ https://redis.io/docs/latest/develop/ai/context-engine/agent-memory/
+
+ To create an Agent Memory service and get the values above, follow the
+ Redis Cloud Agent Memory quickstart in the documentation.
+'''
+
+import os
+import uuid
+from datetime import datetime, timezone
+
+import openai
+from redis_agent_memory import AgentMemory, models
+
+# How many recent session events to load for short-term context each turn.
+MAX_SESSION_EVENTS = 12
+# How many long-term memories to inject as relevant background each turn.
+MAX_LONG_TERM_RESULTS = 5
+
+
+class ${AgentClassName}:
+ def __init__(self, session_id=None, actor_id='user'):
+ # Managed Agent Memory client. The service owns the vector index,
+ # embeddings, and storage — this client just talks to its REST API.
+ self.memory = AgentMemory(
+ os.environ['AGENT_MEMORY_URL'],
+ store_id=os.environ['STORE_ID'],
+ api_key=os.environ['AGENT_MEMORY_API_KEY'],
+ )
+
+ # Chat LLM. Uses the OpenAI SDK with a configurable base URL so any
+ # OpenAI-compatible provider works.
+ self.llm = openai.OpenAI(
+ api_key=os.environ['LLM_API_KEY'],
+ base_url=os.getenv('LLM_API_BASE_URL', '${CONFIG.models[formData.llmModel].baseUrl}'),
+ )
+ self.model = os.getenv('LLM_MODEL', '${CONFIG.models[formData.llmModel].defaultModel}')
+
+ # A session groups the events of one conversation. Reuse the same
+ # session_id to continue a conversation; long-term memory is shared
+ # across all of a user's sessions.
+ self.session_id = session_id or f'session-{uuid.uuid4().hex[:12]}'
+ self.actor_id = actor_id
+
+ def _relevant_memories(self, query):
+ '''Semantic search over long-term memory for facts relevant to the query.'''
+ try:
+ results = self.memory.search_long_term_memory(request={'text': query})
+ except Exception as e:
+ print(f'[memory] long-term search unavailable: {e}')
+ return []
+
+ # Matching records come back in `.items`; each record exposes its `.text`.
+ items = getattr(results, 'items', []) or []
+ return [item.text for item in items[:MAX_LONG_TERM_RESULTS]]
+
+ def _load_session(self):
+ '''Load the session: recent events for short-term context, plus the
+ compacted summary of older turns the service has already summarized.'''
+ try:
+ session = self.memory.get_session_memory(session_id=self.session_id)
+ except Exception:
+ return [], ''
+
+ events = getattr(session, 'events', []) or []
+ turns = []
+ for event in events[-MAX_SESSION_EVENTS:]:
+ role = getattr(event, 'role', 'USER')
+ content = getattr(event, 'content', []) or []
+ # Content parts are Content model objects (or dicts); read either.
+ text = ' '.join(
+ getattr(part, 'text', None) or (part.get('text', '') if isinstance(part, dict) else '')
+ for part in content
+ )
+ turns.append({
+ 'role': 'assistant' if str(role).upper().endswith('ASSISTANT') else 'user',
+ 'content': text,
+ })
+
+ # After summarization, older events are dropped from `events` and the
+ # compacted history is returned separately in `summary`.
+ summary_obj = getattr(session, 'summary', None)
+ summary = getattr(summary_obj, 'text', '') if summary_obj else ''
+ return turns, summary
+
+ def _record(self, role, text):
+ '''Persist one turn as a session event. Long-term promotion is automatic.'''
+ self.memory.add_session_event(
+ actor_id=self.actor_id,
+ role=role,
+ content=[{'text': text}],
+ created_at=datetime.now(timezone.utc),
+ session_id=self.session_id,
+ )
+
+ def ask(self, user_input):
+ # 1. Pull relevant long-term facts and 2. this session's recent turns + summary.
+ facts = self._relevant_memories(user_input)
+ recent, summary = self._load_session()
+
+ system_prompt = (
+ 'You are a helpful assistant with persistent memory. '
+ 'Use the following remembered facts about the user when relevant. '
+ 'If nothing is relevant, answer normally.\n\n'
+ + ('Relevant memories:\n' + '\n'.join(f'- {f}' for f in facts)
+ if facts else 'Relevant memories: (none yet)')
+ )
+ if summary:
+ system_prompt += f'\n\nSummary of earlier conversation:\n{summary}'
+
+ messages = [{'role': 'system', 'content': system_prompt}]
+ messages.extend(recent)
+ messages.append({'role': 'user', 'content': user_input})
+
+ # 3. Call the LLM.
+ response = self.llm.chat.completions.create(model=self.model, messages=messages)
+ answer = response.choices[0].message.content
+
+ # 4. Write both turns back to session memory.
+ self._record(models.MessageRole.USER, user_input)
+ self._record(models.MessageRole.ASSISTANT, answer)
+
+ return answer
+
+
+def main():
+ agent = ${AgentClassName}()
+ print('Redis Iris Conversational Assistant — type "exit" to quit.')
+ print(f'Session: {agent.session_id}\n')
+ while True:
+ try:
+ user_input = input('You: ').strip()
+ except (EOFError, KeyboardInterrupt):
+ print()
+ break
+ if not user_input or user_input.lower() in ('exit', 'quit'):
+ break
+ print(f'Agent: {agent.ask(user_input)}\n')
+
+
+if __name__ == '__main__':
+ main()
diff --git a/static/js/agent-builder.js b/static/js/agent-builder.js
index 36a326c341..4676ab40ab 100644
--- a/static/js/agent-builder.js
+++ b/static/js/agent-builder.js
@@ -26,6 +26,12 @@
description: "A RAG agent that ingests documents, uses Redis-native hybrid retrieval (text pre-filter + vector search), semantic caching, and session memory to answer questions with citations.",
features: ["Document ingestion with chunking", "Hybrid vector + full-text search", "Semantic caching", "Citations"],
keywords: ["rag", "knowledge", "documents", "search", "retrieval", "qa", "question answering", "citations", "hybrid"]
+ },
+ iris: {
+ name: "Redis Iris Conversational Assistant",
+ description: "A conversational assistant whose memory is managed by Redis Iris Agent Memory. It stores session events and semantically searches long-term memory through the managed service — no vector index or embeddings to build.",
+ features: ["Managed Agent Memory service", "Session (short-term) memory", "Semantic long-term memory search", "Cross-session recall"],
+ keywords: ["iris", "context engine", "agent memory"]
}
},
languages: {
@@ -293,7 +299,7 @@
switch (conversationState.step) {
case 'agent-type': {
- const agentIcons = { recommendation: '🛍️', conversational: '💬', rag: '🔍' };
+ const agentIcons = { recommendation: '🛍️', conversational: '💬', rag: '🔍', iris: '🧠' };
suggestions = Object.entries(CONFIG.agentTypes).map(([key, config]) => ({
value: key,
label: config.name,
@@ -400,7 +406,8 @@
const defaultNames = {
recommendation: 'RecommendationEngine',
conversational: 'ConversationalAgent',
- rag: 'KnowledgeAssistant'
+ rag: 'KnowledgeAssistant',
+ iris: 'IrisConversationalAssistant'
};
conversationState.selections.agentName = defaultNames[selectedType] || 'RedisAgent';
@@ -418,7 +425,8 @@
addMessage("I didn't understand that. Please choose one of the agent types:", 'bot', [
{ value: 'recommendation', label: '🛍️ Recommendation Engine' },
{ value: 'conversational', label: '💬 Conversational Assistant' },
- { value: 'rag', label: '🔍 Knowledge Assistant' }
+ { value: 'rag', label: '🔍 Knowledge Assistant' },
+ { value: 'iris', label: '🧠 Redis Iris Conversational Assistant' }
]);
}
}