Timeline
16,716 memories — chronological, newest first.
Speaker 1: ...docs that has cloud blobs.
Speaker 2: Oh yeah.
Speaker 1: Yeah.
Speaker 2: Yeah, that's it.
May 14, 05:24 PM
[Web Browser Content]
Create Space | Byterover
Performance Optimization
- batching-io-optimization.md
- Resource Management
- Cache results of repeated system calls
Olvia Ryde updated "Add new config in batches"
Summary
Batching small I/O operations into asynchronous groups minimizes the number of context switches.
Technical Rationale
- Each I/O call (disk or network) introduces blocking latency.
- Small, frequent I/O requests can be coalesced into larger groups.
- Use frameworks like asyncio.gather() or Promise.all().
- Ideal batch size: 10-20 requests per async group.
Benchmark result
- Sequential: 220ms avg latency / 10 requests
- Async batch: 95ms avg latency / 10 requests
- CPU usage: 47% -> 62% (optimized thread utilization)
May 14, 05:24 PM
Speaker 1: Ranker, Ranker, Ranker.
Speaker 1: There's another one besides RankerX. Staxio? Staxio? Whatever. I forget the name of that thing.
Speaker 2: Yeah, Staxio or GSA? That has Cloudflare?
Speaker 1: Yeah, that's it.
May 14, 05:24 PM
Speaker 1: Staxio?
Speaker 2: RankerX?
Speaker 1: RankerX, yeah, that's one of them. Is that in there?
Speaker 2: No, we don't have... we have GeoRanker and AccuRanker.
Speaker 1: Oh. And there's another one besides RankerX. Staxio? Stakio? Whatever. I forget the name of it, damn.
Speaker 2: Yeah, Staxio or...
May 14, 05:24 PM
[Web Browser Content]
Byterover Console
app.byterover.dev/settings/merlino/plan?checkout=success
Supermemory Console
BYTEROVER
Loading
Ask Gemini
May 14, 05:24 PM
[Web Browser Content]
BYTE-ROVER Pro Subscription
Plan: Pro
Billed monthly: $19.00
Total due today: $19.00
Payment Information:
Cardholder: Michael Merlino
Billing Address: 4650 Country Manor Drive, Sarasota, Florida, 34233, United States
Email: quotes@abreumovers.com
Status: Your card has been declined.
Powered by Stripe.
May 14, 05:24 PM
Speaker 1: What's the name of that other tool that people use if they're not using ours? I forget the name, I've never used it, but people still talk about it.
Speaker 2: RankerX? SEnuke?
Speaker 1: RankerX, yeah, that's the one. Is that in there?
May 14, 05:23 PM
Speaker 1: He goes and tells me as a SaaS company that he's going to dump it sooner or later. What's the name of that other tool that, um, people use if they're not using ours? I forget the name because I've never used it, but people still talk about it.
Speaker 2: RankerX?
May 14, 05:23 PM
Speaker 1: Yeah, I have three licenses. I have three licenses I have.
Speaker 2: I got the UberSuggest with $480 lifetime.
Speaker 1: Yeah, I have it. But, you know, I don't like these kind of deals because it tells me as a SaaS company that it's going to dump it.
May 14, 05:23 PM
Speaker 1: 90% off, 90% offer on the lifetime deal.
Speaker 2: Yeah, I have three licenses I have.
Speaker 1: You can get UberSuggest with $480 lifetime.
Speaker 2: Yep, I have it.
Speaker 1: But you know, I don't like these kind of deals because...
May 14, 05:23 PM
Screen: bash
x
bash
x
bash
x
bash
x
bash
o
x
3 benchmarks available:
- locomo —
Long Context Memory (fact recall, temporal, multi-hop, abstention)
- longmemeval
— single + multi-session, temporal, knowledge update
— user [assistant facts, preferences, implicit connections
- convomem
3 providers supported: supermemory, mem0, zep
Quick start:
cd D:\ClaudeDev\00_GITHUB\memorybench
bun run src/index.ts run -p supermemory -b convomem -s 3
--sample-type random
The -s 3
--sample-type random keeps the first run small (3 questions per category) so you don't burn credits
exploring.
To compare against Mem@ (which you already use):
1. Add MEMO_API_KEY to .env. local (it's in your master env)
2. Add OPENAI_API_KEY if using gpt-40 as judge
3. bun run src/index.ts compare -p supermemory,mem@ -b convomem -j gpt-4
May 14, 05:23 PM
One is more broad and the other one is maybe more narrowed down.
Ubersuggest, Ubersuggest is dying. Neil Patel had a 90% offer. He is selling it off, 90% offer on the lifetime.
May 14, 05:23 PM
Maybe it's a good split. The first one is more broad and the other one is maybe more narrowed down.
Ubersuggest. Ubersuggest is dying. Neil Patel had a 90% offer. He's selling...
May 14, 05:23 PM
Screen: OneTab
X O BYTE-ROVER
Supermemory Console
Supermemory Console
Ask Gemini
2; checkout.stripe.com/c/pay/cs_live_b1zLiXIVNZylc3prfwHxsZ5TgXpuFLMtUzd2ZzjrHlRRP7tZAnYVwr3fUY#fidnandhYHdWcXxpYCc%2FJ2FgY2RwaXEnKSd2cGd2ZndsdXFsamtQ...
Work
You also agree to the Link and .?.r.i.y.agy..P.QJ.i.qy..
By subscribing, you authorize BYTEROVER to charge you
according to the terms until you cancel.
Subscribe
I agree to BYTEROVER's .Terms..Q.f..S.ery.ice and P.r.i.y.acy.
.?.Q.l.i.gy
KUDOS
Wallet
Card-Linked Offers
O Best card to use
Not a Boost store
o
Partner Stores >
The American Express Blue
Business CashTM Card ••••
1005
Total rewards
Card rewards O
Card rewards
2% Back
2% Back
2% Cashback
Reward and card details
Chase Sapphire Reserve@
4654
Total rewards
Card rewards O
Reward and card details
lx Points
May 14, 05:23 PM
Do you think we should go with Ahrefs instead of link building? Or not all in, I mean, 5,000 to link building audience and 5,000 to Ahrefs audience?
May 14, 05:22 PM
Speaker 1: Do you think we should go with Ahrefs instead of Link Building? Or not all in, I mean 5,000 to Link Building audience and 5,000 to Ahrefs audience?
Speaker 2: Maybe it's a good split, the first one.
May 14, 05:22 PM
Competitor tool tools the segment
May 14, 05:22 PM
Screen: < Settings
Account
o
Profile
d API Keys
Team: (M) Merlino v
General
Billing & Usage
+ Plan
Plan
Pricing
Upgrade, downgrade or cancel anytime
Pro
For individual power users
$19
per month
Upgrade to Pro
4,500 credits / month
1 user • no team invites
500 MB storage
Cloud Sync
Context Management
48-hr Email SLA
Premium community access
Free
Local-first, forever free
MOST POPULAR
Team
For collaborative teams
$35
per user / month
Upgrade to Team
4,500 credits / user / month
5 GiB storage
Cloud Sync
Context Management
Team Management
24-hr Email SLA
Priority agent access
Premium community access
Full CLI access
Markdown-backed context store
100% local — no cloud, no accounts
Bring Your Own Key
Monthly
00
Enterprise
Yearly
OFF
Custom scale, total control
Custom
Contact Us
Custom model allocation
C
May 14, 05:22 PM
Speaker 1: What about Semrush? I'm super curious now that they have sold for 1.5 billion. It's less than Ahrefs.
Speaker 2: But trending up.
Speaker 1: Yeah. Trending up and it is 98% relevance too.
May 14, 05:22 PM
Speaker 1: It's almost half a million.
Speaker 2: Hmm.
Speaker 1: What about Semrush? I'm super curious now that they have sold for 1.5 billion. It's less than 8x.
Speaker 2: They're trending up.
Speaker 1: Yeah, trending up. It is 98...
May 14, 05:22 PM
[Web Browser Content]
Create Team | Byterover
[Navigation]
Discord Community | Engineering-team Pro | IC Design | Talk with Founder | BETA | Docs | Memory | Resources | Search...
[Performance Optimization]
File: batching-io-optimization.md
Author: Olvia Ryde (updated "Add new config in batches")
Summary: Batching small I/O operations into asynchronous groups minimizes context switches.
Technical Rationale:
- Each I/O call (disk or network) introduces blocking latency.
- Small, frequent I/O requests can be coalesced.
- Use frameworks like asyncio.gather() or Promise.all().
- Ideal batch size: 10-20 requests per async group.
Benchmark result:
- Sequential: 220ms avg latency / 10 requests
- Async batch: 95ms avg latency / 10 requests
- CPU usage: 47% -> 62% (optimized thread utilization)
[Team Creation]
Team Name: my-team
URL: https://byterover.dev/
[Error Message]
Access Denied: You don't have permission to create additional teams.
May 14, 05:21 PM
Speaker 1: ...the past seven days. Relevance 98%.
Speaker 2: Mhm. And this issue included that there was a 40 down percent in the trend.
Speaker 1: Yeah.
Speaker 2: Yeah, it's a big... mhm.
Speaker 1: It was almost half a million.
Speaker 2: Mhm.
May 14, 05:21 PM
[Web Browser Content]
Onboarding | Byterover
How would you like to work? Choose the version that fits your workflow:
Local (Free Forever)
- 100% Offline-first & Private
- Access all tools (BYO keys)
- Manual data management
Cloud (Paid)
- Auto-sync across all devices
- 3,000 req/mo (Powered by Gemini)
- Automated remote backups
[Engineering-team Pro] [IC Design]
Performance Optimization / batching-io-optimization.md
Olvia Ryde updated "Add new config in batches"
Summary: Batching small I/O operations into asynchronous groups minimizes context switches.
Technical Rationale:
- Each I/O call (disk or network) introduces blocking.
- Small, frequent I/O requests can be coalesced.
- Use frameworks like asyncio.gather() or Promise.all().
- Ideal batch size: 10-20 requests per async group.
Benchmark result:
- Sequential: 220ms avg latency / 10 requests
- Async batch: 95ms avg latency / 10 requests
- CPU usage: 47% -> 62% (optimized thread utilization)
May 14, 05:21 PM
Speaker 1: 37... 170,000 the past seven days. Relevant 98%.
Speaker 2: And he included that there was a 40% trend.
Speaker 1: Yeah, it's a big... it's a big...
May 14, 05:21 PM
Screen: Talk with Founder
May 14, 05:21 PM
[Web Browser Content]
Discord Community
Team Not Found
You don't have access to this team or it doesn't exist.
Go to Home
Talk with Founder
Google Docs
BYTEROVER
app.byterover.dev/auth/sign-in
May 14, 05:21 PM
[Web Browser Content]
Sign in | Byterover
BYTEROVER
Sign in with Google
Sign in with Github
Email: you@company.com
Password: [Password Field]
Don't have an account? Create One.
Forgot password?
Context-Awareness: Auto
Ai Agent: # Memory
/ query Find relevant context and summarize the key points
By continuing, you agree to our Terms and Conditions, Privacy Policy, and Cookie Policy.
May 14, 05:21 PM
[Web Browser Content]
Supermemory Console
Search for your card
Top Cards (15 Cards):
- COSTON LR
- VISA EXPRESS
- VISA prime
- Chase Sapphire Preferred Card
- Blue Cash Everyday Card from American Express
- Apple Card
- Chase Freedom Unlimited
- Prime Visa
Plans:
All plans include usage-metered access. Top-ups roll over with paid plans.
FREE ($0/mo):
- Try the API with no commitment
- $5 of usage included
- Pay-as-you-go after $5 runs out
- Full search & memory API access
- Email support
PRO ($19/mo):
- For developers building with AI memory
- $20 of usage included
- Auto top-up when balance runs low
- All plugins (Claude Code, Cursor, Hermes...)
- Priority support
SCALE ($399/mo):
- For teams and production workloads
- $600 of usage included
- Everything in Pro, plus Auto top-up & spend caps
- Gmail, S3 & Web Crawler connectors
- Dedicated support
ENTERPRISE (Custom):
- Custom deployments with dedicated engineering
- Everything in Scale, plus Custom metering & billing, Custom integrations & SSO, Forward-deployed engineer
May 14, 05:21 PM
Speaker 1: ...the tool. That's like a agency, yeah, those tools.
Speaker 2: Mm, yeah. Indeed, indeed.
Speaker 1: So what do you think? What do you recommend?
Speaker 2: Ahrefs, I'm sorry, Ahrefs has 370,000... the...
May 14, 05:21 PM
Speaker 1: ...they're not someone that's trying to learn what link building is, they're using the tool.
Speaker 2: That's it.
Speaker 1: Yeah, Ahrefs, SEMrush, yeah, those tools.
Speaker 2: Hmm, yeah. Indeed, indeed.
Speaker 1: So what, what do you think, what do you recommend?
Speaker 2: Ahrefs, Ahrefs has...
May 14, 05:21 PM
[Web Browser Content]
Supermemory Console
console.supermemory.ai/billing
Overview
Playground
Documents
Container Tags
Memory Graph
Requests
USAGE THIS PERIOD: PRO PLAN
0/0 of monthly usage (resets Jun 14)
TOP-UP CREDITS
No top-up credits yet. Optional add-on that rolls over month-to-month.
ANALYTICS
User Insights
DATA
Connectors
Import
DEVELOPER
API Keys
Agents
Plugins
ORGANIZATION
Team
Billing
Settings
Payment cards in your vault are safe, secure, and ready when you need them.
Saved Cards:
American Express ending in 4006
Capital One Quicksilver Cash Rewards Credit Card
May 14, 05:21 PM
[Web Browser Content]
Supermemory API Documentation: Personal AI Assistant
This endpoint receives the chat request. It expects:
- messages: Full conversation history
- email: User's email for identity
Why require email? Without it, we can't create a stable user ID, meaning no persistent personalization.
Derive User Identity:
try:
user_id = stable_user_id_from_email(email)
except ValueError as e:
raise HTTPException(status_code=400, detail=str(e))
container_tag = convert_email_to_stable_user_id_container_tag(email)
The container tag (e.g., user_abc123) isolates this user's memories from everyone else's. Each user has their own 'memory box.'
Search and Inject Memories:
user_message = messages[-1]["content"]
memory_context = await search_user_memories(user_message, container_tag)
On this page:
- What You'll Build
- Choose Your Implementation
- Prerequisites
- Python Implementation
- Step 1: Project Setup
- Step 2: Backend (FastAPI)
- Step 3: Frontend (Streamlit)
- Step 4: Run It
- TypeScript Implementation
May 14, 05:21 PM
[Web Browser Content]
MemoryBench: Unified benchmark for evaluating conversational memory and RAG across multiple datasets
Languages: TypeScript 99.2%, Other 0.8%
Files:
- README.md
- bun.lock
- framework.md
- package.json
- tsconfig.json
Recent Activity:
- Add MemScore section to README with link to full docs
- Fix memscore review issues: cache encoders, truthiness check
- init: memorybench benchmarking framework
Repository Stats:
- 264 stars
- 1 watching
- 61 forks
- 64 Commits
Contributor: Dhravya
May 14, 05:21 PM
Speaker 1: ...BrightLocal that has heat maps.
Speaker 2: Mm-hmm. I would—I would also argue that anyone who's using something like Ahrefs, they're 100% in our industry. They're not someone that's trying to learn what link building is. They're using...
May 14, 05:21 PM
[Web Browser Content]
Supermemory Console
GitHub: naman06dev/mini-opensearch
Project: mini-opensearch
Description: A perplexity clone enhanced with memory, based on Supermemory's OpenSearch.
Files:
- node_modules
- public
- .DS_Store
- .gitignore
- package-lock.json
- package.json
- server.js
Contributors: Naman Bansal
Languages: JavaScript (58.8%), HTML (41.2%)
May 14, 05:21 PM
Speaker 1: ...whatever, yeah, and then another software maybe, a signal that...
Speaker 2: Right local that has impact.
Speaker 3: I would, I would also argue that anyone who's using something like Ahrefs, they're 100% in our industry.
May 14, 05:21 PM
[Chat Transcript]
V: /restart
V: I also set the env file permissions to see. Next: restart/reload OpenClaw so the new key is picked up.
V: Restarting OpenClaw in-process (SIGUSRI); back in a few seconds.
V: Gateway restart restart 0k (gateway.restart)
V: /restart
V: Run: openclaw doctor --non-interactive
V: Restarting OpenClaw in-process (SIGUSRI); back in a few seconds.
V: Sarsota to Austin Texas June 1st to June 5th find me all flight options make a site on vercel including first class options. also include tampa airport or any other besides TPA and SRQ near me not Orlando though not driving that far to get to an airport.
V: No added note from my side.
Agent: Agent couldn't generate a response. Note: some tool actions may have already been executed — please verify before retrying.
V: * Reduce search limits * Implement caching for frequent queries * Use appropriate thresholds
[Code Snippet: Supermemory UUIDv5 Implementation]
Why UUIDv5? It's deterministic—same email always produces the same ID. This means:
* User memories persist across sessions
* No raw emails in logs or database tags
* Privacy-preserving yet stable identity
We use uuid.NAMESPACE_DNS as the namespace to ensure uniqueness.
[Code Snippet: Memory Search Function]
async def search_user_memories(query: str, container_tag: str) -> str:
try:
results = supermemory_client.search.memories(q=query, container_tag=container_tag, limit=5)
if results.results:
context = "\n".join([r.memory for r in results.results])
return f"Relevant memories: \n{context}"
return "No relevant memories found."
except Exception as e:
return f"Error searching memories: {e}"
May 14, 05:20 PM
[Web Browser Content]
Build Your Own Perplexity in 15 Minutes With Supermemory
Honestly, once I saw it working, I couldn't believe how easy it had been to set up. Let's dive right in.
Here's the GitHub repo with the full code for you to follow along.
Video: perplexity-clone-video
Naman Bansal
Open Search GPT: What are you looking for?
19:03
Saved memories
Vimeo
Retrieve memories without dealing with complicated vector databases or complex integrations.
- Brave Search API: A fast and easy API to pull relevant, real-time web results.
- OpenAI's GPT Model: Just one straightforward call to fuse memories and web search results into clean, easy-to-understand answers.
- Supermemory's Memory API: A super-simple way to automatically save and retrieve memories.
May 14, 05:20 PM
https://github.com/naman06dev/mini-opensearch?ref=blog.supermemory.ai
May 14, 05:20 PM
Speaker 1: And another one's Topmeter, local SEO tool software. So we can use when split between, you know, link building which is more gamble or whatever.
Speaker 2: Yeah.
Speaker 1: And another software maybe, a signal that it's...
May 14, 05:20 PM
[Web Browser Content]
Build Your Own Perplexity in 15 Minutes With Supermemory
Naman Bansal
11 Aug 2025 • 10 min read
Supermemory has a fascinating open-source tool called OpenSearchAI. It's essentially a search assistant similar to Perplexity, but it remembers everything you've searched for and enriches future responses with that memory. I thought to myself, "This seems cool. But how complicated is it to build something like this?" So, I challenged myself: Could I recreate a simplified version of this memory?
May 14, 05:20 PM
...other softwares, see for SEO platforms, right? and another one's Semrush, local SEO tool software. So we can use, split between, you know, link building, which is more...
May 14, 05:20 PM
[Chat Transcript]
Today
Personal
Unread
IO
532
Oscar
Yes — direct/nonstop means TPA is the airport to check first. I'm adding a direct-flight section to the page now so it's obvious.
1:10 PM
Yes: TPA * AUS is the direct/nonstop airport to check first.
• TPA * AUS: yes, best bet for nonstop/direct — likely Southwest. No first class on Southwest.
• SRQ * AUS: no reliable direct; expect 1 stop.
• RSW / PIE / PGD: maybe limited/seasonal, but not better than TPA.
• MCO: excluded like you said.
I updated the site with a direct-flight section: https://srq-aus-flight-options.vercel.app
Sarasota Austin Flight Options | June 1—5, 2026
Flight option board for Sarasota / Tampa area to Austin, Texas, June 1—5, 2026. Includes SRQ TPA, PIE, RSW, PGD and first class/business options.
Ava
Got it. I'm adding it to the OpenClaw env without printing it back.
11:06 AM
Done.
Zernio API key is configured in: / . openclaw/ . env
I also set the env file permissions to see.
Next: restart/reload OpenClaw so the new key is picked up.
11:06 AM
Restarting OpenClaw in-process (SIGUSRI); back in a few seconds.
12:53 PM
Gateway restart restart 0k (gateway.restart)
/restart
Run: openclaw doctor --non-interactive
12:53 PM
Restarting OpenClaw in-process (SIGUSRI); back in a few seconds.
12:54 PM
Sarsota to Austin Texas June 1st to June 5th find me all flight options make a site on vercel including first class options. also include tampa airport or any other besied TPA an SRQ near me not Orlando though not driving that far to get to an airport.
May 14, 05:20 PM
[Web Browser Content]
Supermemory API Reference
Implementation Options:
- Python + FastAPI: Uses FastAPI, Streamlit, and OpenAI.
- TypeScript + AI SDK: Modern React approach using Next.js and Vercel AI SDK.
Prerequisites:
- Python 3.8+ or Node.js 18+
- Supermemory API key
- OpenAI API key
- Note: Never hardcode API keys; use environment variables.
Python Implementation:
Step 4: Project Setup
mkdir personal-ai && cd personal-ai
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
pip install supermemory openai fastapi uvicorn python-dotenv streamlit requests
System Prompt & Identity:
- The system prompt ensures the AI learns user preferences and searches memory.
- Identity Helpers: Normalize emails (trim whitespace, lowercase) to ensure consistency.
- UUIDv5: Used for deterministic user IDs to persist memories across sessions without storing raw emails.
- Memory Injection: Each user has a "memory box" (container tag) to isolate their data.
May 14, 05:20 PM
Speaker 1: We can also see, yeah, yeah, and also I see competitors. Like if you see there are some, I don't know, competitors. I mean, other softwares for SEO platforms, right? And...
May 14, 05:20 PM
[Web Browser Content]
Plugins
API Ref
Provides personalized recommendations based on user history
Handles multiple conversation topics while maintaining context
Choose Your Implementation
Python + FastAPI
Thoroughly tested, production-ready.
Uses FastAPI + Streamlit + OpenAI.
TypeScript + AI SDK
Modern React approach. Uses Next.js +
Vercel AI SDK + Supermemory tools.
Prerequisites
Python 3.8+
Node.js 18+
Supermemory API key (get one here)
OpenAI API key (get one here)
Never hardcode API keys in your code. Use environment variables.
Python Implementation
May 14, 05:20 PM
[Web Browser Content]
What You'll Build
A personal AI assistant that:
- Remembers user preferences (dietary restrictions, work schedule, communication style)
- Maintains context across multiple chat sessions
- Provides personalized recommendations based on user history
- Handles multiple conversation topics while maintaining context
Choose Your Implementation
- Python + FastAPI
- TypeScript + AI SDK
Build a personal AI assistant that learns and remembers everything about the user - their preferences, habits, work context, and conversation history.
On this page:
- What You'll Build
- Choose Your Implementation
- Prerequisites
- Python Implementation
- Step 1: Project Setup
- Step 2: Backend (FastAPI)
- Import Dependencies
- Initialize Application and Clients
- Define System Prompt
- Create Identity Helpers
- Memory Search Function
- Memory Storage Function
- Main Chat Endpoint
- Derive User Identity
- Search and Inject Memories
- Stream OpenAI Response
- Handle Streaming
- Optional Memory Storage
- Return Streaming Response
- Local Development Server
- Step 3: Frontend (Streamlit)
- Step 4: Run It
- TypeScript Implementation
- Step 1: Project Setup
May 14, 05:20 PM
Speaker 1: I don't know though, yeah. So this is a bit of a gamble, but we can also see, yeah, yeah. And also I see competitors, like as you see there, there are some... I don't know, it's... competitors, I mean.
May 14, 05:20 PM
[Web Browser Content]
Cookbook - supermemory | Memory API for the AI era
https://supermemory.ai/blog/building-an-ai-compliance-chatbot-with-supermemory-and-google-drive/
Ask a question...
Available Recipes:
- Personal AI Assistant: Build an AI assistant that remembers user preferences and context across conversations.
- Customer Support Bot: Build a support system that remembers customer history and provides personalized help.
- Document System: Create a chatbot that answers questions from your documents with citations.
- AI SDK Integration: Complete examples using Vercel AI SDK with Supermemory tools.
Cookbook: The Supermemory Cookbook provides complete, production-ready examples that show how to build real applications with Supermemory. Each recipe includes full implementation details, best practices, and common patterns.
May 14, 05:20 PM
> ## Documentation Index
> Fetch the complete documentation index at: https://supermemory.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.
# Personal AI Assistant
> Build an AI assistant that remembers user preferences, habits, and context across conversations
Build a personal AI assistant that learns and remembers everything about the user - their preferences, habits, work context, and conversation history.
## What You'll Build
A personal AI assistant that:
* **Remembers user preferences** (dietary restrictions, work schedule, communication style)
* **Maintains context** across multiple chat sessions
* **Provides personalized recommendations** based on user history
* **Handles multiple conversation topics** while maintaining context
## Choose Your Implementation
<CardGroup cols={2}>
<Card title="Python + FastAPI" icon="python" href="#python-implementation">
Thoroughly tested, production-ready. Uses FastAPI + Streamlit + OpenAI.
</Card>
<Card title="TypeScript + AI SDK" icon="triangle" href="#typescript-implementation">
Modern React approach. Uses Next.js + Vercel AI SDK + Supermemory tools.
</Card>
</CardGroup>
## Prerequisites
* **Python 3.8+** or **Node.js 18+**
* **Supermemory API key** ([get one here](https://console.supermemory.ai))
* **OpenAI API key** ([get one here](https://platform.openai.com/api-keys))
<Warning>
Never hardcode API keys in your code. Use environment variables.
</Warning>
***
## Python Implementation
### Step 1: Project Setup
```bash theme={null}
mkdir personal-ai && cd personal-ai
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
pip install supermemory openai fastapi uvicorn python-dotenv streamlit requests
```
Create a `.env` file:
```bash theme={null}
SUPERMEMORY_API_KEY=your_supermemory_key_here
OPENAI_API_KEY=your_openai_key_here
```
### Step 2: Backend (FastAPI)
Create `main.py`. Let's build it step by step:
#### Import Dependencies
```python theme={null}
from fastapi import FastAPI, HTTPException
from fastapi.responses import StreamingResponse
from openai import AsyncOpenAI
from supermemory import Supermemory
import json
import os
import uuid
from dotenv import load_dotenv
```
* **FastAPI**: Web framework for building the API endpoint
* **StreamingResponse**: Enables real-time response streaming (words appear as they're generated)
* **AsyncOpenAI**: OpenAI client that supports async/await for non-blocking operations
* **Supermemory**: Client for storing and retrieving long-term memories
* **uuid**: Creates stable, deterministic user IDs from emails
#### Initialize Application and Clients
```python theme={null}
load_dotenv()
app = FastAPI()
openai_client = AsyncOpenAI(api_key=os.getenv("OPENAI_API_KEY"))
supermemory_client = Supermemory(api_key=os.getenv("SUPERMEMORY_API_KEY"))
```
`load_dotenv()` loads API keys from your `.env` file into environment variables. We create two clients:
* **OpenAI client**: Handles conversations and generates responses
* **Supermemory client**: Stores and retrieves user-specific memories
These are separate because you can swap providers independently (e.g., switch from OpenAI to Anthropic without changing memory logic).
#### Define System Prompt
```python theme={null}
SYSTEM_PROMPT = """You are a highly personalized AI assistant.
MEMORY MANAGEMENT:
1. When users share personal information, store it immediately
2. Search for relevant context before responding
3. Use past conversations to inform current responses
Always be helpful while respecting privacy."""
```
This prompt guides the assistant's behavior. It tells the AI to:
* Be proactive about learning user preferences
* Always search memory before responding
* Respect privacy boundaries
The system prompt is injected at the start of every conversation, so the AI consistently follows these rules.
#### Create Identity Helpers
```python theme={null}
def normalize_email(email: str) -> str:
return (email or "").strip().lower()
def stable_user_id_from_email(email: str) -> str:
norm = normalize_email(email)
if not norm:
raise ValueError("Email is required")
return uuid.uuid5(uuid.NAMESPACE_DNS, norm).hex
```
**Why normalize?** `"User@Mail.com"` and `" user@mail.com "` should map to the same person. We trim whitespace and lowercase to ensure consistency.
**Why UUIDv5?** It's deterministic—same email always produces the same ID. This means:
* User memories persist across sessions
* No raw emails in logs or database tags
* Privacy-preserving yet stable identity
We use `uuid.NAMESPACE_DNS` as the namespace to ensure uniqueness.
#### Memory Search Function
```python theme={null}
async def search_user_memories(query: str, container_tag: str) -> str:
try:
results = supermemory_client.search.memories(
q=query,
container_tag=container_tag,
limit=5
)
if results.results:
context = "\n".join([r.memory for r in results.results])
return f"Relevant memories:\n{context}"
return "No relevant memories found."
except Exception as e:
return f"Error searching memories: {e}"
```
This searches the user's memory store for context relevant to their current message.
**Parameters:**
* `q`: The search query (usually the user's latest message)
* `container_tag`: Isolates memories per user (e.g., `user_abc123`)
* `limit=5`: Returns top 5 most relevant memories
**Why search before responding?** The AI can provide personalized answers based on what it knows about the user (e.g., dietary preferences, work context, communication style).
**Error handling:** If memory search fails, we return a fallback message instead of crashing. The conversation continues even if memory has a hiccup.
#### Memory Storage Function
```python theme={null}
async def add_user_memory(content: str, container_tag: str, email: str = None):
try:
supermemory_client.add(
content=content,
container_tag=container_tag,
metadata={"type": "personal_info", "email": normalize_email(email) if email else None}
)
except Exception as e:
print(f"Error adding memory: {e}")
```
Stores new information about the user.
**Parameters:**
* `content`: The text to remember
* `container_tag`: User isolation tag
* `metadata`: Additional context (type of info, associated email)
**Why metadata?** Makes it easier to filter and organize memories later (e.g., "show me all personal\_info memories").
**Error handling:** We log errors but don't crash. Failing to save one memory shouldn't break the entire conversation.
#### Main Chat Endpoint
```python theme={null}
@app.post("/chat")
async def chat_endpoint(data: dict):
messages = data.get("messages", [])
email = data.get("email")
if not messages:
raise HTTPException(status_code=400, detail="No messages provided")
if not email:
raise HTTPException(status_code=400, detail="Email required")
```
This endpoint receives the chat request. It expects:
* `messages`: Full conversation history `[{role: "user", content: "..."}]`
* `email`: User's email for identity
**Why require email?** Without it, we can't create a stable user ID, meaning no persistent personalization.
#### Derive User Identity
```python theme={null}
try:
user_id = stable_user_id_from_email(email)
except ValueError as e:
raise HTTPException(status_code=400, detail=str(e))
container_tag = f"user_{user_id}"
```
Convert email → stable user ID → container tag.
The container tag (`user_abc123`) isolates this user's memories from everyone else's. Each user has their own "memory box."
#### Search and Inject Memories
```python theme={null}
user_message = messages[-1]["content"]
memory_context = await search_user_memories(user_message, container_tag)
enhanced_messages = [
{"role": "system", "content": f"{SYSTEM_PROMPT}\n\n{memory_context}"}
] + messages
```
We take the user's latest message, search for relevant memories, then inject them into the system prompt.
**Example:**
```
Original: "What should I eat for breakfast?"
Enhanced system message:
"You are a helpful assistant... [system prompt]
Relevant memories:
- User is vegetarian
- User works out at 6 AM
- User prefers quick meals"
```
Now the AI can answer: "Try overnight oats with plant-based protein—perfect for post-workout!"
#### Stream OpenAI Response
```python theme={null}
try:
response = await openai_client.chat.completions.create(
model="gpt-5",
messages=enhanced_messages,
temperature=0.7,
stream=True
)
```
**Key parameters:**
* `model="gpt-5"`: Fast, capable model
* `messages`: Full conversation + memory context
* `temperature=0.7`: Balanced creativity (0=deterministic, 1=creative)
* `stream=True`: Enables word-by-word streaming
**Why stream?** Users see responses appear in real-time instead of waiting for the complete answer. Much better UX.
#### Handle Streaming
```python theme={null}
async def generate():
try:
async for chunk in response:
if chunk.choices[0].delta.content:
content = chunk.choices[0].delta.content
yield f"data: {json.dumps({'content': content})}\n\n"
except Exception as e:
yield f"data: {json.dumps({'error': str(e)})}\n\n"
```
This async generator:
1. Receives chunks from OpenAI as they're generated
2. Extracts the text content from each chunk
3. Formats it as Server-Sent Events (SSE): `data: {...}\n\n`
4. Yields it to the client
**SSE format** is a web standard for server→client streaming. The frontend can process each chunk as it arrives.
#### Optional Memory Storage
```python theme={null}
if "remember this" in user_message.lower():
await add_user_memory(user_message, container_tag, email=email)
```
After streaming completes, check if the user explicitly asked to remember something. If yes, store it.
**Why opt-in?** Gives users control over what gets remembered. You could also make this automatic based on content analysis.
#### Return Streaming Response
```python theme={null}
return StreamingResponse(generate(), media_type="text/plain")
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
```
`StreamingResponse` keeps the HTTP connection open and sends chunks as they're generated. The frontend receives them in real-time.
#### Local Development Server
```python theme={null}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
```
Run with `python main.py` and the server starts on port 8000. `0.0.0.0` means it accepts connections from any IP (useful for testing from other devices).
### Step 3: Frontend (Streamlit)
Create `streamlit_app.py`:
<Accordion title="Complete Frontend Code" defaultOpen>
```python theme={null}
import streamlit as st
import requests
import json
import uuid
st.set_page_config(page_title="Personal AI Assistant", page_icon="🤖", layout="wide")
def normalize_email(email: str) -> str:
return (email or "").strip().lower()
def stable_user_id_from_email(email: str) -> str:
return uuid.uuid5(uuid.NAMESPACE_DNS, normalize_email(email)).hex
# Session state
if 'messages' not in st.session_state:
st.session_state.messages = []
if 'user_name' not in st.session_state:
st.session_state.user_name = None
if 'email' not in st.session_state:
st.session_state.email = None
if 'user_id' not in st.session_state:
st.session_state.user_id = None
st.title("🤖 Personal AI Assistant")
st.markdown("*Your AI that learns and remembers*")
with st.sidebar:
st.header("👤 User Profile")
if not st.session_state.user_name or not st.session_state.email:
name = st.text_input("What should I call you?")
email = st.text_input("Email", placeholder="you@example.com")
if st.button("Get Started"):
if name and email:
st.session_state.user_name = name
st.session_state.email = normalize_email(email)
st.session_state.user_id = stable_user_id_from_email(st.session_state.email)
st.session_state.messages.append({
"role": "user",
"content": f"Hi! My name is {name}."
})
st.rerun()
else:
st.warning("Please enter both fields.")
else:
st.write(f"**Name:** {st.session_state.user_name}")
st.write(f"**Email:** {st.session_state.email}")
if st.button("Reset Conversation"):
st.session_state.messages = []
st.rerun()
if st.session_state.user_name and st.session_state.email:
for message in st.session_state.messages:
with st.chat_message(message["role"]):
st.markdown(message["content"])
if prompt := st.chat_input("Message..."):
st.session_state.messages.append({"role": "user", "content": prompt})
with st.chat_message("user"):
st.markdown(prompt)
with st.chat_message("assistant"):
try:
response = requests.post(
"http://localhost:8000/chat",
json={
"messages": st.session_state.messages,
"email": st.session_state.email
},
stream=True,
timeout=30
)
if response.status_code == 200:
full_response = ""
for line in response.iter_lines():
if line:
try:
data = json.loads(line.decode('utf-8').replace('data: ', ''))
if 'content' in data:
full_response += data['content']
except:
continue
st.markdown(full_response)
st.session_state.messages.append({"role": "assistant", "content": full_response})
else:
st.error(f"Error: {response.status_code}")
except Exception as e:
st.error(f"Error: {e}")
else:
st.info("Please enter your profile in the sidebar")
```
</Accordion>
### Step 4: Run It
Terminal 1 - Start backend:
```bash theme={null}
python main.py
```
Terminal 2 - Start frontend:
```bash theme={null}
streamlit run streamlit_app.py
```
Open `http://localhost:8501` in your browser.
***
## TypeScript Implementation
### Step 1: Project Setup
```bash theme={null}
npx create-next-app@latest personal-ai --typescript --tailwind --app
cd personal-ai
npm install @supermemory/tools ai @ai-sdk/openai
```
Create `.env.local`:
```bash theme={null}
SUPERMEMORY_API_KEY=your_supermemory_key_here
OPENAI_API_KEY=your_openai_key_here
```
### Step 2: API Route
Create `app/api/chat/route.ts`. Let's break it down:
#### Import Dependencies
```typescript theme={null}
import { streamText } from 'ai'
import { createOpenAI } from '@ai-sdk/openai'
import { supermemoryTools } from '@supermemory/tools/ai-sdk'
```
* **streamText**: Vercel AI SDK function that handles streaming responses and tool calling
* **createOpenAI**: Factory function to create an OpenAI provider
* **supermemoryTools**: Pre-built tools for memory search and storage
#### Initialize OpenAI Provider
```typescript theme={null}
const openai = createOpenAI({
apiKey: process.env.OPENAI_API_KEY!
})
```
Creates an OpenAI provider configured with your API key. The `!` tells TypeScript "this definitely exists" (because we set it in `.env.local`).
This provider object will be passed to `streamText` to specify which AI model to use.
#### Define System Prompt
```typescript theme={null}
const SYSTEM_PROMPT = `You are a highly personalized AI assistant.
When users share personal information, remember it using the addMemory tool.
Before responding, search your memories using searchMemories to provide personalized help.
Always be helpful while respecting privacy.`
```
This guides the AI's behavior and tells it:
* **When to use tools**: Search memories before responding, add memories when users share info
* **Personality**: Be helpful and personalized
* **Boundaries**: Respect privacy
The AI SDK uses this to decide when to call `searchMemories` and `addMemory` tools automatically.
#### Create POST Handler
```typescript theme={null}
export async function POST(req: Request) {
try {
const { messages, email } = await req.json()
```
Next.js App Router convention: export an async function named after the HTTP method. This handles POST requests to `/api/chat`.
We extract:
* `messages`: Chat history array `[{role, content}]`
* `email`: User identifier
#### Validate Input
```typescript theme={null}
if (!messages?.length) {
return new Response('No messages provided', { status: 400 })
}
if (!email) {
return new Response('Email required', { status: 400 })
}
```
**Why validate?** Prevents crashes from malformed requests. We need:
* At least one message to respond to
* An email to isolate user memories
Without email, we can't maintain personalization across sessions.
#### Create Container Tag
```typescript theme={null}
const containerTag = `user_${email.toLowerCase().trim()}`
```
Convert email to a container tag for memory isolation.
**Simpler than Python**: We skip UUID generation here for simplicity. In production, you might want to hash the email for privacy:
```typescript theme={null}
// Optional: More privacy-preserving approach
import crypto from 'crypto'
const containerTag = `user_${crypto.createHash('sha256').update(email).digest('hex').slice(0, 16)}`
```
#### Call streamText with Tools
```typescript theme={null}
const result = streamText({
model: openai('gpt-5'),
messages,
tools: supermemoryTools(process.env.SUPERMEMORY_API_KEY!, {
containerTags: [containerTag]
}),
system: SYSTEM_PROMPT
})
```
This is where the magic happens! Let's break down each parameter:
**`model: openai('gpt-5')`**
* Specifies which AI model to use
* The AI SDK handles the API calls
**`messages`**
* Full conversation history
* Format: `[{role: "user"|"assistant", content: "..."}]`
**`tools: supermemoryTools(...)`**
* Gives the AI access to memory operations
* The AI SDK automatically:
* Decides when to call tools based on the conversation
* Calls `searchMemories` when it needs context
* Calls `addMemory` when users share information
* Handles tool execution and error handling
**`containerTags: [containerTag]`**
* Scopes all memory operations to this specific user
* Ensures User A can't access User B's memories
**`system: SYSTEM_PROMPT`**
* Guides the AI's behavior and tool usage
**How tools work:**
1. User: "Remember that I'm vegetarian"
2. AI SDK detects this is memory-worthy
3. Automatically calls `addMemory("User is vegetarian")`
4. Stores in Supermemory with the user's container tag
5. Responds: "Got it, I'll remember that!"
Later:
1. User: "What should I eat?"
2. AI SDK calls `searchMemories("food preferences")`
3. Retrieves: "User is vegetarian"
4. Responds: "How about a delicious veggie stir-fry?"
**No manual tool handling needed!** The AI SDK manages the entire flow.
#### Return Streaming Response
```typescript theme={null}
return result.toAIStreamResponse()
```
`toAIStreamResponse()` converts the streaming result into a format the frontend can consume. It:
* Sets appropriate headers for streaming
* Formats data for the `useChat` hook
* Handles errors gracefully
This returns immediately (doesn't wait for completion), and chunks stream to the client as they're generated.
#### Error Handling
```typescript theme={null}
} catch (error: any) {
console.error('Chat error:', error)
return new Response(error.message, { status: 500 })
}
}
```
Catches any errors (API failures, tool errors, etc.) and returns a clean error response.
**Why log to console?** In production, you'd send this to a monitoring service (Sentry, DataDog, etc.) to track issues.
***
**Key Differences from Python:**
| Aspect | Python | TypeScript |
| ------------------ | ------------------------------------ | ------------------------------------------------ |
| **Memory Search** | Manual `search_user_memories()` call | AI SDK calls `searchMemories` tool automatically |
| **Memory Add** | Manual `add_user_memory()` call | AI SDK calls `addMemory` tool automatically |
| **Tool Decision** | You decide when to search/add | AI decides based on conversation context |
| **Streaming** | Manual SSE formatting | `toAIStreamResponse()` handles it |
| **Error Handling** | Try/catch in each function | AI SDK handles tool errors |
**Python = Manual Control**
You explicitly search and add memories. More control, more code.
**TypeScript = AI-Driven**
The AI decides when to use tools. Less code, more "magic."
### Step 3: Chat UI
Replace `app/page.tsx`:
<Accordion title="Complete Frontend Code" defaultOpen>
```typescript theme={null}
'use client'
import { useChat } from 'ai/react'
import { useState } from 'react'
export default function ChatPage() {
const [email, setEmail] = useState('')
const [userName, setUserName] = useState('')
const [tempEmail, setTempEmail] = useState('')
const [tempName, setTempName] = useState('')
const { messages, input, handleInputChange, handleSubmit } = useChat({
api: '/api/chat',
body: { email }
})
if (!email) {
return (
<div className="flex items-center justify-center min-h-screen p-4">
<div className="w-full max-w-md space-y-4 p-6 bg-white rounded-lg shadow-lg">
<h1 className="text-2xl font-bold text-center">🤖 Personal AI Assistant</h1>
<input
type="text"
placeholder="Your name"
value={tempName}
onChange={(e) => setTempName(e.target.value)}
className="w-full px-4 py-2 border rounded-lg"
/>
<input
type="email"
placeholder="your@email.com"
value={tempEmail}
onChange={(e) => setTempEmail(e.target.value)}
className="w-full px-4 py-2 border rounded-lg"
/>
<button
onClick={() => {
if (tempName && tempEmail) {
setUserName(tempName)
setEmail(tempEmail.toLowerCase().trim())
}
}}
className="w-full px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700"
>
Get Started
</button>
</div>
</div>
)
}
return (
<div className="flex flex-col h-screen max-w-4xl mx-auto p-4">
<div className="flex-1 overflow-y-auto space-y-4 mb-4">
{messages.map((message) => (
<div
key={message.id}
className={`p-4 rounded-lg ${
message.role === 'user'
? 'bg-blue-100 ml-auto max-w-[80%]'
: 'bg-gray-100 mr-auto max-w-[80%]'
}`}
>
<p className="whitespace-pre-wrap">{message.content}</p>
</div>
))}
</div>
<form onSubmit={handleSubmit} className="flex gap-2">
<input
value={input}
onChange={handleInputChange}
placeholder="Tell me about yourself..."
className="flex-1 p-3 border rounded-lg"
/>
<button
type="submit"
className="px-6 py-3 bg-blue-600 text-white rounded-lg hover:bg-blue-700"
>
Send
</button>
</form>
</div>
)
}
```
</Accordion>
### Step 4: Run It
```bash theme={null}
npm run dev
```
Open `http://localhost:3000`
***
## Testing Your Assistant
Try these conversations to test memory:
**Personal Preferences:**
```
User: "I'm Sarah, a product manager. I prefer brief responses."
[Later]
User: "What's a good way to prioritize features?"
Assistant: [Should reference PM role and brevity preference]
```
**Dietary & Lifestyle:**
```
User: "Remember I'm vegan and work out at 6 AM."
[Later]
User: "Suggest a quick breakfast."
Assistant: [Should suggest vegan options for pre/post workout]
```
**Work Context:**
```
User: "I'm working on a React project with TypeScript."
[Later]
User: "Help me with state management."
Assistant: [Should suggest TypeScript-specific solutions]
```
## Verify Memory Storage
### Python
Create `check_memories.py`:
```python theme={null}
from supermemory import Supermemory
import os
from dotenv import load_dotenv
load_dotenv()
client = Supermemory(api_key=os.getenv("SUPERMEMORY_API_KEY"))
# Replace with your user_id from console logs
user_id = "your_user_id_here"
container_tag = f"user_{user_id}"
memories = client.documents.list(
container_tags=[container_tag],
limit=20,
sort="updatedAt",
order="desc"
)
print(f"Found {len(memories.memories)} memories:")
for i, memory in enumerate(memories.memories):
full = client.documents.get(id=memory.id)
print(f"\n{i + 1}. {full.content}")
```
### TypeScript
Create `scripts/check-memories.ts`:
```typescript theme={null}
const userId = "your_user_id_here"
const containerTag = `user_${userId}`
const response = await fetch('https://api.supermemory.ai/v3/memories', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.SUPERMEMORY_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
containerTags: [containerTag],
limit: 20,
sort: 'updatedAt',
order: 'desc'
})
})
const data = await response.json()
console.log(`Found ${data.memories?.length || 0} memories`)
```
## Troubleshooting
**Memory not persisting?**
* Verify container tags are consistent
* Check API key has write permissions
* Ensure email is properly normalized
**Responses not personalized?**
* Increase search limit to find more memories
* Check that memories are being added
* Verify system prompt guides tool usage
**Performance issues?**
* Reduce search limits
* Implement caching for frequent queries
* Use appropriate thresholds
***
*Built with Supermemory. Customize based on your needs.*
May 14, 05:20 PM