with-inngest
A complete Next.js chat application that demonstrates Recall Core with Inngest for background memory extraction.
Features
Section titled “Features”- Chat interface with OpenAI GPT
- Automatic memory extraction via Inngest functions
- Real-time memory display panel
- SQLite persistence
- AI SDK wrapper for simplified integration
Prerequisites
Section titled “Prerequisites”- Node.js 18+
- pnpm
- OpenAI API key
- Inngest CLI (for local development)
1. Install dependencies
Section titled “1. Install dependencies”cd examples/with-inngestpnpm install2. Configure environment
Section titled “2. Configure environment”cp .env.example .envAdd your OpenAI API key to .env:
OPENAI_API_KEY=sk-proj-your-key-here3. Start the development server
Section titled “3. Start the development server”In one terminal, start the Next.js app:
pnpm devIn another terminal, start the Inngest dev server:
pnpm dev:inngest4. Open the app
Section titled “4. Open the app”Visit http://localhost:3000
Project Structure
Section titled “Project Structure”src/├── app/│ ├── api/│ │ ├── chat/ # Manual memory handling│ │ ├── ai-sdk/ # AI SDK wrapper approach│ │ ├── inngest/ # Inngest webhook endpoint│ │ └── memories/ # List memories endpoint│ └── page.tsx├── components/│ ├── chat-interface.tsx│ └── memories-panel.tsx└── lib/ ├── memory.ts # Recall instance + AI SDK wrapper └── inngest/ ├── client.ts # Inngest client └── functions.ts # Memory extraction functionHow It Works
Section titled “How It Works”Memory Instance
Section titled “Memory Instance”import { createMemory } from '@youcraft/recall'import { createRecall } from '@youcraft/recall-ai-sdk'
export const memory = createMemory({ db: sqliteAdapter({ filename: 'recall.db' }), extractor: openaiExtractor({ apiKey: process.env.OPENAI_API_KEY! }), embeddings: openaiEmbeddings({ apiKey: process.env.OPENAI_API_KEY! }),})
export const recall = createRecall({ memory, onExtract: async ({ messages, userId }) => { await inngest.send({ name: 'chat/message.completed', data: { userId, messages }, }) },})Chat Endpoint
Section titled “Chat Endpoint”The example includes two chat endpoints:
/api/chat — Manual approach with explicit memory handling
/api/ai-sdk — Simplified approach using the recall() wrapper:
import { recall } from '@/lib/memory'
const result = streamText({ model: recall(openai('gpt-5-nano'), { userId: USER_ID }), system: 'You are a helpful assistant.', messages: convertToModelMessages(messages),})Inngest Function
Section titled “Inngest Function”export const extractMemories = inngest.createFunction( { id: 'extract-memories' }, { event: 'chat/message.completed' }, async ({ event, step }) => { const { userId, messages } = event.data
const conversation = await step.run('format-conversation', async () => { return messages.map(m => `${m.role}: ${m.content}`).join('\n') })
const memories = await step.run('extract-memories', async () => { return memory.extract(conversation, { userId }) })
return { memoriesExtracted: memories.length } })