Skip to content

with-inngest

A complete Next.js chat application that demonstrates Recall Core with Inngest for background memory extraction.

  • Chat interface with OpenAI GPT
  • Automatic memory extraction via Inngest functions
  • Real-time memory display panel
  • SQLite persistence
  • AI SDK wrapper for simplified integration
  • Node.js 18+
  • pnpm
  • OpenAI API key
  • Inngest CLI (for local development)
Terminal window
cd examples/with-inngest
pnpm install
Terminal window
cp .env.example .env

Add your OpenAI API key to .env:

OPENAI_API_KEY=sk-proj-your-key-here

In one terminal, start the Next.js app:

Terminal window
pnpm dev

In another terminal, start the Inngest dev server:

Terminal window
pnpm dev:inngest

Visit http://localhost:3000

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 function
src/lib/memory.ts
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 },
})
},
})

The example includes two chat endpoints:

/api/chat — Manual approach with explicit memory handling

/api/ai-sdk — Simplified approach using the recall() wrapper:

src/app/api/ai-sdk/route.ts
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),
})
src/lib/inngest/functions.ts
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 }
}
)