Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 13 additions & 7 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@
GRAPH_BACKEND=sqlite
# ENGRAMA_DB_PATH=~/.engrama/engrama.db # default; uncomment to override

# === Profile (used by `engrama init`) ===
ENGRAMA_PROFILE=developer
# === Profile ===
# The schema profile is selected with the `--profile` flag at init time
# (e.g. `engrama init --profile developer`), not via an env var.

# === Obsidian vault sync (optional) ===
# Required for engrama_sync_note / engrama_sync_vault /
Expand Down Expand Up @@ -46,11 +47,16 @@ OLLAMA_URL=http://localhost:11434
# OPENAI_BASE_URL=https://api.openai.com/v1
# OPENAI_API_KEY=

# === Hybrid search (DDR-003 Phase C) ===
# Alpha controls fulltext vs vector weight (0.0 = all fulltext, 1.0 = all vector)
HYBRID_ALPHA=0.6
# Beta is the graph topology boost weight
HYBRID_GRAPH_BETA=0.15
# === Hybrid search ranking (DDR-003 Phase C, Spec 002) ===
# Relevance base: rrf (default) or linear (legacy blend).
# ENGRAMA_FUSION_MODE=rrf
# RRF constant k — larger flattens the top-rank advantage.
# ENGRAMA_RRF_K=60
# Graph node-distance rerank stage (rrf mode) and its hop budget.
# ENGRAMA_GRAPH_RERANK=true
# ENGRAMA_GRAPH_HOPS=2
# One-flag revert to the legacy linear blend.
# ENGRAMA_RANKING_LEGACY=false


# ============================================================
Expand Down
4 changes: 2 additions & 2 deletions .github/ISSUE_TEMPLATE/bug.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ body:
label: Steps to reproduce
description: Minimal commands or code that trigger the bug. Smaller is better.
placeholder: |
1. `engrama init`
2. `engrama remember "..."`
1. `engrama init --profile developer`
2. `engrama search "..."`
3. Observed: ...
validations:
required: true
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ sensitive data. The full policy lives in
change the default password and enable TLS before any networked use.
- **Embedding providers.** Endpoints reached via `OPENAI_BASE_URL` should
use HTTPS unless they are on localhost or a trusted network. With
`EMBEDDING_PROVIDER=null` no text is sent anywhere; search degrades to
`EMBEDDING_PROVIDER=none` no text is sent anywhere; search degrades to
fulltext-only.
- **Tenant isolation.** Since 0.13.0 every node and relation is owned by an
`(org_id, user_id)` identity and reads are **fail-closed**. A single
Expand Down
15 changes: 10 additions & 5 deletions docs/architecture.es.md
Original file line number Diff line number Diff line change
Expand Up @@ -608,7 +608,7 @@ correspondiente. Toda la lógica de almacenamiento reside en
`*AsyncStore`; los handlers de herramientas MCP se encargan solo de
orquestación, validación, E/S del vault y formateo de respuestas.

Trece herramientas:
Catorce herramientas:

- `engrama_status` — introspección de solo lectura: ruta del vault,
backend, embedder, modo de búsqueda, versión y `admin_tools` (las
Expand Down Expand Up @@ -638,6 +638,9 @@ Trece herramientas:
- `engrama_approve_insight` — el humano aprueba o descarta un Insight
- `engrama_write_insight_to_vault` — añadir Insight aprobado a una nota
de Obsidian
- `engrama_gdpr_forget` — borrar permanentemente la memoria del propio
llamante (derecho de supresión RGPD); `mode='dry-run'` previsualiza,
`mode='apply'` elimina

### Forma de respuesta de `engrama_status`

Expand All @@ -647,7 +650,7 @@ agente puede hacer `if "path" in payload["vault"]:` de forma fiable.

```json
{
"version": "0.13.0",
"version": "0.15.0",
"backend": {
"name": "sqlite",
"ok": true,
Expand Down Expand Up @@ -726,16 +729,18 @@ genera módulos personalizados mediante una entrevista conversacional.
| `NEO4J_USERNAME` | `neo4j` | Nombre de usuario de Neo4j |
| `NEO4J_PASSWORD` | — | Contraseña de Neo4j (requerida cuando `GRAPH_BACKEND=neo4j`) |
| `NEO4J_DATABASE` | `neo4j` | Nombre de la base de datos Neo4j |
| `ENGRAMA_PROFILE` | `developer` | Nombre de perfil para la generación del esquema |
| `VAULT_PATH` | `~/Documents/vault` | Ruta raíz del vault de Obsidian |
| `EMBEDDING_PROVIDER` | `none` | `none`, `ollama` u `openai` |
| `EMBEDDING_MODEL` | `nomic-embed-text` | Nombre del modelo de embedding |
| `EMBEDDING_DIMENSIONS` | `768` | Tamaño del vector de embedding |
| `OPENAI_BASE_URL` | `https://api.openai.com/v1` | Endpoint OpenAI-compatible |
| `OPENAI_API_KEY` | — | Clave API (cuando sea necesaria) |
| `OLLAMA_URL` | `http://localhost:11434` | Endpoint de la API de Ollama (proveedor legacy) |
| `HYBRID_ALPHA` | `0.6` | Peso vectorial vs fulltext |
| `HYBRID_GRAPH_BETA` | `0.15` | Peso del boost por topología del grafo |
| `ENGRAMA_FUSION_MODE` | `rrf` | Base de relevancia: `rrf` (por defecto) o `linear` (mezcla legacy) |
| `ENGRAMA_RRF_K` | `60` | Constante `k` de RRF — mayor aplana la ventaja del primer rango |
| `ENGRAMA_GRAPH_RERANK` | `true` | Activa la etapa de rerank por distancia en el grafo (modo rrf) |
| `ENGRAMA_GRAPH_HOPS` | `2` | Saltos máximos para cohesión + distancia al ancla |
| `ENGRAMA_RANKING_LEGACY` | `false` | Revierte con un flag a la mezcla lineal legacy |
| `ENGRAMA_ORG_ID` | — | Org propietaria en standalone (Spec 001); sin fijar → identidad standalone derivada |
| `ENGRAMA_USER_ID` | — | Usuario propietario en standalone (Spec 001); sin fijar → identidad standalone derivada |
| `ENGRAMA_LOCAL_SUB` | — | Semilla de la identidad standalone derivada cuando org/user no están fijados |
Expand Down
14 changes: 9 additions & 5 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -592,7 +592,7 @@ Native MCP server built with FastMCP and the matching async store. All
storage logic lives in `*AsyncStore`; the MCP tool handlers handle
orchestration, validation, vault I/O, and response formatting only.

Thirteen tools:
Fourteen tools:

- `engrama_status` — read-only introspection: vault path, backend,
embedder, search mode, version, and `admin_tools` (the not-tenant-isolated
Expand All @@ -616,6 +616,8 @@ Thirteen tools:
- `engrama_surface_insights` — read pending Insights for agent presentation
- `engrama_approve_insight` — human approves or dismisses an Insight
- `engrama_write_insight_to_vault` — append approved Insight to Obsidian note
- `engrama_gdpr_forget` — permanently erase the caller's own memory
(GDPR right-to-erasure); `mode='dry-run'` previews, `mode='apply'` deletes

### `engrama_status` response shape

Expand All @@ -625,7 +627,7 @@ payload["vault"]:` reliably.

```json
{
"version": "0.13.0",
"version": "0.15.0",
"backend": {
"name": "sqlite",
"ok": true,
Expand Down Expand Up @@ -702,16 +704,18 @@ through a conversational interview.
| `NEO4J_USERNAME` | `neo4j` | Neo4j username |
| `NEO4J_PASSWORD` | — | Neo4j password (required when `GRAPH_BACKEND=neo4j`) |
| `NEO4J_DATABASE` | `neo4j` | Neo4j database name |
| `ENGRAMA_PROFILE` | `developer` | Profile name for schema generation |
| `VAULT_PATH` | `~/Documents/vault` | Obsidian vault root path |
| `EMBEDDING_PROVIDER` | `none` | `none`, `ollama`, or `openai` |
| `EMBEDDING_MODEL` | `nomic-embed-text` | Embedding model name |
| `EMBEDDING_DIMENSIONS` | `768` | Embedding vector size |
| `OPENAI_BASE_URL` | `https://api.openai.com/v1` | OpenAI-compat endpoint |
| `OPENAI_API_KEY` | — | API key (when needed) |
| `OLLAMA_URL` | `http://localhost:11434` | Ollama API endpoint (legacy provider) |
| `HYBRID_ALPHA` | `0.6` | Vector vs fulltext weight |
| `HYBRID_GRAPH_BETA` | `0.15` | Graph topology boost weight |
| `ENGRAMA_FUSION_MODE` | `rrf` | Relevance base: `rrf` (default) or `linear` (legacy blend) |
| `ENGRAMA_RRF_K` | `60` | RRF constant `k` — larger flattens the top-rank advantage |
| `ENGRAMA_GRAPH_RERANK` | `true` | Toggle the graph node-distance rerank stage (rrf mode) |
| `ENGRAMA_GRAPH_HOPS` | `2` | Max hops for cohesion + anchor distance |
| `ENGRAMA_RANKING_LEGACY` | `false` | One-flag revert to the legacy linear blend |
| `ENGRAMA_ORG_ID` | — | Standalone owning org (Spec 001); unset → derived standalone identity |
| `ENGRAMA_USER_ID` | — | Standalone owning user (Spec 001); unset → derived standalone identity |
| `ENGRAMA_LOCAL_SUB` | — | Seed for the derived standalone identity when org/user are unset |
Expand Down
8 changes: 3 additions & 5 deletions docs/backends.es.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,7 @@ En la práctica, la primera rama cubre ~90 % de los usuarios.
## Cuándo elegir SQLite

- **Estás empezando.** Cero fricción de instalación, sin Docker, sin JVM.
`git clone … && uv sync && uv run engrama init` y ya puedes consultar
el grafo (Engrama aún no está en PyPI; instalación desde fuente por
ahora).
`pip install engrama && engrama init` y ya puedes consultar el grafo.
- **Configuraciones de un solo agente.** Un Claude Desktop, un cliente
MCP, un script de larga ejecución. SQLite lo gestiona perfectamente.
- **Ejecuciones en CI y tests.** Sin servicios externos que levantar —
Expand Down Expand Up @@ -156,7 +154,7 @@ Los skills, el servidor MCP, la CLI y el SDK de Python están escritos
contra los protocolos — no saben qué backend hay debajo. Por eso el
cambio se reduce a una sola variable.

Consulta [architecture.md](architecture.md#capa-de-protocolo-y-backends)
Consulta [architecture.md](architecture.md#capa-de-protocolos-y-backends)
para el diagrama completo de capas, y [DDR-004](ddr-004.md) para la
justificación de diseño del backend portable.

Expand All @@ -170,7 +168,7 @@ Diferentes procesos pueden apuntar a backends distintos — útil para
pruebas o migraciones.

**¿SQLite soporta todas las características de Neo4j?**
Para la API pública de Engrama (las 12 herramientas MCP, el SDK, la
Para la API pública de Engrama (las 14 herramientas MCP, el SDK, la
CLI), sí — son funcionalmente equivalentes y se prueban con la misma
suite de tests de contrato parametrizados. Lo único que SQLite no puede
hacer es ejecutar patrones Cypher en crudo; en su lugar usa consultas
Expand Down
5 changes: 2 additions & 3 deletions docs/backends.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,7 @@ In practice the first branch covers ~90% of users.
## When to pick SQLite

- **You're getting started.** Zero install friction, no Docker, no JVM.
`git clone … && uv sync && uv run engrama init` and you're querying
the graph (Engrama is not yet on PyPI; install from source for now).
`pip install engrama && engrama init` and you're querying the graph.
- **Single-agent setups.** One Claude Desktop, one MCP client, one
long-running script. SQLite handles this perfectly.
- **CI runs and tests.** No external service to spin up — `pytest` works
Expand Down Expand Up @@ -164,7 +163,7 @@ You can, but a single Engrama process binds to one. Different processes
can target different backends — useful for testing or migrations.

**Does SQLite support all the features Neo4j has?**
For the public Engrama API (the 12 MCP tools, the SDK, the CLI), yes —
For the public Engrama API (the 14 MCP tools, the SDK, the CLI), yes —
they're feature-equivalent and exercised by the same parameterised
contract suite. The only thing SQLite cannot do is execute raw Cypher
patterns; it uses pre-translated SQL queries instead. If a future
Expand Down
4 changes: 2 additions & 2 deletions docs/ddr-003.es.md
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ VECTOR_BACKEND=neo4j # neo4j | chroma | pgvector | none

# Neo4j (when GRAPH_BACKEND=neo4j or VECTOR_BACKEND=neo4j)
NEO4J_URI=bolt://localhost:7687
NEO4J_USER=neo4j
NEO4J_USERNAME=neo4j
NEO4J_PASSWORD=changeme

# ChromaDB (when VECTOR_BACKEND=chroma)
Expand Down Expand Up @@ -748,7 +748,7 @@ VECTOR_BACKEND=neo4j

# === Neo4j ===
NEO4J_URI=bolt://localhost:7687
NEO4J_USER=neo4j
NEO4J_USERNAME=neo4j
NEO4J_PASSWORD=CHANGE_ME_BEFORE_FIRST_RUN

# === Embeddings ===
Expand Down
4 changes: 2 additions & 2 deletions docs/ddr-003.md
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ VECTOR_BACKEND=neo4j # neo4j | chroma | pgvector | none

# Neo4j (when GRAPH_BACKEND=neo4j or VECTOR_BACKEND=neo4j)
NEO4J_URI=bolt://localhost:7687
NEO4J_USER=neo4j
NEO4J_USERNAME=neo4j
NEO4J_PASSWORD=changeme

# ChromaDB (when VECTOR_BACKEND=chroma)
Expand Down Expand Up @@ -733,7 +733,7 @@ VECTOR_BACKEND=neo4j

# === Neo4j ===
NEO4J_URI=bolt://localhost:7687
NEO4J_USER=neo4j
NEO4J_USERNAME=neo4j
NEO4J_PASSWORD=CHANGE_ME_BEFORE_FIRST_RUN

# === Embeddings ===
Expand Down
8 changes: 3 additions & 5 deletions docs/index.es.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@ conocimiento acumulado.
Hay dos backends de primera clase:

- **SQLite + `sqlite-vec`** (por defecto desde la 0.9) — un único
archivo, sin servicios externos, `git clone` + `uv sync` y a
correr (Engrama aún no está en PyPI; instalación desde fuente).
archivo, sin servicios externos, `pip install engrama` y a correr.
- **Neo4j 5.26 LTS** (opcional) — para producción multiproceso, índices
vectoriales muy grandes o equipos que ya usan Cypher.

Expand Down Expand Up @@ -541,7 +540,7 @@ coincidencia exacta de palabras clave.

**Cómo activar la búsqueda híbrida:**
1. Establece `EMBEDDING_PROVIDER` en `.env` (ver
[Configuración de embeddings](#configuración-de-embeddings-opcional)).
[Configuración de embeddings](#configuracion-de-embeddings-opcional)).
2. Ejecuta `uv run engrama reindex` para generar embeddings de nodos
existentes.
3. Los nodos nuevos reciben embeddings automáticamente al crearse.
Expand Down Expand Up @@ -570,7 +569,7 @@ Valores por defecto: `β` (grafo) = 0.15, `γ` (temporal) = 0.1, RRF `k` =
60, saltos de grafo = 2, decaimiento de cohesión = 0.5. La mezcla lineal
heredada (con el `graph_boost` por grado) se conserva para revertir con
un solo flag vía `ENGRAMA_RANKING_LEGACY=1`. Consulta la [referencia de
configuración](#referencia-de-configuración) para todos los knobs.
configuración](#referencia-de-configuracion) para todos los knobs.

---

Expand Down Expand Up @@ -699,7 +698,6 @@ freelance.
| `NEO4J_USERNAME` | `neo4j` | Usuario Neo4j |
| `NEO4J_PASSWORD` | — | Contraseña Neo4j (requerida con `GRAPH_BACKEND=neo4j`) |
| `NEO4J_DATABASE` | `neo4j` | Nombre de base de datos Neo4j |
| `ENGRAMA_PROFILE` | `developer` | Perfil para generar el esquema |
| `VAULT_PATH` | `~/Documents/vault` | Raíz del vault de Obsidian |
| `EMBEDDING_PROVIDER` | `none` | `none`, `ollama` u `openai` |
| `EMBEDDING_MODEL` | `nomic-embed-text` | Nombre del modelo |
Expand Down
46 changes: 42 additions & 4 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ Expected output: `backend=sqlite, ok=true, ...`

Three ways:

**A) From Claude Desktop** — see [MCP integration](#mcp-integration-claude-desktop) below.
**A) From Claude Desktop or Codex** — see [MCP integration](#mcp-integration) below.

**B) From Python:**

Expand Down Expand Up @@ -356,12 +356,14 @@ context. For shorter inputs and tighter latency, use

---

## MCP integration (Claude Desktop)
## MCP integration

Engrama acts as an abstraction layer between the AI agent and the
storage backend. Claude Desktop connects to the Engrama MCP server — it
storage backend. The MCP client connects to the Engrama MCP server — it
never sees database credentials, connection strings, or raw queries.

### Claude Desktop

**1. Find your Claude Desktop config file:**

- **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
Expand Down Expand Up @@ -403,6 +405,43 @@ the server reads them from `.env` when running against Neo4j.

**3. Restart Claude Desktop** completely (quit and reopen).

### Codex

Codex supports local MCP servers over `stdio`, so you can register
Engrama straight from the CLI:

```bash
codex mcp add engrama -- uv run --directory C:\Proyectos\engrama --extra mcp engrama-mcp --backend sqlite
```

For Neo4j, swap `--backend sqlite` for `--backend neo4j` and add the
extra too:

```bash
codex mcp add engrama -- uv run --directory C:\Proyectos\engrama --extra mcp --extra neo4j engrama-mcp --backend neo4j
```

Then confirm it registered:

```bash
codex mcp list
```

As with Claude Desktop, change `C:\Proyectos\engrama` to the actual path
where you cloned the repo.

### ChatGPT Desktop

ChatGPT does **not** use this local `stdio` configuration directly.
OpenAI's current docs describe ChatGPT's custom MCP connectors as
**remote** MCP servers imported from `Settings -> Connectors`, over
HTTP/SSE rather than a local command.

That means `engrama-mcp` fits Claude Desktop and Codex well, but **not
yet** as a direct ChatGPT Desktop integration. To use Engrama from
ChatGPT you would expose a remote MCP endpoint and package it as a
custom ChatGPT connector.

You should now see the fourteen Engrama tools:

| Tool | Description |
Expand Down Expand Up @@ -733,7 +772,6 @@ creative.
| `NEO4J_USERNAME` | `neo4j` | Neo4j user |
| `NEO4J_PASSWORD` | — | Neo4j password (required when `GRAPH_BACKEND=neo4j`) |
| `NEO4J_DATABASE` | `neo4j` | Neo4j database name |
| `ENGRAMA_PROFILE` | `developer` | Profile for schema generation |
| `VAULT_PATH` | `~/Documents/vault` | Obsidian vault root path |
| `EMBEDDING_PROVIDER` | `none` | `none`, `ollama`, or `openai` |
| `EMBEDDING_MODEL` | `nomic-embed-text` | Model name |
Expand Down
2 changes: 1 addition & 1 deletion docs/roadmap.es.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
> Objetivo: usar el grafo desde Claude Desktop vía MCP sin escribir Cypher manualmente.

- [x] `engrama/adapters/mcp/server.py` — servidor MCP nativo vía FastMCP + driver asíncrono de Neo4j
- [x] Diez herramientas MCP: search, remember, relate, context, sync_note, sync_vault, reflect, surface_insights, approve_insight, write_insight_to_vault (el conjunto ha crecido desde entonces a doce — `engrama_ingest` llegó en la Fase 9 y `engrama_status` en #52; véase architecture.md para la lista actual)
- [x] Diez herramientas MCP: search, remember, relate, context, sync_note, sync_vault, reflect, surface_insights, approve_insight, write_insight_to_vault (el conjunto ha crecido desde entonces a catorce — `engrama_ingest` llegó en la Fase 9, `engrama_status` en #52, y `engrama_reindex` / `engrama_gdpr_forget` después; véase architecture.md para la lista actual)
- [x] `examples/claude_desktop/config.json` — configuración lista para copiar y pegar
- [x] `examples/claude_desktop/system-prompt.md` — system prompt de memoria
- [ ] Test extremo a extremo: Claude Desktop → MCP → Neo4j → respuesta (verificación manual hecha, test automatizado pendiente)
Expand Down
2 changes: 1 addition & 1 deletion docs/roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
> Goal: use the graph from Claude Desktop via MCP without writing Cypher manually.

- [x] `engrama/adapters/mcp/server.py` — native MCP server via FastMCP + async Neo4j driver
- [x] Ten MCP tools: search, remember, relate, context, sync_note, sync_vault, reflect, surface_insights, approve_insight, write_insight_to_vault (the set has since grown to twelve — `engrama_ingest` landed in Phase 9 and `engrama_status` in #52; see architecture.md for the current list)
- [x] Ten MCP tools: search, remember, relate, context, sync_note, sync_vault, reflect, surface_insights, approve_insight, write_insight_to_vault (the set has since grown to fourteen — `engrama_ingest` landed in Phase 9, `engrama_status` in #52, and `engrama_reindex` / `engrama_gdpr_forget` later; see architecture.md for the current list)
- [x] `examples/claude_desktop/config.json` — ready-to-paste config
- [x] `examples/claude_desktop/system-prompt.md` — memory system prompt
- [ ] End-to-end test: Claude Desktop → MCP → Neo4j → response (manual verification done, automated test pending)
Expand Down
2 changes: 1 addition & 1 deletion docs/vision.es.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Karpathy construyó su segundo cerebro en Markdown y wikis — eso funciona para

**Engrama** es un framework Python plug-and-play que proporciona a cualquier agente de IA una memoria persistente y estructurada respaldada por un grafo de conocimiento. El agente puede recordar, asociar, olvidar y razonar sobre el conocimiento acumulado — exactamente como lo haría un humano con buena memoria.

El grafo funciona sobre **SQLite + sqlite-vec** (por defecto desde la 0.9 — un único archivo, sin servicios externos, `git clone` + `uv sync` y a correr; Engrama aún no está en PyPI) o **Neo4j 5.26 LTS** (opcional para producción multiproceso, índices vectoriales grandes o equipos que ya usan Cypher). Ambos exponen el mismo modelo de datos y las mismas doce herramientas MCP — consulta [backends.md](backends.md) para la guía de elección.
El grafo funciona sobre **SQLite + sqlite-vec** (por defecto desde la 0.9 — un único archivo, sin servicios externos, `pip install engrama` y a correr) o **Neo4j 5.26 LTS** (opcional para producción multiproceso, índices vectoriales grandes o equipos que ya usan Cypher). Ambos exponen el mismo modelo de datos y las mismas catorce herramientas MCP — consulta [backends.md](backends.md) para la guía de elección.

## Qué lo diferencia

Expand Down
Loading
Loading