Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions assets/css/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand Down
3 changes: 2 additions & 1 deletion content/develop/ai/agent-builder/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
2 changes: 2 additions & 0 deletions content/develop/ai/agent-builder/agent-concepts.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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/)
Expand Down
1 change: 1 addition & 0 deletions layouts/shortcodes/agent-builder.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ <h3 class="text-2xl font-semibold text-redis-ink-900 mb-2">Build Your AI Agent</
<button class="suggestion-chip" data-suggestion="recommendation">🛍️ Recommendation Engine</button>
<button class="suggestion-chip" data-suggestion="conversational">💬 Conversational Assistant</button>
<button class="suggestion-chip" data-suggestion="rag">🔍 Knowledge Assistant</button>
<button class="suggestion-chip" data-suggestion="iris">🧠 Redis Iris Conversational Assistant</button>
</div>
</div>
</div>
Expand Down
202 changes: 202 additions & 0 deletions static/code/agent-templates/javascript/iris_agent.js
Original file line number Diff line number Diff line change
@@ -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};
Loading
Loading