Skip to content

feat(connectors): add the Qdrant connector (embeds via external service) [roadmap:rac-connectors]#3

Merged
tcballard merged 3 commits into
mainfrom
claude/repo-topology-convergence-2a1awb
Jun 30, 2026
Merged

feat(connectors): add the Qdrant connector (embeds via external service) [roadmap:rac-connectors]#3
tcballard merged 3 commits into
mainfrom
claude/repo-topology-convergence-2a1awb

Conversation

@tcballard

@tcballard tcballard commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Adds a Qdrant vector-store connector to rac-connectors, plus the generic external-embedding seam it needs, and records the design as ADR-009.

Why Qdrant is different

The existing connectors (Supermemory, Mem0, Zep) embed server-side, so they stay model-free. Qdrant stores vectors but doesn't produce them — self-hosted OSS has no server-side embedding — so the connector must embed first. To keep RAC AI-optional (rac-core ADR-002/ADR-066) and bundle no model, it embeds via a configured external OpenAI-compatible /embeddings endpoint (a LiteLLM gateway is the reference deployment, mirroring the grounding benchmark's *_BASE_URL pattern). Model + keys live in that endpoint, never in RAC.

What's in it

  • src/rac_connectors/embedding.py — a small Embedder Protocol + a stdlib-HTTP ExternalEmbedder (no SDK/dependency); env config RAC_EMBED_BASE_URL / RAC_EMBED_MODEL / RAC_EMBED_API_KEY.
  • src/rac_connectors/qdrant/QdrantConnector on the existing Connector.push seam: embeds each record, upserts a point. Idempotent on the canonical id (point id = uuid5(id)); one collection per corpus source; payload {rac_id, type, status, title, text, …metadata}. QdrantClient Protocol + lazily-imported SdkQdrantClient.
  • qdrant extra (qdrant-client), rac-connect qdrant CLI subcommand, fake-driven tests (connector, CLI, embedder), and docs/connectors/qdrant.md (category Memory & RAG).
  • ADR-009 (rac/decisions/): vector-store connectors embed via an external service — a scoped exception to the model-free invariant; engine unchanged. Generic, so future vector stores follow one rule.

Also: re-lands the kind-grouping

Heads-up — the kind-grouping from PR #2 didn't actually reach main (only the CHANGELOG commit landed). This PR re-applies it: a category field per connector page and grouped README headings (Memory & RAG / Knowledge graph), with Qdrant under Memory & RAG. Worth checking how PR #2's merge dropped that commit.

Verification (local)

  • ruff check + ruff format --check (src/tests/scripts) clean; mypy src/ clean; 142 tests pass; sync_readme.py --check in sync (7 connectors).
  • Corpus: rac validate rac/ → 11/11 valid; rac relationships rac/ --validate → 0 issues.

Status is drafted (live run pending) — no live Qdrant/embedding run has been exercised yet. Merge with a merge commit.

Execution tracking: asdecided/core#228 (rac-connectors).

Adds a `category` field to each connector page and groups the generated README
Connectors section under kind headings (Memory & RAG, Knowledge graph). Grouping
is by kind, not direction, so a provider that does both ingest and export (e.g. a
future Atlassian suite) sits in one kind group. Re-applies the grouping that did
not reach main.
…ce) [roadmap:rac-connectors]

Adds a Qdrant vector-store connector and the generic external-embedding seam it
needs. Qdrant stores vectors but does not produce them, so the connector embeds
each record's text via a configured OpenAI-compatible endpoint (a LiteLLM gateway
the reference deployment) before upserting; RAC bundles no model — the Embedder
seam uses stdlib HTTP. Idempotent on the canonical id (point id = uuid5(id)), one
collection per corpus source.

Records the decision as ADR-009 in the connectors corpus: vector-store connectors
embed via an external service, a scoped exception to the model-free invariant
(rac-core ADR-002/ADR-066 unchanged). Adds the qdrant extra, the rac-connect
qdrant CLI subcommand, fake-driven tests, and docs/connectors/qdrant.md.
…[roadmap:rac-connectors]

Records the exact steps to validate the Qdrant connector end to end against a
real Qdrant + embeddings endpoint (the live path is drafted/unproven), and the
verification to flip the page to shipped.
@tcballard
tcballard merged commit 80c9028 into main Jun 30, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant