NoteFlow · IA por dentro

Dentro
del cerebro.

Embeddings locales, un grafo semántico, recuperación híbrida y un agente nativo — cada prompt y cada umbral documentados, directos del código.

01 / providers

Trae tu propio modelo

NoteFlow no incluye ningún modelo — conectas tu proveedor, y con tu propia key o un Ollama local nada pasa por servidores de NoteFlow (solo la suscripción gestionada opcional NoteFlow AI usa el proxy de NoteFlow). Dos implementaciones lo cubren todo: Anthropic mediante el SDK oficial, y un cliente OpenAI-compatible (streaming de /chat/completions) que habla con todos los demás, desde la propia OpenAI hasta un Ollama local.

Cada preset guarda su propia API key, modelo y base URL, así que cambiar de proveedor nunca mezcla credenciales. La base URL es editable en todos los presets salvo Anthropic — apúntala a un endpoint regional o a un gateway autoalojado.

Anthropic (Claude)

SDK oficial

Integración nativa vía @anthropic-ai/sdk. El único preset que acepta adjuntos PDF; endpoint fijo.

API keyimágenesPDF

OpenAI

api.openai.com/v1

La familia GPT sobre la API estándar de chat-completions.

API keyimágenes

DeepSeek

api.deepseek.com/v1

deepseek-chat / deepseek-reasoner. Solo texto — la API rechaza la entrada de imágenes.

API keysolo texto

MiniMax

api.minimax.io/v1

MiniMax-Text-01. Edita la base URL para usar el endpoint de China. Solo texto.

API keysolo texto

Moonshot (Kimi)

api.moonshot.ai/v1

Kimi K2 y los modelos moonshot-v1. Solo texto.

API keysolo texto

OpenRouter

openrouter.ai/api/v1

Una key, cientos de modelos — elige cualquier id de modelo en el selector.

API keyimágenes

OpenCode Zen

opencode.ai/zen/go/v1

El gateway de OpenCode, totalmente OpenAI-compatible.

API keyimágenes

Ollama (local)

localhost:11434/v1

Inferencia 100% local — sin key, sin cuenta, nada sale nunca de tu máquina.

sin keylocalimágenes

Custom (OpenAI-compatible)

tu base URL

Cualquier servidor OpenAI-compatible: LM Studio, vLLM, llama.cpp, un gateway corporativo…

key opcionalimágenes

El soporte de adjuntos sigue al preset, porque la visión depende en realidad del modelo: la entrada de imágenes viene activada por defecto en los proveedores con visión o flexibles de modelo, y desactivada en los de solo texto (DeepSeek, MiniMax, Moonshot — sus APIs rechazan image_url con un HTTP 400). Los adjuntos PDF son exclusivos de Anthropic. Los archivos de texto y código se incrustan como texto plano y funcionan con cualquier proveedor.

02 / embeddings

Un índice semántico local

Todo lo que el cerebro sabe empieza en un índice 100% local y offline. NoteFlow embebe tus notas con Transformers.js sobre el onnxruntime nativo — en un proceso utilitario aparte, para que la app nunca se bloquee — usando Xenova/paraphrase-multilingual-mpnet-base-v2: un modelo multilingüe que produce vectores de 768 dimensiones, descargado una sola vez al activarlo (la IA local viene apagada por defecto).

La unidad de significado es la sección, no la nota: cada sección de cada nota se convierte en su propio embedding, guardado en una base SQLite con sqlite-vec para los vectores y FTS5 para el texto completo.

  • Antes de embeber, cada sección se limpia: se eliminan las imágenes base64 y el texto se trunca a ~2.000 caracteres (≈ 512 tokens — el modelo ignora todo lo que pase de ahí de todos modos).
  • El indexado es incremental: un hash de contenido por sección salta lo que no cambió, y las ediciones se reindexan unos 2,5 s después de dejar de escribir.
  • Las notas cifradas nunca se indexan — nada de su texto plano entra jamás en la base de datos.
  • La base de datos vive en la carpeta de datos de la app, fuera del directorio de notas — nunca se commitea ni se sincroniza a GitHub.
  • El índice es un artefacto desechable: bórralo y se reconstruye solo desde el markdown en disco.
03 / relations

Cómo se conectan las notas en el cerebro

La similitud cruda entre embeddings engaña: los vectores de frases se apiñan en un cono estrecho (anisotropía), así que todo se parece vagamente a todo. NoteFlow primero centra cada vector sobre la media global de tus propias notas y después compara con coseno — lo que sobrevive es la parte del significado que hace a una nota distinta de tu nota media.

Notas relacionadas — por sección

Para la sección que estás editando, su vector centrado se compara contra todas las demás secciones. De cada otra nota solo sobrevive la sección que mejor casa, y solo por encima de una similitud post-centrado de 0,03 — un listón deliberadamente estricto que mantiene el panel “Related” temático en vez de parlanchín.

Grafo de contenido — nota ↔ nota

Para la vista cerebro, cada nota se colapsa al centroide de los vectores de sus secciones, centrado y normalizado igual. Cada pareja de notas por encima de 0,05 se convierte en arista candidata, y luego las aristas se podan al top 6 de cada nota (se conservan si cualquiera de los dos extremos las clasifica) para que las notas-hub no se conviertan en bolas de pelo.

El grafo que ves tiene dos capas: la capa de estructura (grupo → carpeta → nota, dibujada de cómo organizas de verdad) y esta capa de contenido (aristas semánticas). Un índice, la misma matemática — y la recuperación del chat de abajo reutiliza ambas.

04 / rag

Solo las notas relevantes llegan al modelo

Cuando le preguntas algo al chat, tu cuaderno no se pega entero en el prompt. Un pipeline de recuperación elige las pocas secciones que importan:

  1. 01

    Búsqueda híbrida

    La pregunta se embebe en local y se lanza contra ambos índices — similitud vectorial y coincidencia de palabras clave FTS5 — y los dos rankings se fusionan con Reciprocal Rank Fusion (RRF, k = 60). Sobreviven los 6 mejores resultados por nota.

  2. 02

    Expansión por el grafo

    Se suman hasta 3 vecinas conectadas a esos resultados por aristas de contenido — notas que no mencionaste, pero que el grafo sabe que van de lo mismo.

  3. 03

    Frescas del disco

    Las secciones encontradas se releen del markdown en disco (nunca del índice), con un tope de 1.500 caracteres por bloque.

  4. 04

    Un solo system prompt

    Los bloques se añaden como contexto al system prompt del chat y la respuesta llega en streaming. Solo tu pregunta y estos fragmentos recuperados salen de tu máquina.

El chat emite sus fuentes antes de que llegue el primer token, y las notas citadas literalmente se encienden en la vista cerebro — puedes ver de dónde sale cada respuesta.

Tu nota de perfil (siguiente sección) se inyecta como trasfondo invisible en cada pregunta, sea o no relevante semánticamente — pero nunca se cita como fuente ni se ilumina.

El system prompt literal del chat

Verbatim del código (CHAT_SYSTEM_BASE, electron/main.ts), en inglés porque es la cadena real que se envía. El contexto recuperado y el bloque de perfil se añaden debajo.

You are NoteFlow's assistant — a second brain over the user's personal notes. Answer directly and concisely, in the same language the user writes in. When context from the notes is provided, ground your answer in it and avoid inventing facts; if the notes don't contain the answer, say so plainly.

You can also ACT on the notes through the provided tools (create/edit/organize/delete notes, sections, groups and folders). Only act when the user clearly asks you to; otherwise just answer. Never invent ids — call list_notes / list_groups (or search_notes) first to discover the real ids you need. Ids are stable and never change, so if a tool reports a note/section as not found, the id is stale or mistyped: do not retry it verbatim — re-run list_notes and use the freshly returned id. When acting on several notes, fetch their ids right before you act on them (especially after creating, moving or renaming anything) and copy each id exactly. After acting, briefly tell the user what you did. Deletions require user confirmation, which the app handles automatically.

When the context includes the user's profile or personality notes (including any "soft signals" / raw favourites), use them only as BACKGROUND to tailor your tone and suggestions. Never cite where a preference comes from or name-drop the user's favourite song/film/book in an unrelated answer (do not say "since you like X…"). Make recommendations directly.

NEXT-ACTION SUGGESTIONS. At the very end of your FINAL answer (never in an intermediate turn that still calls tools), if there are genuinely useful follow-ups, append the literal marker "<!--SUGGESTIONS-->" on its own line, then 1 or 2 short, actionable next things the user might want to ask, one per line prefixed with "- ". Phrase each as a brief imperative from the USER's point of view, in the same language as your answer. Keep each suggestion VERY short so it fits on a small button: aim for 2-5 words, 6 words maximum, no trailing period (e.g. "- Reorganize into sections", "- Add a summary"). Keep them concrete and grounded in this conversation. If nothing useful applies, omit the marker entirely. Never mention the marker or these suggestions in the visible part of your answer.
05 / profile

El perfil del segundo cerebro

La primera vez que entras al cerebro con un proveedor configurado, NoteFlow te ofrece un cuestionario corto en cuatro secciones — Professional, Personal, Your style y Working with the AI — y convierte tus respuestas en una nota de perfil que el asistente lee como trasfondo a partir de entonces.

Lo indirecto gana a lo directo. Preguntar “¿eres creativo?” da una mala respuesta; pedir música, cine y libros favoritos, un viaje soñado o binarias juguetonas de “esto o lo otro” da señal honesta. Las binarias están diseñadas para tap-ear las dimensiones del Big Five (OCEAN), y al modelo se le indica explícitamente que las trate como priors suaves — tendencias modestas y probabilísticas que solo cuajan cuando convergen varias pistas, nunca veredictos.

También puedes adjuntar un CV o cualquier PDF, imágenes y enlaces. Los documentos van a tu proveedor en nativo (bloques de documento/visión) — la app nunca los procesa en local. Los enlaces se descargan, se reducen a texto legible y se incluyen como contexto.

La nota generada te describe en rasgos y valores abstractos — lo que un favorito representa, nunca su título — para que el asistente no suelte tu película favorita en chats que no vienen a cuento. Los favoritos literales quedan en cuarentena en una sección final llamada “Soft signals (raw — do not cite)”, marcada como solo-trasfondo.

¿No te convence el resultado? Regenerar reutiliza la misma nota en vez de crear duplicados.

El prompt literal de generación del perfil

Verbatim del código (el handler ai:profile-generate, electron/main.ts), en inglés porque es la cadena real que se envía. ${locale} se sustituye por el idioma de tu app en tiempo de ejecución.

You are a perceptive profiler building a personal profile note for a "second brain" notes app. The note is later retrieved as BACKGROUND CONTEXT to tailor answers to this person, so its value is in capturing WHO THEY ARE, not in cataloguing trivia. The user may be anyone (not necessarily a developer). You are given short form answers (grouped by section), optional attached documents (CV/PDF/images) and text scraped from links. Write the profile in ${locale}.

INFER, DON'T JUST TRANSCRIBE. Many answers are intentionally INDIRECT proxies — favourite music/films/books, a dream trip, and playful "this or that" picks. Read them through validated personality psychology (the Big Five / OCEAN: openness, conscientiousness, extraversion, agreeableness, emotional stability) to infer likely TRAITS, VALUES, MOTIVATIONS and working/communication preferences. These signals are PROBABILISTIC and modest, so treat them as soft priors, never certainties: phrase inferences as tendencies ("tends to…", "likely values…", "seems energised by…"), and let multiple cues converge before you commit to a trait.

ABSTRACT AWAY THE SOURCE. The main body must describe the person in terms of traits, values and how they think and want to be treated — NOT by naming the specific media that produced the inference. Write what a favourite REPRESENTS, not its title: e.g. "drawn to introspective, character-driven stories and big-picture thinking" rather than "likes Interstellar". This keeps the assistant from awkwardly name-dropping a movie/song in unrelated conversations.

Cover BOTH professional and personal dimensions, and especially HOW they want the assistant to communicate with them (tone, length, level of detail) — capture this clearly so future answers can adapt. Stay faithful: do not invent hard specifics (names, employers, dates) that the inputs do not support.

STRUCTURE. Organize into a few clear sections; skip any with no information. Suggested: "About" (a tight summary), "How they think & what they value" (the inferred traits/values), "Communication style" (how the assistant should talk to them), "Work & focus", "Interests", and "Links" (the URLs provided). Then, ONLY if the user gave literal favourites (songs, films, books, etc.), add a FINAL section named exactly "Soft signals (raw — do not cite)" that lists them verbatim, opening with one line: "Raw references kept for background only — do not bring these up in unrelated conversations." Keep this section short and low-key.

Return ONLY a JSON object with this exact shape: {"title": string, "sections": [{"name": string, "content": string}]}. No text outside the JSON. "content" is Markdown.
06 / agent

Un agente sobre tus notas

El chat no solo habla de tus notas — puede actuar sobre ellas. Esto no es un envoltorio del CLI de NoteFlow: el modelo usa function calling nativo, y cada tool se ejecuta dentro del proceso principal de la app por los mismos caminos de código que usa la interfaz — mismas escrituras, misma sincronización con GitHub, mismo reindexado.

El bucle agéntico realimenta cada resultado de tool al modelo hasta que deja de llamar tools, con un tope duro de 12 pasos por turno. Las 17 tools están siempre disponibles — decide el modelo — pero las cuatro destructivas están vigiladas:

  • Las llamadas destructivas pausan el turno con una confirmación explícita en el chat que muestra el objetivo resuelto — el título real de la nota o el grupo, no un id opaco — para cazar un borrado equivocado antes de que ocurra.
  • Si rechazas, el agente no se aborta: la tool devuelve “user declined” y el modelo sigue con el resto de la tarea.
  • Los ids se auto-corrigen: cuando una tool reporta un id de nota caducado, el error lleva la lista viva id ↔ título, así que el modelo se corrige en el siguiente paso en vez de quedarse atascado.
  • Las notas cifradas aparecen en los listados, pero ninguna tool puede leer ni editar su contenido.
ToolQué hace
list_notes Lista las notas — id, título, tags, grupo/carpeta y nombres de sección. Así descubre el agente los ids reales antes de actuar.
get_note Lee una nota completa, incluyendo id, nombre y contenido de cada sección.
list_groups Lista todos los grupos y carpetas con sus ids.
search_notes Búsqueda semántica sobre las notas (requiere el índice local activado).
create_note Crea una nota — opcionalmente dentro de un grupo/carpeta, con secciones pre-rellenadas.
update_note Actualiza metadatos: título, flags de favorito/archivado, o mueve la nota entre grupo y carpeta.
add_section Añade una sección nueva a una nota existente.
update_section Reemplaza el contenido de una sección.
rename_section Renombra una sección.
create_group Crea un grupo (con color opcional).
create_folder Crea una carpeta dentro de un grupo.
rename_group Renombra un grupo.
rename_folder Renombra una carpeta.
delete_note destructiva Borra permanentemente una nota y todas sus secciones.
delete_section destructiva Borra una sección de una nota.
delete_group destructiva Borra un grupo y sus carpetas — las notas sobreviven, solo quedan sin grupo.
delete_folder destructiva Borra una carpeta — sus notas conservan el grupo.
07 / privacy

Lo que la IA nunca ve

Todas las superficies de IA — índice, recuperación, tools — respetan los mismos límites, aplicados en el proceso principal, no en la interfaz:

Secciones ocultas

Marca cualquier sección como “Hide from AI” y sale de todas las superficies de IA a la vez: no se indexa (y se borra del índice si ya lo estaba), nunca entra al contexto del chat — ni siquiera por la expansión de vecinas del grafo — y las tools del agente la omiten. El modelo ni siquiera ve su id de sección, así que no puede leerla ni editarla.

Notas cifradas

Fuera del índice, fuera de la recuperación y fuera de las lecturas de tools. Pueden aparecer en los listados por título, pero su texto plano nunca llega al índice — y mucho menos a un proveedor.

El índice no sale de casa

Los embeddings viven en un fichero SQLite local fuera de tu directorio de notas: nunca se sincroniza a GitHub, nunca se sube a ningún sitio. Borrarlo solo te cuesta un reindexado.

Keys bajo llave

Las API keys de los proveedores se cifran con el almacén de claves del SO y quedan confinadas al proceso principal — ver proveedores.

Y toda la capa es opt-in, detrás de dos interruptores independientes: los embeddings locales alimentan las notas relacionadas, el grafo de contenido y el RAG; un proveedor LLM configurado alimenta el chat y la generación. Cada uno funciona sin el otro — el chat sin índice simplemente responde sin el contexto de tus notas, y el índice solo te da notas relacionadas y el cerebro sin nube de por medio.