# klieo-memory-pgvector
PostgreSQL + [pgvector](https://github.com/pgvector/pgvector) implementation of
klieo-core's `LongTermMemory` (and `FilterableLongTermMemory`). Sibling to
`klieo-memory-qdrant` — same trait surface, different store. Targets Aurora
PostgreSQL Serverless v2 but works against any Postgres with the `vector`
extension.
## Schema
One table per deployment (`<prefix>_v1`, default `klieo_facts_v1`):
| `fact_id` | `uuid` (PK) | caller-facing `FactId` |
| `text` | `text` | fact body |
| `metadata` | `jsonb` | caller's opaque JSON |
| `embedding` | `vector(dim)` | `Embedder::embed(text)` |
| `scope_kind` | `text` | `workspace` \| `agent` \| `global` |
| `scope_value` | `text` | scope owner (empty for global) |
Indexes: HNSW on `embedding` (`vector_cosine_ops`) for ANN recall, and
`(scope_kind, scope_value)` for the scope filter. Provisioned lazily on the
first `remember` (so process starts don't race on DDL); the embedding
dimension is fixed at first write.
`metadata` is `jsonb` (not a string) so relational joins from domain keys
(Versicherungsnummer, Vertrag, GeVo-Typ) to facts remain possible against the
same table — that join layer is a separate component, intentionally out of
this crate.
## Usage
```rust,no_run
# async fn example() {
use klieo_memory_pgvector::{MemoryPgvector, PgvectorConfig, DummyEmbedder};
use std::sync::Arc;
// Capability-shaped default (DummyEmbedder):
let mem = MemoryPgvector::connect("postgres://localhost/klieo").await.unwrap();
// Real embedder + config:
let cfg = PgvectorConfig::new("postgres://aurora.internal/klieo?sslmode=require")
.with_table_prefix("triage")
.with_embedder_id("titan-v2");
let mem = MemoryPgvector::new(cfg, Arc::new(DummyEmbedder)).await.unwrap();
let _ = mem.long_term;
# }
```
## TLS / credentials
Carried by the connection URL (`?sslmode=require`), standard libpq behaviour —
not a separate config knob. The table prefix is validated as a lowercase SQL
identifier before it is interpolated into DDL.
## Permissions
The first `remember` runs `CREATE EXTENSION IF NOT EXISTS vector` — the role
needs permission to create the extension (on Aurora, `rds_superuser`), or an
operator must pre-create it.
## Embeddings
Model-agnostic via the shared `Embedder` trait. Pair with a Bedrock Titan
`Embedder` on the AWS estate; `DummyEmbedder` (zero-vector, FIFO recall) is the
default for tests/dev.