{"title":"Arquitectura de Synapse","slug":"architecture","category":"concepts","summary":"Cómo está construido Synapse — Fastify, PostgreSQL, FTS5, embeddings, servidor MCP.","audience":["human","llm"],"tags":["architecture","design","components"],"difficulty":"intermediate","updated":"2026-06-27","word_count":498,"read_minutes":2,"lang":"es","translated":true,"requested_lang":"es","content_markdown":"\n# Arquitectura de Synapse\n\nSynapse es una API de memoria multi-tenant construida sobre Fastify, PostgreSQL\ncon FTS5, y un servicio opcional de embeddings para búsqueda semántica.\n\n## Arquitectura de alto nivel\n\n```\n┌──────────────────────────────────────────────────────────┐\n│                       Clients                            │\n├──────────────┬──────────────┬──────────────┬─────────────┤\n│  LLM Agents  │  Web Browsers│  MCP Clients │  Webhooks   │\n│  (curl/SDK)  │  (humans)    │ (Claude/etc) │  (external) │\n└──────┬───────┴──────┬───────┴──────┬───────┴──────┬──────┘\n       │              │              │              │\n       └──────────────┴──────────────┴──────────────┘\n                              │\n                              ▼\n              ┌───────────────────────────────┐\n              │    Synapse API (Fastify)      │\n              │    port 12800                 │\n              │    - REST endpoints           │\n              │    - Auth (Mind Key / JWT)    │\n              │    - Rate limiting            │\n              │    - Static file serving      │\n              └───────────────┬───────────────┘\n                              │\n              ┌───────────────┼───────────────┐\n              ▼               ▼               ▼\n       ┌─────────────┐ ┌─────────────┐ ┌─────────────┐\n       │ PostgreSQL  │ │ Embeddings  │ │ MCP Server  │\n       │ + FTS5      │ │ Service     │ │ (separate)  │\n       │             │ │ (optional)  │ │ port 13100  │\n       │ - memories  │ │             │ │             │\n       │ - tasks     │ │ - generate  │ │ - 79 tools  │\n       │ - chat      │ │   embeddings│ │ - stdio/SSE │\n       │ - scripts   │ │             │ │ - WebSocket │\n       └─────────────┘ └─────────────┘ └─────────────┘\n```\n\n## Componentes principales\n\n### 1. Synapse API (Fastify)\n\nEl servidor HTTP principal. Gestiona:\n\n- Endpoints REST (`/memory`, `/chat`, `/mind/tasks`, etc.)\n- Autenticación (Mind Key para agentes, JWT para humanos)\n- Límites de frecuencia (solo auth con `?key=`)\n- Servido de archivos estáticos (interfaz web en `/human`, `/docs`, etc.)\n- Dispatch de webhooks\n\nConstruido con **Fastify 5** para rendimiento. Se ejecuta en el puerto 12800 en\nproducción.\n\n### 2. PostgreSQL con FTS5\n\nEl almacén de datos principal. Usa PostgreSQL con la extensión FTS5 para\nbúsqueda de texto completo.\n\n**Tablas principales:**\n\n| Tabla | Propósito |\n|-------|---------|\n| `users` | Cuentas de usuario |\n| `minds` | Ámbitos de mind (cada uno tiene un Mind Key) |\n| `memories` | Registros de memoria con tabla virtual FTS5 |\n| `tasks` | Gestión de tareas |\n| `chat_messages` | Historial de chat |\n| `scripts` | Scripts persistentes |\n| `webhooks` | Registros de webhooks |\n| `cron_jobs` | Tareas programadas |\n| `variables` | Almacén clave-valor |\n| `audit_log` | Pista de auditoría |\n\n**FTS5** permite búsqueda de texto completo sub-milisegundo sobre todo el\ncontenido de memoria. Consulte [Búsqueda FTS5](/docs/concepts/fts5-search) para\nmás detalles.\n\n### 3. Servicio de Embeddings (opcional)\n\nPara búsqueda semántica, Synapse genera embeddings vectoriales del contenido de\nmemoria. Se almacenan junto a las memorias y se usan para búsqueda por similitud.\n\n- Proveedor: configurable (OpenAI, modelo local, etc.)\n- Se almacenan como columna `vector` en la tabla `memories`\n- Los usa el endpoint `/memory/semantic-search`\n- Consulte [Búsqueda semántica](/docs/concepts/semantic-search)\n\n### 4. Servidor MCP (servicio separado)\n\nEl servidor MCP de Synapse se ejecuta como un proceso aparte (puerto 13100).\nEsta persona:\n\n- Expone 79 herramientas vía Model Context Protocol\n- Admite transportes stdio, HTTP/SSE y WebSocket\n- Traduce llamadas a herramientas MCP en llamadas a la API de Synapse\n- Multi-tenant: un Mind Key por sesión\n\n### 5. Browser Proxy (servicio separado)\n\nPara automatización de navegador, un servicio separado basado en Playwright se\nejecuta en el puerto 13000. El servidor MCP puede invocarlo para las\nherramientas `browser_*`.\n\n### 6. SSH Proxy (servicio separado)\n\nPara comandos remotos basados en SSH, un servicio separado se ejecuta en el\npuerto 12900.\n\n## Modelo multi-tenant\n\n```\nUser Account (email + password)\n  │\n  ├── Mind 1 (Mind Key 1)\n  │   ├── Memories\n  │   ├── Tasks\n  │   ├── Chat\n  │   └── Scripts\n  │\n  ├── Mind 2 (Mind Key 2)\n  │   └── ... (isolated from Mind 1)\n  │\n  └── Mind 3 (Mind Key 3)\n      └── ...\n```\n\nCada mind está completamente aislado. Los Mind Keys otorgan acceso a\nexactamente un mind. Los JWT otorgan acceso a la cuenta de usuario (para\ngestionar minds).\n\nConsulte [Multi-Tenancy](/docs/concepts/multi-tenancy) para más detalles.\n\n## Flujo de solicitudes\n\n### Solicitud de almacenamiento de memoria\n\n```\n1. Client sends POST /memory with Authorization: Bearer mk_xxx\n2. Fastify receives request\n3. Auth middleware validates Mind Key, attaches mind_id to request\n4. Memory route handler:\n   a. Validate JSON body (zod schema)\n   b. Insert into memories table\n   c. Update FTS5 index\n   d. (Async) Generate embedding if embeddings enabled\n   e. Trigger webhooks for memory.store event\n5. Return { id, status: \"stored\" }\n```\n\n### Solicitud de búsqueda de memoria\n\n```\n1. Client sends GET /memory/search?q=docker\n2. Auth middleware validates Mind Key\n3. Memory route handler:\n   a. Parse query (FTS5 syntax)\n   b. Execute FTS5 MATCH against memories table\n   c. Filter by mind_id (tenant isolation)\n   d. Rank by relevance\n   e. Return results\n```\n\n## Despliegue\n\nSynapse se despliega como un contenedor Docker. Consulte `docker-compose.yml`:\n\n```yaml\nservices:\n  synapse:\n    image: registry.gitlab.com/schaefer-services/synapse:latest\n    ports:\n      - \"12800:12800\"\n    environment:\n      - DATABASE_URL=postgres://...\n      - JWT_SECRET=...\n      - SYNAPSE_HOST=0.0.0.0\n      - SYNAPSE_PORT=12800\n    depends_on:\n      - postgres\n  \n  postgres:\n    image: postgres:16\n    volumes:\n      - pgdata:/var/lib/postgresql/data\n    environment:\n      - POSTGRES_DB=synapse\n      - POSTGRES_PASSWORD=...\n```\n\n## Características de rendimiento\n\n| Operación | Latencia | Throughput |\n|-----------|---------|------------|\n| Memory store | ~5ms | 1000+ req/s |\n| Memory recall | ~20ms | 500 req/s |\n| FTS5 search | ~10ms | 800 req/s |\n| Semantic search | ~50ms | 200 req/s |\n| Chat poll | ~5ms | 2000 req/s |\n\n## Próximos pasos\n\n- [Modelo de memoria](/docs/concepts/memory-model)\n- [Multi-Tenancy](/docs/concepts/multi-tenancy)\n- [Búsqueda FTS5](/docs/concepts/fts5-search)\n","content_html":"<h1>Arquitectura de Synapse</h1>\n<p>Synapse es una API de memoria multi-tenant construida sobre Fastify, PostgreSQL\ncon FTS5, y un servicio opcional de embeddings para búsqueda semántica.</p>\n<h2>Arquitectura de alto nivel</h2>\n<pre><code class=\"hljs language-plaintext\">┌──────────────────────────────────────────────────────────┐\n│                       Clients                            │\n├──────────────┬──────────────┬──────────────┬─────────────┤\n│  LLM Agents  │  Web Browsers│  MCP Clients │  Webhooks   │\n│  (curl/SDK)  │  (humans)    │ (Claude/etc) │  (external) │\n└──────┬───────┴──────┬───────┴──────┬───────┴──────┬──────┘\n       │              │              │              │\n       └──────────────┴──────────────┴──────────────┘\n                              │\n                              ▼\n              ┌───────────────────────────────┐\n              │    Synapse API (Fastify)      │\n              │    port 12800                 │\n              │    - REST endpoints           │\n              │    - Auth (Mind Key / JWT)    │\n              │    - Rate limiting            │\n              │    - Static file serving      │\n              └───────────────┬───────────────┘\n                              │\n              ┌───────────────┼───────────────┐\n              ▼               ▼               ▼\n       ┌─────────────┐ ┌─────────────┐ ┌─────────────┐\n       │ PostgreSQL  │ │ Embeddings  │ │ MCP Server  │\n       │ + FTS5      │ │ Service     │ │ (separate)  │\n       │             │ │ (optional)  │ │ port 13100  │\n       │ - memories  │ │             │ │             │\n       │ - tasks     │ │ - generate  │ │ - 79 tools  │\n       │ - chat      │ │   embeddings│ │ - stdio/SSE │\n       │ - scripts   │ │             │ │ - WebSocket │\n       └─────────────┘ └─────────────┘ └─────────────┘</code></pre><h2>Componentes principales</h2>\n<h3>1. Synapse API (Fastify)</h3>\n<p>El servidor HTTP principal. Gestiona:</p>\n<ul>\n<li>Endpoints REST (<code>/memory</code>, <code>/chat</code>, <code>/mind/tasks</code>, etc.)</li>\n<li>Autenticación (Mind Key para agentes, JWT para humanos)</li>\n<li>Límites de frecuencia (solo auth con <code>?key=</code>)</li>\n<li>Servido de archivos estáticos (interfaz web en <code>/human</code>, <code>/docs</code>, etc.)</li>\n<li>Dispatch de webhooks</li>\n</ul>\n<p>Construido con <strong>Fastify 5</strong> para rendimiento. Se ejecuta en el puerto 12800 en\nproducción.</p>\n<h3>2. PostgreSQL con FTS5</h3>\n<p>El almacén de datos principal. Usa PostgreSQL con la extensión FTS5 para\nbúsqueda de texto completo.</p>\n<p><strong>Tablas principales:</strong></p>\n<table>\n<thead>\n<tr>\n<th>Tabla</th>\n<th>Propósito</th>\n</tr>\n</thead>\n<tbody><tr>\n<td><code>users</code></td>\n<td>Cuentas de usuario</td>\n</tr>\n<tr>\n<td><code>minds</code></td>\n<td>Ámbitos de mind (cada uno tiene un Mind Key)</td>\n</tr>\n<tr>\n<td><code>memories</code></td>\n<td>Registros de memoria con tabla virtual FTS5</td>\n</tr>\n<tr>\n<td><code>tasks</code></td>\n<td>Gestión de tareas</td>\n</tr>\n<tr>\n<td><code>chat_messages</code></td>\n<td>Historial de chat</td>\n</tr>\n<tr>\n<td><code>scripts</code></td>\n<td>Scripts persistentes</td>\n</tr>\n<tr>\n<td><code>webhooks</code></td>\n<td>Registros de webhooks</td>\n</tr>\n<tr>\n<td><code>cron_jobs</code></td>\n<td>Tareas programadas</td>\n</tr>\n<tr>\n<td><code>variables</code></td>\n<td>Almacén clave-valor</td>\n</tr>\n<tr>\n<td><code>audit_log</code></td>\n<td>Pista de auditoría</td>\n</tr>\n</tbody></table>\n<p><strong>FTS5</strong> permite búsqueda de texto completo sub-milisegundo sobre todo el\ncontenido de memoria. Consulte <a href=\"/docs/concepts/fts5-search\">Búsqueda FTS5</a> para\nmás detalles.</p>\n<h3>3. Servicio de Embeddings (opcional)</h3>\n<p>Para búsqueda semántica, Synapse genera embeddings vectoriales del contenido de\nmemoria. Se almacenan junto a las memorias y se usan para búsqueda por similitud.</p>\n<ul>\n<li>Proveedor: configurable (OpenAI, modelo local, etc.)</li>\n<li>Se almacenan como columna <code>vector</code> en la tabla <code>memories</code></li>\n<li>Los usa el endpoint <code>/memory/semantic-search</code></li>\n<li>Consulte <a href=\"/docs/concepts/semantic-search\">Búsqueda semántica</a></li>\n</ul>\n<h3>4. Servidor MCP (servicio separado)</h3>\n<p>El servidor MCP de Synapse se ejecuta como un proceso aparte (puerto 13100).\nEsta persona:</p>\n<ul>\n<li>Expone 79 herramientas vía Model Context Protocol</li>\n<li>Admite transportes stdio, HTTP/SSE y WebSocket</li>\n<li>Traduce llamadas a herramientas MCP en llamadas a la API de Synapse</li>\n<li>Multi-tenant: un Mind Key por sesión</li>\n</ul>\n<h3>5. Browser Proxy (servicio separado)</h3>\n<p>Para automatización de navegador, un servicio separado basado en Playwright se\nejecuta en el puerto 13000. El servidor MCP puede invocarlo para las\nherramientas <code>browser_*</code>.</p>\n<h3>6. SSH Proxy (servicio separado)</h3>\n<p>Para comandos remotos basados en SSH, un servicio separado se ejecuta en el\npuerto 12900.</p>\n<h2>Modelo multi-tenant</h2>\n<pre><code class=\"hljs language-plaintext\">User Account (email + password)\n  │\n  ├── Mind 1 (Mind Key 1)\n  │   ├── Memories\n  │   ├── Tasks\n  │   ├── Chat\n  │   └── Scripts\n  │\n  ├── Mind 2 (Mind Key 2)\n  │   └── ... (isolated from Mind 1)\n  │\n  └── Mind 3 (Mind Key 3)\n      └── ...</code></pre><p>Cada mind está completamente aislado. Los Mind Keys otorgan acceso a\nexactamente un mind. Los JWT otorgan acceso a la cuenta de usuario (para\ngestionar minds).</p>\n<p>Consulte <a href=\"/docs/concepts/multi-tenancy\">Multi-Tenancy</a> para más detalles.</p>\n<h2>Flujo de solicitudes</h2>\n<h3>Solicitud de almacenamiento de memoria</h3>\n<pre><code class=\"hljs language-plaintext\">1. Client sends POST /memory with Authorization: Bearer mk_xxx\n2. Fastify receives request\n3. Auth middleware validates Mind Key, attaches mind_id to request\n4. Memory route handler:\n   a. Validate JSON body (zod schema)\n   b. Insert into memories table\n   c. Update FTS5 index\n   d. (Async) Generate embedding if embeddings enabled\n   e. Trigger webhooks for memory.store event\n5. Return { id, status: &quot;stored&quot; }</code></pre><h3>Solicitud de búsqueda de memoria</h3>\n<pre><code class=\"hljs language-plaintext\">1. Client sends GET /memory/search?q=docker\n2. Auth middleware validates Mind Key\n3. Memory route handler:\n   a. Parse query (FTS5 syntax)\n   b. Execute FTS5 MATCH against memories table\n   c. Filter by mind_id (tenant isolation)\n   d. Rank by relevance\n   e. Return results</code></pre><h2>Despliegue</h2>\n<p>Synapse se despliega como un contenedor Docker. Consulte <code>docker-compose.yml</code>:</p>\n<pre><code class=\"hljs language-yaml\"><span class=\"hljs-attr\">services:</span>\n  <span class=\"hljs-attr\">synapse:</span>\n    <span class=\"hljs-attr\">image:</span> <span class=\"hljs-string\">registry.gitlab.com/schaefer-services/synapse:latest</span>\n    <span class=\"hljs-attr\">ports:</span>\n      <span class=\"hljs-bullet\">-</span> <span class=\"hljs-string\">&quot;12800:12800&quot;</span>\n    <span class=\"hljs-attr\">environment:</span>\n      <span class=\"hljs-bullet\">-</span> <span class=\"hljs-string\">DATABASE_URL=postgres://...</span>\n      <span class=\"hljs-bullet\">-</span> <span class=\"hljs-string\">JWT_SECRET=...</span>\n      <span class=\"hljs-bullet\">-</span> <span class=\"hljs-string\">SYNAPSE_HOST=0.0.0.0</span>\n      <span class=\"hljs-bullet\">-</span> <span class=\"hljs-string\">SYNAPSE_PORT=12800</span>\n    <span class=\"hljs-attr\">depends_on:</span>\n      <span class=\"hljs-bullet\">-</span> <span class=\"hljs-string\">postgres</span>\n  \n  <span class=\"hljs-attr\">postgres:</span>\n    <span class=\"hljs-attr\">image:</span> <span class=\"hljs-string\">postgres:16</span>\n    <span class=\"hljs-attr\">volumes:</span>\n      <span class=\"hljs-bullet\">-</span> <span class=\"hljs-string\">pgdata:/var/lib/postgresql/data</span>\n    <span class=\"hljs-attr\">environment:</span>\n      <span class=\"hljs-bullet\">-</span> <span class=\"hljs-string\">POSTGRES_DB=synapse</span>\n      <span class=\"hljs-bullet\">-</span> <span class=\"hljs-string\">POSTGRES_PASSWORD=...</span></code></pre><h2>Características de rendimiento</h2>\n<table>\n<thead>\n<tr>\n<th>Operación</th>\n<th>Latencia</th>\n<th>Throughput</th>\n</tr>\n</thead>\n<tbody><tr>\n<td>Memory store</td>\n<td>~5ms</td>\n<td>1000+ req/s</td>\n</tr>\n<tr>\n<td>Memory recall</td>\n<td>~20ms</td>\n<td>500 req/s</td>\n</tr>\n<tr>\n<td>FTS5 search</td>\n<td>~10ms</td>\n<td>800 req/s</td>\n</tr>\n<tr>\n<td>Semantic search</td>\n<td>~50ms</td>\n<td>200 req/s</td>\n</tr>\n<tr>\n<td>Chat poll</td>\n<td>~5ms</td>\n<td>2000 req/s</td>\n</tr>\n</tbody></table>\n<h2>Próximos pasos</h2>\n<ul>\n<li><a href=\"/docs/concepts/memory-model\">Modelo de memoria</a></li>\n<li><a href=\"/docs/concepts/multi-tenancy\">Multi-Tenancy</a></li>\n<li><a href=\"/docs/concepts/fts5-search\">Búsqueda FTS5</a></li>\n</ul>\n","urls":{"html":"/docs/concepts/architecture","text":"/docs/concepts/architecture?format=text","json":"/docs/concepts/architecture?format=json","llm":"/docs/concepts/architecture?format=llm"},"translations_available":["en","zh","hi","es","fr","ar","pt","ru","ja","de","it","ko","nl","pl","tr","sv","vi","th","id","uk"]}