Skip to main content
Glama
README.md
<p align="center">
  <img src="docs/assets/synaptiq-overview.png" alt="SynaptiQ Core: durable facts become relevant context across sessions" width="100%">
</p>

# SynaptiQ Core

**Give AI applications memory they can retrieve, inspect, and update.**

SynaptiQ stores facts and relationships in PostgreSQL, organizes them by tenant and
project context, and retrieves relevant memory through a FastAPI service and MCP
tools. Use it as the memory layer behind an assistant, agent, or application.

[Quick start](#quick-start) · [Try it](#store-and-retrieve-your-first-memory) ·
[Architecture](docs/architecture.md) · [API](docs/api.md) ·
[GCP hosting](docs/gcp-hosting.md) · [Contributing](CONTRIBUTING.md)

## Why SynaptiQ?

A conversation contains useful details that should outlive a single session:
project goals, changing priorities, relationships, and preferences. Replaying an
entire transcript makes the application responsible for finding the relevant
parts and deciding which facts still apply.

SynaptiQ gives those details an explicit structure and lifecycle. An application
can save a fact, associate it with a project, retrieve it later, and update or
supersede it when the situation changes. The application or model still decides
what to remember and how to use the returned context; SynaptiQ does not train the
model or automatically capture every conversation.

For example: store **“Example app → goal → Ship the local prototype”** under
`work.projects.example`. In a later session, ask for context about that project.
The stored goal can become part of the assistant's next prompt.

## What makes the approach different?

These are architectural distinctions, not competitive benchmarks. Other systems
can implement similar behavior; SynaptiQ packages these choices together.

| Starting point | What SynaptiQ adds |
| --- | --- |
| Replaying chat history | Explicit, queryable facts with project anchors, lifecycle states, and timestamps. |
| Building directly on a vector index | Canonical subject–predicate–object records, relationship queries, and symbolic retrieval; vector retrieval is optional. |
| Retrieving document chunks | Tools for storing and changing individual facts, including supersession, timelines, and review workflows. |
| A database with a custom API | A memory-oriented tool catalog, context resolver, tenant-aware request handling, and MCP transport. |

Use it when your application needs evolving, structured memory across sessions.
For a short-lived chat or a document-only search feature, a smaller solution may
be sufficient. SynaptiQ is a memory backend, not an agent runner or a chat UI.

## How it works

![Architecture: clients call FastAPI and MCP, the memory core writes and queries PostgreSQL; optional workers enrich stored records](docs/assets/synaptiq-architecture.png)

1. **Store:** submit a fact or relationship with a tenant and `context_anchor`.
   The write path normalizes entities and predicates and checks for duplicates.
2. **Persist:** PostgreSQL holds canonical facts, lifecycle information, and
   supporting evidence. Memory survives API restarts while the database persists.
3. **Resolve:** a later request retrieves context using query, scope, intent,
   lifecycle, and ranking rules. Optional embeddings add a semantic signal.
4. **Maintain:** update, supersede, or delete facts as their meaning changes.
   Separate worker processes support enrichment and maintenance when configured.

Read the [architecture guide](docs/architecture.md) for the write/read paths,
trust boundaries, design tradeoffs, and a map from each component to its code.

## Quick start

**Prerequisites:** Python 3.12, Docker with Compose, and a free local port 5432.
Run these commands from the repository root. The basic setup requires no model
API key and does not enable cloud services or the embedding pipeline.

### 1. Install and start PostgreSQL

```bash
python3.12 -m venv .venv
source .venv/bin/activate
python -m pip install --require-hashes -r requirements.txt
cp .env.example .env
docker compose up -d postgres
until docker compose exec -T postgres pg_isready -U cme -d cme; do sleep 1; done
```

### 2. Initialize a fresh database and start the API

```bash
bash -e -c 'for f in migrations/*.sql; do
  docker compose exec -T postgres psql -U cme -d cme -v ON_ERROR_STOP=1 < "$f"
done'
uvicorn api.main:app --host 127.0.0.1 --port 8080 --reload
```

The migration loop stops on a failed migration. For an **existing database**, back
up first and inspect the tracked runner with
`python scripts/stabilization/run_schema_migrations.py --help`; do not replay the
fresh-database loop. See the [database guide](docs/database.md).

### 3. Check readiness

In another terminal:

```bash
curl --fail-with-body http://127.0.0.1:8080/healthz
curl --fail-with-body http://127.0.0.1:8080/readyz
```

Open the interactive [API docs](http://127.0.0.1:8080/docs). `/healthz` checks
liveness; `/readyz` checks database readiness. Docker Compose runs PostgreSQL;
the command above runs the API on your host. The database uses example local
credentials, and both services bind to localhost. Local API defaults permit
unauthenticated requests.

## Store and retrieve your first memory

Save a project goal:

```bash
curl --fail-with-body http://127.0.0.1:8080/mcp/invoke \
  -H 'Content-Type: application/json' \
  -d '{"tool_name":"memory_store_fact","args":{"tenant_id":"local-example","context_anchor":"work.projects.example","payload":{"subject":"Example app","predicate":"goal","object_value":"Ship the local prototype"}}}'
```

Retrieve context about that project:

```bash
curl --fail-with-body http://127.0.0.1:8080/mcp/invoke \
  -H 'Content-Type: application/json' \
  -d '{"tool_name":"memory_resolve_context","args":{"tenant_id":"local-example","context_anchor":"work.projects.example","user_message":"What is the goal of Example app?","limit":5}}'
```

Inspect the JSON response for the stored goal and its identifiers. Save returned
fact IDs when you need to update or delete a specific record. These examples are
local development requests; authenticated installations also require a bearer
token and must obey the tenant associated with the authenticated identity.

Use the MCP write tools for persistence. The old REST write routes
`/memory/attributes` and `/memory/relationships` return HTTP 410.

## Connect an MCP client

The HTTP MCP endpoint is `http://127.0.0.1:8080/mcp`. For clients accepting this
configuration shape:

```json
{
  "mcpServers": {
    "synaptiq": {"url": "http://127.0.0.1:8080/mcp"}
  }
}
```

Use your client's HTTP MCP configuration format and discover the server's tools.
Useful entry points include `memory_capabilities`, `memory_store_fact`,
`memory_store_facts`, and `memory_resolve_context`. The convenience endpoint
`/mcp/invoke` above accepts JSON directly; protocol clients use `/mcp`.

Remote clients need a reachable, authenticated endpoint—their localhost is not
your computer. Configuration, OAuth support, and approval flows vary by client.
This package does not claim end-to-end certification for individual Claude or
Codex clients. See the [API reference](docs/api.md).

## Local core and optional features

| Capability | With the supplied `.env.example` |
| --- | --- |
| Store facts and relationships; symbolic retrieval | Available with the API and migrated PostgreSQL database. |
| Project/topic grouping | Supply `context_anchor` when writing and resolving context. |
| Semantic embeddings and hybrid retrieval | Disabled; need a compatible embedding provider and worker processing. |
| Context token budgeting | Disabled; enable and configure the budgeting settings explicitly. |
| Background enrichment | Not started by the local quick start. The local event publisher simulates delivery. |
| Cloud adapters | Source included; require your own infrastructure, credentials, and configuration. |

A context anchor organizes memory; it is not an authorization boundary. A shared
API token does not give each caller a separate tenant identity. See the
[architecture security boundaries](docs/architecture.md#security-boundaries).

## Hosting and configuration

Start with [`.env.example`](.env.example). Keep actual secrets in your own `.env`
or secret manager. Non-local environments require configured authentication;
set `ENV=production`, choose the supported authentication method, and restrict
`CORS_ALLOWED_ORIGINS` to your client origins. Admin operations use a separate token.

The [GCP hosting guide](docs/gcp-hosting.md) covers Cloud Run, PostgreSQL/pgvector,
Secret Manager, migrations, and optional workers using portable examples.
The [Dockerfile](Dockerfile) builds the API image. The source package contains no
website, hosted service, private cloud configuration, or deployment workflows.

## Repository map

| Path | Purpose |
| --- | --- |
| [`api/`](api/) | FastAPI routes, authentication, MCP transport, and service lifecycle. |
| [`core/`](core/) | Canonical memory, context resolution, ranking, and lifecycle policies. |
| [`db/`](db/) · [`migrations/`](migrations/) | Connection handling and ordered PostgreSQL schema evolution. |
| [`workers/`](workers/) | Optional outbox, embedding, reinforcement, and maintenance services. |
| [`tests/`](tests/) | Memory, API, authentication, tenancy, and worker tests. |
| [`docs/`](docs/) | Architecture, API, database, and hosting references. |

## Troubleshooting

| Symptom | Check |
| --- | --- |
| Port 5432 is already in use | Stop the other local database or change the Compose port and matching database settings. |
| `/readyz` returns 503 | Confirm PostgreSQL is running and `.env` points to it. Readiness checks connectivity, not the full schema. |
| A request reports missing tables | Confirm every migration completed successfully against the same database used by the API. |
| A write returns 422 | Include `tenant_id`, `context_anchor`, and the required fact fields; inspect the error detail. |
| Semantic results are missing | Local defaults disable embeddings. Verify provider configuration and worker processing before enabling hybrid retrieval. |

## Develop and verify

```bash
python -m pip install --require-hashes -r requirements-dev.txt
python -m pytest -q
ruff check .
pip-audit -r requirements-dev.txt --disable-pip --no-deps
```

The prepared core passed 320 tests, and a container smoke check covered fresh
migrations, API startup, MCP tool discovery, and a real database save/search.
Many tests use mocks. These checks do not establish production capacity, a live
GCP deployment, or compatibility with every MCP client. No performance benchmark
or availability guarantee is claimed.

See [CONTRIBUTING.md](CONTRIBUTING.md) for development and
[SECURITY.md](SECURITY.md) for security reporting. The
[publication scope](PUBLIC_SCOPE.md) explains the included source boundaries.

## License

[MIT](LICENSE). Third-party packages retain their own licenses.

Maintenance

ActivityMaintained
ResponsivenessNo issues