Compatible clients
Use Qdrant, Elasticsearch, Arrow Flight SQL, Postgres and MySQL clients against Loams.
Loams speaks several protocols you may already use, each on its own loopback listener. Compatibility covers the implemented subset of each protocol; check the API references before you depend on a specific operation.
| Client | Port on loams dev | Tested with | Status |
|---|---|---|---|
| Qdrant REST and gRPC | 6333, 6334 | qdrant-client 1.15 and 1.19 | Available |
| Elasticsearch REST subset | 9200 | elasticsearch-py 8.19 | Available |
| Arrow Flight SQL | 8082 | ADBC Flight SQL driver | Available |
| Postgres wire (read-only) | off unless --pg-listen | psql, psycopg, node-postgres | Available |
| MySQL wire (read-only) | off unless --mysql-listen | Available |
These listeners stay on loopback. In the self-hosted stack they are on loopback inside the engine's network namespace and are not forwarded over the tailnet; only the native API is. Do not publish them in 0.1.0: the Postgres and MySQL wire listeners authenticate nobody.
Qdrant
# pip install qdrant-client
from qdrant_client import QdrantClient, models
client = QdrantClient(url="http://127.0.0.1:6333")
client.create_collection("docs", vectors_config=models.VectorParams(size=3, distance=models.Distance.COSINE))
client.upsert("docs", points=[models.PointStruct(id=1, vector=[1.0, 0.0, 0.0], payload={"title": "refunds"})], wait=True)
print(client.query_points("docs", query=[1.0, 0.0, 0.0], limit=1))Requests without a Loams-Namespace header go to the default namespace. The gRPC API is on port 6334 (QdrantClient(host="127.0.0.1", grpc_port=6334, prefer_grpc=True)).
Elasticsearch
The subset covers the document APIs, _bulk, and _search with the core Query DSL, knn, hybrid and RRF. LangChain and LlamaIndex Elasticsearch stores work through it.
# pip install "elasticsearch>=8.19,<9"
from elasticsearch import Elasticsearch
es = Elasticsearch("http://127.0.0.1:9200")
es.index(index="docs", id="1", document={"title": "refund policy"}, refresh=True)
print(es.search(index="docs", query={"match": {"title": "refund"}})["hits"]["hits"])As with Qdrant, the Loams-Namespace header picks the namespace and its absence means default.
Flight SQL
Any language with an ADBC or Flight SQL driver gets SQL with Arrow results. The namespace is a call header:
# pip install adbc-driver-flightsql pyarrow
import adbc_driver_flightsql.dbapi as flight_sql
with flight_sql.connect(
"grpc://127.0.0.1:8082",
db_kwargs={"adbc.flight.sql.rpc.call_header.loams-namespace": "demo"},
) as conn, conn.cursor() as cur:
cur.execute("SELECT _id, body FROM kb ORDER BY _id")
print(cur.fetch_arrow_table())The search table functions work here too: vector_search, text_search and rrf.
Postgres wire
The Postgres listener is in the pgwire Cargo feature (on in the release image) and is off unless you give it an address. It serves one namespace's collections as tables, read-only; --pg-namespace picks the namespace (default default).
cargo run --release -p loams --features pgwire -- dev --pg-listen 127.0.0.1:5432 --pg-namespace demo
psql "postgres://loams@127.0.0.1:5432/demo" -c "SELECT _id, body FROM kb"Writes answer SQLSTATE 25006. A collection's _id is text in SQL, whatever its keys are, so ORDER BY _id sorts integer keys as text; use ORDER BY CAST(_id AS BIGINT) for integer keys.
This listener is not Loams Postgres. For a real Postgres database whose storage lives on your bucket, see Loams Postgres.
MySQL wire
The MySQL listener is in the mysql-wire Cargo feature (on in the release image) and is off unless you give it an address. Like the Postgres listener it is read-only, serves one namespace, and accepts any user name and password.
cargo run --release -p loams --features mysql-wire -- dev --mysql-listen 127.0.0.1:3306
mysql -h 127.0.0.1 -P 3306 -u loams -e "SELECT _id, body FROM kb"This listener is not Loams SQL. For MySQL-compatible transactions, see Loams SQL.