moss
Elixir SDK for moss — local-first indexing and querying for real-time agent workflows, with built-in embedding flows for "moss-minilm" and "moss-mediumlm".
Features
- Local Session Index — Index and query entirely in memory during a live session
- Built-In Embeddings —
add_docs/3andquery/3embed automatically for built-in models - Custom Embeddings — Set
.embeddingon eachDocumentInfoand passembedding:toquery/3 - Index Loading — Load indexes into memory and query them with
Moss.Client.query/4 - Cloud Sync — Push a session index to cloud, or manage cloud indexes directly
- High-Performance Rust Core — Indexing, search, and embedding execution run through Rust NIFs
Installation
# mix.exs
defp deps do
[{:moss, "~> 1.0"}]
endQuick Start
alias Moss.{Client, DocumentInfo, Session}
# 1. Create a client
{:ok, client} = Client.new("your-project-id", "your-project-key")
# 2. Open a session (auto-loads from cloud if the index exists)
{:ok, session} = Client.session(client, "session-abc")
# 3. Index documents locally
docs = [
%DocumentInfo{id: "1", text: "Customer asked about their invoice from March"},
%DocumentInfo{id: "2", text: "Discussed upgrading to the business plan"},
%DocumentInfo{id: "3", text: "Customer mentioned difficulty logging in"}
]
{:ok, {3, 0}} = Session.add_docs(session, docs)
# 4. Query (local, no cloud round trip)
{:ok, result} = Session.query(session, "billing question", top_k: 2)
for doc <- result.docs do
IO.puts("#{Float.round(doc.score, 3)} #{String.slice(doc.text, 0, 60)}")
end
# 5. Push to cloud
{:ok, push_result} = Session.push_index(session)
IO.puts("Pushed #{push_result.doc_count} docs as '#{push_result.index_name}'")Custom Embeddings
{:ok, client} = Moss.Client.new("your-project-id", "your-project-key")
{:ok, session} = Moss.Client.session(client, "session-abc", model_id: "custom")
docs = [
%Moss.DocumentInfo{id: "1", text: "Invoice from March", embedding: embedding_1},
%Moss.DocumentInfo{id: "2", text: "Plan upgrade", embedding: embedding_2}
]
{:ok, {2, 0}} = Moss.Session.add_docs(session, docs)
{:ok, result} = Moss.Session.query(session, "billing", embedding: query_embedding, top_k: 2)Load and Query Cloud Indexes Locally
{:ok, client} = Moss.Client.new("project-id", "project-key")
# Load a cloud index into memory
{:ok, _} = Moss.Client.load_index(client, "faq-index")
# Query it locally
{:ok, results} = Moss.Client.query(client, "faq-index", "cancel subscription", top_k: 3)Session + Loaded Cloud Index
{:ok, client} = Moss.Client.new("project-id", "project-key")
{:ok, _} = Moss.Client.load_index(client, "faq-index")
{:ok, session} = Moss.Client.session(client, "session-xyz")
# Index session-specific documents
{:ok, _} =
Moss.Session.add_docs(session, [
%Moss.DocumentInfo{id: "turn-1", text: "Customer: I need to cancel my subscription"},
%Moss.DocumentInfo{id: "turn-2", text: "Agent: I can help with that. Can I ask why?"}
])
# Query session and cloud indexes independently
{:ok, session_results} = Moss.Session.query(session, "subscription cancellation", top_k: 3)
{:ok, faq_results} = Moss.Client.query(client, "faq-index", "subscription cancellation", top_k: 3)
# Push session to cloud when done
{:ok, _} = Moss.Session.push_index(session)
For loaded "custom" indexes, pass embedding: [...] to Moss.Client.query/4.
Metadata Filters
All local query functions accept the same :filter keyword argument.
filter = %{"field" => "type", "condition" => %{"$eq" => "billing"}}
{:ok, result} = Moss.Session.query(session, "invoice", filter: filter)
filter = %{
"$and" => [
%{"field" => "type", "condition" => %{"$eq" => "billing"}},
%{"field" => "priority", "condition" => %{"$gte" => "5"}}
]
}
{:ok, result} = Moss.Client.query(client, "faq-index", "urgent billing", filter: filter)
Supported operators: $eq, $ne, $gt, $gte, $lt, $lte, $in, $nin, $near
Logical combinators: $and, $or
Available Models
model_id | Behavior |
|---|---|
"moss-minilm" | Built-in local embeddings, optimized for speed |
"moss-mediumlm" | Built-in local embeddings, higher quality |
"custom" |
Caller supplies embeddings via DocumentInfo.embedding and embedding: opt |
Hybrid Search
The :alpha option blends semantic and keyword search.
Moss.Session.query(session, "billing", alpha: 0.0) # keyword-only
Moss.Session.query(session, "billing") # balanced (default 0.8)
Moss.Session.query(session, "billing", alpha: 1.0) # semantic-onlyCloud CRUD
{:ok, client} = Moss.Client.new("project-id", "project-key")
{:ok, result} = Moss.Client.create_index(client, "my-index", docs)
{:ok, info} = Moss.Client.get_index(client, "my-index")
{:ok, status} = Moss.Client.get_job_status(client, result.job_id)Module Reference
| Module | Description |
|---|---|
Moss.Client | Entry point — cloud CRUD, local index ops, and sessions |
Moss.Session | GenServer for local session indexing |
Moss.DocumentInfo | %{id, text, metadata, embedding} |
Moss.SearchResult | %{docs, query, index_name, time_taken_ms} |
Moss.QueryResultDoc | %{id, text, metadata, score} |
Moss.IndexInfo | %{id, name, version, status, doc_count, created_at, updated_at, model} |
Moss.PushIndexResult | %{job_id, index_name, doc_count, status} |
License
This package is licensed under the PolyForm Shield License 1.0.0.
- Free for testing, evaluation, internal use, and modifications.
- Not permitted for production or competing commercial use.
- For commercial licenses, contact: contact@moss.dev
moss reports aggregated usage counts to Moss servers for billing. No document content is sent.
Contact
For support, commercial licensing, or partnership inquiries: contact@moss.dev