Skip to content

asmit25805/memos

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MemOS

A real-time memory and operating system for companies — it remembers everything that happens across your tools, knows when that information goes stale, and can act on your behalf.


What this is

Most AI tools that companies plug into Slack, Notion, or their docs have a quiet flaw: they read your company's knowledge once, then keep answering from that snapshot — even after the real answer changed. A policy updates in Slack. A process changes in a GitHub PR. The AI tool never finds out. It keeps giving the old answer, confidently, to whoever asks.

MemOS fixes this and goes further. It is two things:

1. A memory layer that reads Slack and GitHub in near real time, stores what it learns with versioned timestamps, detects when new information contradicts something already stored, and — instead of silently overwriting — puts both side by side for a human to approve or reject. Nothing is ever deleted; old information is archived with a timestamp so you can ask what was true on any past date.

2. An action layer sitting on top of that memory. Because MemOS knows what is actually true in your company right now, it can act on that knowledge — send a Slack message, open a GitHub issue, draft an email — using plain English commands, with a confirmation step before anything executes.


What it does in practice

For the company: every employee gets the current, correct answer with a citation. When information changes, a human confirms before it takes effect. Auditors can ask what the company knew on any specific date and get an exact sourced answer.

For each individual: the support rep stops giving out-of-date answers. The new hire asks MemOS instead of interrupting five coworkers. The engineer stops scrolling through six-month-old Slack threads. The PM stops posting the same update to three channels manually.


Screenshots

Login

Login screen

Chat — ask anything, get cited answers

Chat screen

Memory browser — view, filter, and manage all stored knowledge

Memory browser

Deprecation queue — human-in-the-loop conflict review

Deprecation queue

Actions — plain English commands executed across your tools

Actions screen

Settings — connect Slack and GitHub

Settings screen


How it actually works

Slack / GitHub / manual text
        │
        ▼
  Decision filter  ──── regex scan, skips noise before any API call
        │
        ▼
  Chunk + embed (Gemini text-embedding-004)
        │
        ▼
  Store in ChromaDB
    timestamp        → ISO string (display)
    timestamp_epoch  → Unix int  (ChromaDB filtering)
    deprecated_at    → ISO string (display)
    deprecated_at_epoch → Unix int (ChromaDB filtering, sentinel: 253402300799)
    is_deprecated    → bool
        │
        ▼
  Conflict check  ──── cosine similarity against active chunks → pending queue
        │
        ▼
  Human review  ──── approve retires old chunk, reject keeps both

Why epoch integers? ChromaDB's $lte/$gt operators only work on numbers, not strings. Timestamps are stored as both ISO strings (for display) and Unix epoch integers (for filtering). The sentinel for "never deprecated" is 253402300799 (year 9999 as epoch), which lets historical queries use a clean deprecated_at_epoch > as_of_epoch filter without nullable fields.

Historical queries: ask what was true on any past date using timestamp_epoch ≤ as_of_epoch AND deprecated_at_epoch > as_of_epoch. Active chunks always pass the second condition because their sentinel is far in the future.


Feature list

Memory

  • Real-time Slack ingestion (polls every 30 seconds, including thread replies)
  • Real-time GitHub ingestion via webhooks (pushes, PR merges, issues)
  • Manual ingestion of any pasted text
  • Decision-keyword filtering — 22 regex patterns skip non-decision Slack noise before any API call
  • Per-user isolated ChromaDB collections (multi-tenant ready)

Correctness over time

  • Automatic conflict detection on every ingest
  • Human-in-the-loop deprecation queue — nothing auto-deleted or auto-overwritten
  • Side-by-side conflict view with similarity score and source info
  • Full version history — old chunks archived with timestamp, never erased
  • Historical queries — reconstructs what was known on any past date

Question answering

  • Natural-language Q&A grounded only in stored knowledge
  • Inline citations linking back to original source
  • Source name, URL, and timestamp shown per citation

Actions

  • Plain-English command parsing via Gemini function calling
  • Confirm-before-execute on every action
  • Send Slack message to any channel
  • Create GitHub issue with title, body, and labels
  • Draft email (subject + full body)
  • Full action history log with status

Operations

  • /health endpoint — DB status, scheduler status, last poll time, pending conflict count
  • Live sidebar health indicator (poller running/stopped, conflicts awaiting review, chunk count)
  • Memory browser with source filter, deprecated toggle, and pagination
  • Webhook URL override field for ngrok / production URLs

Technical list

Backend

Component Technology
API framework FastAPI (async throughout)
Vector store ChromaDB 0.5.3 (persistent, cosine similarity)
Relational store SQLite via aiosqlite
Embeddings Gemini text-embedding-004 (768 dims, retrieval_document / retrieval_query task types)
Q&A + action parsing Gemini Flash 1.5 (function calling for actions)
Auth JWT (python-jose) + bcrypt 4.0.1 (pinned for passlib compatibility)
Background jobs APScheduler async (Slack polling loop)
Slack slack_sdk AsyncWebClient
GitHub PyGithub + HMAC webhook verification

Frontend

Component Technology
Structure Single HTML file, no build step
Styling Tailwind CSS (CDN)
Reactivity Alpine.js 3.14
Fonts Inter + JetBrains Mono (Google Fonts)

Data model

ChromaDB chunk metadata:
  source           str    # 'slack', 'github', 'manual'
  source_name      str    # '#general', 'PR #42', 'Policy doc'
  source_url       str    # link back to original
  author           str
  timestamp        str    # ISO 8601 (display)
  timestamp_epoch  int    # Unix epoch (ChromaDB filtering)
  deprecated_at    str    # ISO 8601 or '9999-12-31T23:59:59Z'
  deprecated_at_epoch int # Unix epoch or 253402300799
  is_deprecated    bool
  deprecated_by    str
  decision_match   bool   # matched a decision keyword

File structure

memos/
├── backend/
│   ├── main.py              # FastAPI app, lifespan, /health endpoint
│   ├── config.py            # Pydantic settings from .env
│   ├── database.py          # SQLite schema, 5 tables
│   ├── auth.py              # JWT, bcrypt, user CRUD
│   ├── vector_store.py      # ChromaDB wrapper with epoch timestamp handling
│   ├── scheduler.py         # APScheduler — Slack background polling
│   ├── services/
│   │   ├── embedder.py      # Gemini text-embedding-004
│   │   ├── llm.py           # Gemini Flash — Q&A + function calling
│   │   ├── ingestion.py     # Decision filter → chunk → embed → store → conflict check
│   │   ├── conflict.py      # Epoch-based similarity search → deprecation queue
│   │   └── slack_poller.py  # Incremental channel + thread reply polling
│   └── routers/
│       ├── auth_router.py
│       ├── memory_router.py       # /stats and /list before /{chunk_id}
│       ├── deprecation_router.py
│       ├── actions_router.py
│       └── integrations_router.py # HMAC webhook, Slack token validation
├── frontend/
│   └── index.html           # Full SPA — login + 5 sections
├── data/                    # Auto-created at boot
├── requirements.txt         # bcrypt==4.0.1 pinned
├── .env.example
├── run.py
└── test_memos.py

Setup

Minimum to run

# 1. Unzip and enter
cd memos

# 2. Create venv
python3 -m venv venv && source venv/bin/activate  # Windows: venv\Scripts\activate

# 3. Install
pip install -r requirements.txt

# 4. Configure
cp .env.example .env
# Edit .env — add your GEMINI_API_KEY (free at https://aistudio.google.com/app/apikey)

# 5. Run
python run.py
# → http://localhost:8000

Connecting Slack

  1. Create app at https://api.slack.com/apps → From scratch
  2. OAuth & Permissions → Bot Token Scopes: channels:history, channels:read, chat:write
  3. Install to workspace → copy xoxb-… token
  4. In Slack: /invite @YourBotName in each channel to monitor
  5. In MemOS Settings → paste token + channel IDs → Connect

Connecting GitHub

  1. https://github.com/settings/tokens → scopes: repo, issues
  2. In MemOS Settings → paste token + default repo → Connect
  3. For webhooks: paste your public URL in the override field (use ngrok for local dev: ngrok http 8000)
  4. In GitHub repo → Settings → Webhooks → Add: events push, pull_request, issues

Run tests

pip install httpx
python test_memos.py
# Against deployed: python test_memos.py --url https://your-app.fly.dev

Environment variables

Variable Required Default Description
GEMINI_API_KEY Google AI Studio (free)
JWT_SECRET insecure default Change before deploying
SLACK_BOT_TOKEN xoxb-…
SLACK_CHANNELS Comma-separated channel IDs
SLACK_POLL_INTERVAL_SECONDS 30 Polling frequency
GITHUB_TOKEN Personal access token
GITHUB_WEBHOOK_SECRET HMAC secret for webhook verification
SIMILARITY_THRESHOLD 0.85 Conflict detection sensitivity

Deploy to Fly.io (free tier)

fly auth login
fly launch  # accept defaults, skip database
fly secrets set GEMINI_API_KEY=your_key JWT_SECRET=your_secret
fly volumes create memos_data --size 1
# Add to fly.toml:  [mounts] source="memos_data" destination="/app/data"
fly deploy

Bugs fixed in this version

Bug Impact Fix
bcrypt version conflict with passlib Auth completely broken Pinned bcrypt==4.0.1 in requirements
ChromaDB $lte/$gt rejects string timestamps Historical queries silently returned no results Added timestamp_epoch and deprecated_at_epoch as Unix int fields
Conflict detection used string timestamp comparison Wrong ordering, missed conflicts Switched to timestamp_epoch comparison
Slack thread replies not fetched Decisions in threads completely missed Added conversations_replies call for all threaded messages
hmac.new() deprecated form Minor warning Updated to hmac.HMAC()
GET /memory/stats registered after GET /memory/{chunk_id} Route could shadow stats endpoint Moved specific routes before parameterised routes
GitHub webhook URL showed localhost in Settings Webhook useless for local dev Added public URL override input

Roadmap

  • Email SMTP sending (draft is ready, send not wired)
  • Notion / Confluence connectors
  • Google Calendar scheduling actions
  • Automated standups and weekly digest
  • Proactive alerts (unanswered questions, stale deprecation queue)
  • Cross-tool rule automation ("when X, do Y")
  • Slack slash command (/ask what is our refund policy?)

About

Real-time AI memory and operating system for companies

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages