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

Installation

# mix.exs
defp deps do
  [{:moss, "~> 1.0"}]
end

Quick 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 &#39;#{push_result.index_name}&#39;")

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-only

Cloud 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.

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