Skip to main content

Quickstart (OSS)

Store and search a governed memory in 60 seconds. This walkthrough uses the OSS-default path — local fastembed embeddings + an in-Docker pgvector — so it needs no cloud credentials.

1. Run pgvector locally

docker run -d --name memledger-pg -p 5432:5432 \
-e POSTGRES_PASSWORD=postgres \
-e POSTGRES_DB=memledger \
pgvector/pgvector:pg16
Mac users with Homebrew Postgres

If brew services list shows postgresql running, port 5432 is already taken locally and Docker's port-forward will be shadowed silently — asyncpg connects to the wrong daemon and you'll see role "postgres" does not exist. Either stop Homebrew Postgres (brew services stop postgresql) or change the docker port to -p 5434:5432 and update the connection string accordingly.

2. Install

pip install "memledger[oss]"

The [oss] extra pulls in pgvector (asyncpg + pgvector client) and local (fastembed for in-process embeddings — BAAI/bge-small-en-v1.5, 384 dims, ~130 MB on first run).

3. Write and search a memory

import asyncio
from memledger import Memledger
from memledger.models import EmbeddingConfig

async def main():
ml = await Memledger.create(
backend_name="pgvector",
connection_string="postgresql://postgres:postgres@localhost:5432/memledger",
embedding_config=EmbeddingConfig(provider="local"),
)

await ml.add(
content="HikariCP maxPoolSize=50 fixes payment-service OOM",
namespace="/ops/incidents/payment-svc",
confidence=0.9,
created_by="ops-agent",
)

results = await ml.search(
query="connection pool fix",
namespace="/ops/incidents/payment-svc",
)
for r in results.records:
print(r.confidence, r.created_by, "::", r.content)

await ml.close()

asyncio.run(main())

memledger's most opinionated guarantee — effective confidence — only matters when memories derive from one another. Try it:

async def chain_demo():
ml = await Memledger.create(
backend_name="pgvector",
connection_string="postgresql://postgres:postgres@localhost:5432/memledger",
embedding_config=EmbeddingConfig(provider="local"),
)

# Triage agent makes a hedged guess.
triage_id = await ml.add(
content="possible connection-pool exhaustion (ambiguous signal)",
namespace="/ops/incidents/payment-svc",
confidence=0.30,
hedged=True,
created_by="triage-agent",
)

# Diagnosis agent confidently asserts a fix derived from triage.
await ml.add(
content="bump maxPoolSize from 10 to 50",
namespace="/ops/incidents/payment-svc",
confidence=0.85, # declared
created_by="diagnosis-agent",
derived_from=[triage_id], # this is the chain
)

result = await ml.search(
query="connection pool fix",
namespace="/ops/incidents/payment-svc",
confidence_policy={"min_threshold": 0.4, "flag_threshold": 0.6},
)

print(result.metadata["confidence_gating"])
# passed=1, flagged=0, filtered=2 — the step-3 high-confidence record
# passes; both step-4 chain records are filtered because the diagnosis
# inherits min(0.85, 0.30) = 0.30 effective via its triage ancestor

await ml.close()

asyncio.run(chain_demo())

The diagnosis record's declared confidence is 0.85 — high. But its provenance runs through a 0.30-confidence ancestor. memledger's effective confidence is min(declared, chain.min_confidence) = 0.30, and the gate filters it.

Where next