> Markdown export: /developers/embeddings-boundary.md
> HTML: /developers/embeddings-boundary
---
description: Critical security policy — embedding vectors stay in Postgres and never appear in MCP, chat, or LLM payloads.
audience: operator
---

# Embeddings: DB-only boundary

> **In plain terms:** Eigen Mesh stores mathematical search indexes internally but never sends them to AI tools or chat — only human-readable text appears in prompts and tool results.

**Status:** Enforced in the eigen product codebase. **Risk:** Critical (ingestion, retrieval, MCP, chat).

## Who this is for

- **Operators** auditing data exposure in self-hosted deployments
- **Integrators** reviewing what MCP tools may return to AI clients

## Policy

Embedding vectors (1536-dimensional floats for thoughts, entities, temporal events, etc.) are **core infrastructure**:

- **Allowed:** compute via the embedding gateway, store in Postgres/pgvector, use inside retrieval and consolidation (distance queries, internal pipelines).
- **Forbidden:** return vectors from MCP tools, HTTP tool-shaped APIs, chat/agent payloads, or any LLM chat completion request; log full vectors or long embedding inputs.

Text fields (`normalizedText`, snippets, scores) are fine in tools and LLM prompts. **Vectors are not.**

## Why

- Vectors are large (~6k+ tokens each if serialized), leak no useful semantics to chat models, and blow context windows.
- User trust: memory content in prompts should be human-readable text, not raw numeric embeddings.

## Enforcement (defense in depth)

The eigen product applies multiple layers:

| Layer | Role |
|-------|------|
| Query shape | Tool-facing reads exclude `embedding` columns |
| MCP tools | Sanitize every tool return before JSON serialization |
| Agent loop | Sanitize after each tool; compact results for follow-up turns |
| Chat gateway | Strip vectors immediately before LLM requests |
| Shared stripper | Recursively remove vector field names and 1536-element numeric arrays |
| Logs | No vector previews in console output |

## Retrieval and compose-answer

- `searchThoughts` / `retrieve_thoughts` returns **scores and text**, not stored thought embeddings.
- `composeAnswer` and in-app chat build LLM prompts from text, category, scores, and dates — never from embedding columns.
- Query embeddings are created in-process for SQL distance only; they are not attached to tool results.

## Intentional exception

The **graph embedding map UI** (`GET /api/embeddings/snapshot`) returns vectors for authorized in-browser visualization only — not MCP, not chat LLM.

## For integrators

When building on MCP or REST:

1. Never expect or request embedding arrays in tool results — they are stripped by design.
2. Use `retrieve_thoughts` text fields and scores for context assembly.
3. See [MCP tools reference](/developers/mcp-tools).

## For contributors

Implementation file paths and PR review checklist live in the eigen repository's contributor docs and `.cursor/rules/no-embeddings-in-llm.mdc`.

Domain entry points: [Ingestion](/developers/ingestion), [Retrieval](/developers/retrieval).

## Troubleshooting

Embedding-related issues are rare for end users. See [Troubleshooting](/developers/troubleshooting) for broader MCP and retrieval problems.

## Next steps

- [MCP tools reference](/developers/mcp-tools) — allowed tool response fields
- [How memory works](/developers/how-memory-works) — retrieval pipeline overview
