Synapse
A second brain for life management — stores, classifies, and connects all personal information (events, thoughts, tasks, projects, preferences, people) via MCP + REST API. Provides specialized agents, hybrid search (SQL + Vector + FTS5), and a Next.js dashboard for analytics, control, and AI-powered advice.
╔══════════════════════════════════════════════════════════════════════════════════╗
║ USER INTERFACES ║
║ ║
║ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌───────────┐ ┌───────────────┐ ║
║ │ Telegram │ │ Slack │ │ WhatsApp │ │ Discord │ │ Gmail │ ║
║ └────┬─────┘ └────┬─────┘ └────┬─────┘ └─────┬─────┘ └──────┬────────┘ ║
║ │ │ │ │ │ ║
║ └──────────────┴──────────────┴──────┬───────┴───────────────┘ ║
║ │ ║
║ ▼ ║
║ ┌─────────────────────────────────────────────────────────────────────────┐ ║
║ │ NEMOCLAW GATEWAY │ ║
║ │ │ ║
║ │ ┌─────────────┐ ┌──────────────┐ ┌──────────────┐ │ ║
║ │ │ Webhooks │ │ Channel │ │ Scheduled │ │ ║
║ │ │ Receiver │ │ Router │ │ Tasks │ │ ║
║ │ └──────┬──────┘ └──────┬───────┘ └──────┬───────┘ │ ║
║ │ │ │ │ │ ║
║ │ └────────────────┼──────────────────┘ │ ║
║ │ │ │ ║
║ │ ▼ │ ║
║ │ ┌────────────────────────────────────────────────────────────────┐ │ ║
║ │ │ NVIDIA OpenShell Runtime │ │ ║
║ │ │ │ │ ║
║ │ │ ┌──────────────┐ ┌──────────────┐ ┌───────────────────────┐ │ │ ║
║ │ │ │ Guardrails │ │ Privacy │ │ RBAC Policies │ │ │ ║
║ │ │ │ (anti │ │ Router │ │ (action-level │ │ │ ║
║ │ │ │ prompt │ │ (data leak │ │ permissions) │ │ │ ║
║ │ │ │ injection) │ │ protection)│ │ │ │ │ ║
║ │ │ └──────────────┘ └──────────────┘ └───────────────────────┘ │ │ ║
║ │ └────────────────────────────────────────────────────────────────┘ │ ║
║ │ │ │ ║
║ │ ▼ │ ║
║ │ ┌────────────────────────────────────────────────────────────────┐ │ ║
║ │ │ HUMAN-IN-THE-LOOP (HITL) Engine │ │ ║
║ │ │ │ │ ║
║ │ │ Event ──→ Agent generates plan (JSON) ──→ Suspend │ │ ║
║ │ │ │ │ │ ║
║ │ │ ┌───────────────────────────┘ │ │ ║
║ │ │ ▼ │ │ ║
║ │ │ Push notification ──→ Approver App ──→ [Approve/Edit/Reject] │ │ ║
║ │ │ │ │ │ ║
║ │ │ ┌───────────────────────────┘ │ │ ║
║ │ │ ▼ │ │ ║
║ │ │ Resume ──→ Inject API keys ──→ Execute in Sandbox │ │ ║
║ │ └────────────────────────────────────────────────────────────────┘ │ ║
║ │ │ │ ║
║ │ ▼ │ ║
║ │ ┌────────────────────────────────────────────────────────────────┐ │ ║
║ │ │ EPHEMERAL SANDBOX (per-invocation) │ │ ║
║ │ │ │ │ ║
║ │ │ • Docker / Apple Container │ │ ║
║ │ │ • network: none (no outbound access) │ │ ║
║ │ │ • filesystem: read-only (host code) │ │ ║
║ │ │ • only mounted dirs accessible │ │ ║
║ │ │ • destroyed after each invocation │ │ ║
║ │ │ • unprivileged user │ │ ║
║ │ │ │ │ ║
║ │ │ ┌───────────────────────────────────────────────────────┐ │ │ ║
║ │ │ │ Agent (Claude Agent SDK / Nemotron) │ │ │ ║
║ │ │ │ │ │ │ ║
║ │ │ │ Connects to Synapse via MCP ──────────────────────┐ │ │ │ ║
║ │ │ └───────────────────────────────────────────────────┘│ │ │ │ ║
║ │ └────────────────────────────────────────────────────────┘│ │ │ │ ║
║ └─────────────────────────────────────────────────────────────┘ │ │ │ ║
╚════════════════════════════════════════════════════════════════════╪══════════╪════╝
│ │
┌───────────────────────────────────────┘ │
│ │
▼ │
╔════════════════════════════════════════════════════════════════════════════════╗
║ ║
║ SYNAPSE — MEMORY BRAIN ║
║ (MCP Server + REST API) ║
║ ║
║ ┌────────────────────────────────────────────────────────────────────────┐ ║
║ │ MCP INTERFACE │ ║
║ │ │ ║
║ │ Tools exposed to LLM agents: │ ║
║ │ │ ║
║ │ • synapse_ingest(text, source?) │ ║
║ │ → classify + extract entities + store │ ║
║ │ │ ║
║ │ • synapse_search(query, type?, limit?) │ ║
║ │ → hybrid search (vector + FTS + SQL) │ ║
║ │ │ ║
║ │ • synapse_list(type, filters?, sort?) │ ║
║ │ → structured query (SELECT * FROM movies WHERE ...) │ ║
║ │ │ ║
║ │ • synapse_get(id) │ ║
║ │ → full entry details + relations │ ║
║ │ │ ║
║ │ • synapse_relate(source_id, target_id, relation_type) │ ║
║ │ → link two entries │ ║
║ │ │ ║
║ │ • synapse_profile() │ ║
║ │ → aggregated user profile │ ║
║ │ │ ║
║ │ • synapse_timeline(start_date, end_date) │ ║
║ │ → chronological entries │ ║
║ │ │ ║
║ │ Consumers: │ ║
║ │ ├── NemoClaw agents (in sandboxes) │ ║
║ │ ├── Claude Code (direct MCP connection) │ ║
║ │ ├── Gemini CLI (direct MCP connection) │ ║
║ │ └── Windsurf / Cursor (direct MCP connection) │ ║
║ └────────────────────────────────────────────────────────────────────────┘ ║
║ ║
║ ┌────────────────────────────────────────────────────────────────────────┐ ║
║ │ REST API (FastAPI) │ ║
║ │ │ ║
║ │ POST /ingest ← Dashboard quick-input, CLI │ ║
║ │ GET /search ← Dashboard search bar │ ║
║ │ GET /entities/{type} ← Dashboard tables (movies, tasks, etc.) │ ║
║ │ POST /agents/{name} ← Direct agent invocation │ ║
║ │ GET /timeline ← Dashboard timeline view │ ║
║ │ GET /profile ← User profile page │ ║
║ │ WS /ws/events ← Real-time updates to dashboard │ ║
║ │ │ ║
║ │ Consumers: │ ║
║ │ ├── Next.js Dashboard │ ║
║ │ ├── Typer CLI │ ║
║ │ └── NemoClaw Approver App (React) │ ║
║ └────────────────────────────────────────────────────────────────────────┘ ║
║ ║
║ ┌────────────────────────────────────────────────────────────────────────┐ ║
║ │ ORCHESTRATOR │ ║
║ │ │ ║
║ │ user input ──→ LLM (Claude) ──→ plan: [ │ ║
║ │ {agent: "calendar", action: ...}, │ ║
║ │ {agent: "people", action: ...} │ ║
║ │ ] │ ║
║ │ │ │ ║
║ │ ┌───────────┼───────────┐ │ ║
║ │ ▼ ▼ ▼ │ ║
║ │ parallel parallel sequential │ ║
║ │ execution execution (if depends_on) │ ║
║ └────────────────────────────────────────────────────────────────────────┘ ║
║ │ ║
║ ┌───────────┼───────────────┐ ║
║ ▼ ▼ ▼ ║
║ ┌────────────────────────────────────────────────────────────────────────┐ ║
║ │ SPECIALIZED AGENTS │ ║
║ │ │ ║
║ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ ║
║ │ │ Memory │ │ Calendar │ │ Tasks │ │ People │ │ Media │ │ ║
║ │ │ Agent │ │ Agent │ │ Agent │ │ Agent │ │ Agent │ │ ║
║ │ │ │ │ │ │ │ │ │ │ │ │ ║
║ │ │ search │ │ create │ │ create │ │ add │ │ add │ │ ║
║ │ │ recall │ │ list │ │ update │ │ relate │ │ rate │ │ ║
║ │ │ forget │ │ remind │ │ assign │ │ lookup │ │ list │ │ ║
║ │ │ timeline │ │ sync* │ │ complete │ │ graph │ │ recommend│ │ ║
║ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ ║
║ │ │ ║
║ │ ┌──────────┐ ┌──────────┐ │ ║
║ │ │ Profile │ │ Resource │ ← Extensible: new agents added │ ║
║ │ │ Agent │ │ Agent │ without changing existing ones │ ║
║ │ │ │ │ │ │ ║
║ │ │ analyze │ │ save_url │ │ ║
║ │ │ summarize│ │ list │ │ ║
║ │ │ portrait │ │ tag │ │ ║
║ │ └──────────┘ └──────────┘ │ ║
║ │ │ ║
║ │ All agents communicate via MessageBus (asyncio.Queue → Redis Streams) │ ║
║ └────────────────────────────────────────────────────────────────────────┘ ║
║ │ ║
║ ▼ ║
║ ┌────────────────────────────────────────────────────────────────────────┐ ║
║ │ INTAKE PIPELINE │ ║
║ │ │ ║
║ │ raw text ──→ ┌────────────────────┐ │ ║
║ │ │ INTAKE CLASSIFIER │ ← Gemini Flash / GPT-4o-mini │ ║
║ │ │ │ (10-20x дешевле Sonnet) │ ║
║ │ │ • is_significant? │ │ ║
║ │ │ • entry_type │ │ ║
║ │ │ • entities │ │ ║
║ │ │ • sentiment │ │ ║
║ │ └────────┬────────────┘ │ ║
║ │ │ │ ║
║ │ ┌──────────┴──────────┐ │ ║
║ │ │ significant? │ │ ║
║ │ │ │ │ ║
║ │ NO ← │ │ → YES │ ║
║ │ drop └──────────────────┘ │ │ ║
║ │ ▼ │ ║
║ │ ┌────────────────────┐ │ ║
║ │ │ ENTITY EXTRACTOR │ │ ║
║ │ │ │ │ ║
║ │ │ • people → resolve │ │ ║
║ │ │ • dates → parse │ │ ║
║ │ │ • places → geocode │ │ ║
║ │ │ • tags → normalize │ │ ║
║ │ │ • relations → link │ │ ║
║ │ └────────┬────────────┘ │ ║
║ │ │ │ ║
║ │ ▼ │ ║
║ │ ┌────────────────────┐ │ ║
║ │ │ STORAGE WRITER │ │ ║
║ │ │ │ │ ║
║ │ │ → SQL (relational) │ │ ║
║ │ │ → ChromaDB (vector) │ │ ║
║ │ │ → FTS5 (keywords) │ │ ║
║ │ └─────────────────────┘ │ ║
║ └────────────────────────────────────────────────────────────────────────┘ ║
║ │ ║
║ ▼ ║
║ ┌────────────────────────────────────────────────────────────────────────┐ ║
║ │ SHARED MEMORY LAYER │ ║
║ │ │ ║
║ │ ┌─────────────────────┐ ┌─────────────────────┐ │ ║
║ │ │ │ │ │ │ ║
║ │ │ SQLite / PostgreSQL│ │ ChromaDB / Qdrant │ │ ║
║ │ │ (structured data) │ │ (vector embeddings) │ │ ║
║ │ │ │ │ │ │ ║
║ │ │ Tables: │ │ Collections: │ │ ║
║ │ │ ├── entries │ │ └── synapse_memory │ │ ║
║ │ │ ├── events │ │ ├── id │ │ ║
║ │ │ ├── tasks │ │ ├── embedding │ │ ║
║ │ │ ├── media_items │ │ ├── metadata │ │ ║
║ │ │ ├── preferences │ │ └── document │ │ ║
║ │ │ ├── entities │ │ │ │ ║
║ │ │ ├── relations │ │ Embedding model: │ │ ║
║ │ │ ├── tags │ │ text-embedding-3- │ │ ║
║ │ │ └── entry_tags │ │ small (1536 dims) │ │ ║
║ │ │ │ │ │ │ ║
║ │ │ + FTS5 virtual │ │ │ │ ║
║ │ │ table (keywords) │ │ │ │ ║
║ │ └─────────────────────┘ └──────────────────────┘ │ ║
║ │ │ ║
║ │ Query routing: │ ║
║ │ "фильмы с рейтингом > 8" → SQL │ ║
║ │ "фильм про сны внутри снов" → Vector (semantic) │ ║
║ │ "Inception" → FTS5 (keyword) │ ║
║ │ "крутые фильмы типа Inception" → Vector + SQL (hybrid + RRF merge) │ ║
║ └────────────────────────────────────────────────────────────────────────┘ ║
║ ║
║ ┌────────────────────────────────────────────────────────────────────────┐ ║
║ │ LLM ROUTER (litellm) │ ║
║ │ │ ║
║ │ Task │ Provider │ Model │ ║
║ │ ────────────────────────┼────────────────────┼──────────────────────── │ ║
║ │ Orchestration (planning)│ Anthropic │ Claude Sonnet │ ║
║ │ Classification (intake) │ Google │ Gemini Flash │ ║
║ │ Entity extraction │ Google │ Gemini Flash │ ║
║ │ Embeddings │ OpenAI │ text-embedding-3-small │ ║
║ │ Profile analysis │ Anthropic │ Claude Sonnet │ ║
║ │ Agent reasoning │ Anthropic / Google │ Configurable per agent │ ║
║ └────────────────────────────────────────────────────────────────────────┘ ║
║ ║
╚════════════════════════════════════════════════════════════════════════════════╝
╔════════════════════════════════════════════════════════════════════════════════╗
║ FRONTEND LAYER ║
║ ║
║ ┌────────────────────────────────────────────────────────────────────────┐ ║
║ │ NEXT.JS DASHBOARD │ ║
║ │ (connects to Synapse REST API) │ ║
║ │ │ ║
║ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ ║
║ │ │ Dashboard │ │ Timeline │ │ Search │ │ ║
║ │ │ (home) │ │ (chrono) │ │ (semantic) │ │ ║
║ │ │ │ │ │ │ │ │ ║
║ │ │ widgets: │ │ all entries │ │ hybrid │ │ ║
║ │ │ - today's │ │ filtered by │ │ results │ │ ║
║ │ │ events │ │ type, date, │ │ across all │ │ ║
║ │ │ - pending │ │ tags │ │ types │ │ ║
║ │ │ tasks │ │ │ │ │ │ ║
║ │ │ - quick │ │ │ │ │ │ ║
║ │ │ input │ │ │ │ │ │ ║
║ │ └──────────────┘ └──────────────┘ └──────────────┘ │ ║
║ │ │ ║
║ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ ║
║ │ │ Movies │ │ Tasks │ │ People │ │ ║
║ │ │ (table) │ │ (kanban) │ │ (graph) │ │ ║
║ │ │ │ │ │ │ │ │ ║
║ │ │ sortable, │ │ drag-drop │ │ vis.js │ │ ║
║ │ │ filterable │ │ columns: │ │ network │ │ ║
║ │ │ DataTable │ │ pending → │ │ + cards │ │ ║
║ │ │ (shadcn) │ │ progress → │ │ │ │ ║
║ │ │ │ │ done │ │ │ │ ║
║ │ └──────────────┘ └──────────────┘ └──────────────┘ │ ║
║ │ │ ║
║ │ ┌──────────────┐ ┌──────────────────────────────────┐ │ ║
║ │ │ Resources │ │ Approver Panel (HITL) │ │ ║
║ │ │ (links, │ │ │ │ ║
║ │ │ videos, │ │ Pending actions from NemoClaw: │ │ ║
║ │ │ articles) │ │ [Approve] [Edit] [Reject] │ │ ║
║ │ └──────────────┘ └──────────────────────────────────┘ │ ║
║ └────────────────────────────────────────────────────────────────────────┘ ║
╚════════════════════════════════════════════════════════════════════════════════╝Key Highlights
Hybrid Search (Vector + SQL + FTS)
Intelligent query routing: structured queries go to SQL, semantic to ChromaDB vectors, keyword to FTS5. Complex queries use Reciprocal Rank Fusion to merge results.
MCP + REST Dual Interface
MCP interface for LLM agents (Claude Code, Windsurf, NemoClaw sandboxes). REST API (FastAPI) for the Next.js Dashboard, Typer CLI, and Approver App.
Intake Pipeline with LLM Classification
Every input passes through Gemini Flash for significance check, type classification, entity extraction (people, dates, places), and automatic relation linking.
Specialized Agent Orchestra
Orchestrator decomposes requests into parallel/sequential agent calls: Memory, Calendar, Tasks, People, Media, Profile, Resource — extensible without touching existing agents.
NemoClaw Secure Runtime
Ephemeral Docker sandboxes destroyed after each invocation. RBAC policies determine auto-approve vs human-in-the-loop. Guardrails block prompt injection and data leaks.
Multi-LLM Router (litellm)
Task-based model routing: Claude Sonnet for orchestration, Gemini Flash for classification (10–20x cheaper), OpenAI for embeddings. Configurable per agent.
Data Flow: Natural Language Ingest
User sends a message via Telegram — Synapse automatically classifies, extracts entities, creates calendar events, and links people. Zero manual effort.
Telegram: "поехать с Эммой в аэропорт в 7 утра"
│
▼
NemoClaw Gateway (webhook receiver)
│
▼
OpenShell Guardrails ──→ [PASS] не prompt injection
│
▼
RBAC check ──→ [PASS] "ingest" action = auto-approve
│
▼
Ephemeral Sandbox (Docker container)
│
├── Agent (Claude SDK) receives message
│ │
│ ├── MCP call: synapse_ingest("поехать с Эммой в аэропорт в 7 утра")
│ │ │
│ │ ▼
│ │ SYNAPSE: Intake Pipeline
│ │ │
│ │ ├── Gemini Flash classifies → {type: "event", significant: true}
│ │ ├── Entity extraction → people: ["Эмма"], places: ["аэропорт"], time: "07:00"
│ │ ├── Orchestrator → calendar_agent.create_event + people_agent.ensure_person
│ │ ├── SQL INSERT into events table
│ │ ├── ChromaDB upsert embedding
│ │ └── Return: {id: 42, type: "event", title: "Поездка в аэропорт с Эммой"}
│ │
│ └── Agent formats response
│
▼
Telegram: "Записал: поездка в аэропорт с Эммой в 7:00"
│
▼
Container destroyed (ephemeral)Data Flow: Human-in-the-Loop Approval
Destructive actions (posting reviews, sending messages) require explicit human approval through the Approver App. The sandbox is destroyed after plan generation, then a new write-enabled sandbox is created only after approval.
Bitbucket PR created (webhook)
│
▼
NemoClaw Gateway ──→ OpenShell Guardrails ──→ [PASS]
│
▼
RBAC check ──→ [REQUIRES APPROVAL] "review_pr" = require_approve
│
▼
Ephemeral Sandbox (read-only)
│
├── Agent reads PR diff, generates review plan (JSON):
│ {
│ "action": "post_review_comment",
│ "target": "PR #21805",
│ "comment": "Найдена проблема с дубликатами в clientdx..."
│ }
│
▼
Container destroyed. Plan returned to Gateway.
│
▼
Gateway ──→ SUSPENDED STATE
│
├── Push notification to Approver App (Dashboard /approver)
│ │
│ ▼
│ User sees: "NemoClaw wants to post review on PR #21805"
│ [View Plan] [Approve] [Edit] [Reject]
│ │
│ ▼
│ User clicks [Approve]
│
▼
Gateway resumes ──→ NEW Sandbox with write API keys injected
│
├── Agent posts review comment to Bitbucket
├── MCP call: synapse_ingest("Reviewed PR #21805: clientdx duplicate issue")
│ └── Synapse stores in memory for future context
│
▼
Container destroyed. Done.Data Flow: Dashboard Query
The Next.js dashboard connects directly to Synapse REST API. Tables, timeline, search — all rendered server-side with real-time WebSocket updates.
Browser: /movies
│
▼
Next.js SSR / Client
│
▼
GET http://localhost:7777/entities/media?sort=rating&order=desc
│
▼
SYNAPSE REST API
│
├── SQL: SELECT * FROM media_items JOIN entries ON ... ORDER BY rating DESC
│
└── Return JSON → Next.js renders DataTable (shadcn)
│
▼
┌──────────────────────────────────────────────────────┐
│ Title │ Year │ Rating │ Genre │ Status │
├──────────────┼──────┼────────┼──────────┼────────────┤
│ Inception │ 2010 │ 9 │ sci-fi │ watched │
│ Dune 2 │ 2024 │ 8 │ sci-fi │ watched │
│ Oppenheimer │ 2023 │ - │ drama │ want_watch │
└──────────────────────────────────────────────────────┘Dashboard Pages
Dashboard
Today's events, pending tasks, quick input widget, recent activity.
Timeline
Chronological entries filtered by type, date, tags.
Search
Hybrid semantic search across all types with RRF merge.
Movies
Sortable, filterable DataTable (shadcn) for media tracking.
Tasks
Drag-drop kanban: pending → in progress → done.
People
vis.js network graph + cards showing relation connections.