Skip to content

Components

Everything replaceable in Windlass is a component. There are fifteen kinds, thirteen of which have a formal interface in interfaces/. Each kind has exactly one contract, and every implementation — built-in or yours — satisfies it.

The catalogue

Run windlass list to see what your install actually has. Components whose extra is missing are marked.

llm — language models

Name Extra Notes
fake Deterministic and scripted. The reason the test suite runs offline.
echo Returns the last user message. Useful for wiring tests.
openai openai Also Azure, vLLM, LM Studio, OpenRouter — anything OpenAI-compatible
anthropic anthropic Claude, with extended thinking support
gemini gemini Gemini Developer API and Vertex AI
groq groq Open-weight models at very high throughput
ollama Local models over HTTP; no extra needed

Interface: LLM

embedding — embedding models

Name Extra Notes
hash Hashed n-grams. Deterministic, dependency-free, not semantic
huggingface embeddings Local sentence-transformers; applies E5/BGE/Nomic instruction prefixes for you
hf_inference HuggingFace Inference API — hosted, no local model, speaks the core httpx
openai openai Supports Matryoshka dimension reduction

Interface: Embedder

vectordb — vector stores

Name Extra Notes
memory Exact search, JSON persistence. Genuinely fine to ~100k chunks with NumPy
faiss faiss Flat, IVF or HNSW; millions of vectors on one machine
chroma chroma Embedded or client/server, native metadata filtering
pinecone pinecone Managed, distributed, namespace isolation

Interface: VectorStore

chunker — text splitting

Name Extra Notes
recursive Splits on the largest natural boundary that fits. The right default for prose
token Same, measured in model tokens
semantic Splits at topic shifts detected from sentence embeddings
markdown Heading-aware; prefixes each chunk with its heading path
code Function and class boundaries for 13 languages
parent_child Indexes small chunks that expand to their parent at query time

Interface: Chunker

retriever — retrieval strategies

Name Extra Notes
bm25 Okapi BM25 over an in-process inverted index
vector Dense search, optional MMR diversification
hybrid Fuses any number of retrievers with Reciprocal Rank Fusion
contextual LLM-enriched chunks at index time; HyDE and multi-query at search time

Interface: Retriever

loader — document loading

text · markdown · json · csv · html · web (all dependency-free), plus pdf · docx · pptx · xlsx · youtube (loaders), image (ocr) and audio (audio).

Format detection is automatic — you rarely name a loader. Interface: Loader

preprocessor — document processing

Name Extra Notes
clean Unicode and whitespace normalisation, boilerplate removal
pii Detects and redacts personal data before it reaches the index
dedup Exact and near-duplicate removal via shingle similarity
language Detects language; can filter on it
metadata Counts, reading time, keywords
tables Separates tables from prose
ocr ocr Re-reads scanned pages when text extraction came back empty
llm_metadata Title, summary, topics and entities via a model

Preprocessors compose with |. Interface: Preprocessor

memory — conversation and long-term

Name Notes
buffer The full transcript per thread
window The last n messages; never splits a tool call from its result
summary Summarises overflow with an LLM
vector Durable facts recalled by similarity, not recency
composite Combines several

Interface: Memory

guardrail — safety

Name Extra Notes
rules PII, prompt injection, leaked secrets, banned terms. Microseconds, no model call
nemo guardrails NVIDIA NeMo: topical rails, Colang flows, jailbreak detection

Guardrails compose with &. Interface: Guardrail

evaluator — quality measurement

Name Extra Notes
builtin Lexical metrics (free) plus LLM-judged ones (faithfulness, relevancy, correctness)
ragas evaluation Reference-free RAG metrics
deepeval evaluation Metrics with pass/fail verdicts and explanations

Interface: Evaluator

tracer — observability

console · memory · null · multi (fans one span out to several backends) — all dependency-free — plus langsmith and langfuse (observability).

Interface: Tracer

mcp — Model Context Protocol

Name Extra Notes
fastmcp mcp stdio, SSE and streamable HTTP
static In-process, for tests
multi Aggregates several servers with automatic namespacing

Interface: MCPClient

tool, cache, checkpointer

tool ships no built-ins by design — a generic built-in tool would either be useless or a security footgun. cache offers memory, disk and null; checkpointer offers memory and sqlite.

cache and checkpointer are the two kinds that are not built on Component: they are plain ABCs (windlass.core.cache.Cache and windlass.agent.checkpoint.Checkpointer) because neither wraps a provider SDK, so neither has anything for native() to return. They register and resolve through the registry exactly like the other thirteen.

What every component shares

Thirteen of the fifteen kinds extend Component — every kind with a contract in interfaces/:

component.name              # identifier used in traces and errors
component.config            # the configuration it was built with
component.describe()        # JSON-safe summary, secrets masked
component.native()          # the underlying SDK object (Level 3)
await component.aclose()    # release sockets, handles, pools

describe() is worth knowing about. It powers rag.describe(), which prints a complete picture of what a deployment is actually running — invaluable when two environments behave differently:

>>> Windlass.rag().retriever("hybrid").describe()
{'llm': {'kind': 'llm', 'name': 'fake', 'class': '...', 'config': {...}},
 'retriever': {'kind': 'retriever', 'name': 'hybrid', 'legs': [...]},
 'vectorstore': {...},
 'top_k': 5, ...}

Secrets are masked by key name, so it is safe to log.

Constructing one directly

Builders are the ergonomic path, but every component is available on its own:

llm       = Windlass.llm("openai", model="gpt-4o")
embedder  = Windlass.embedding("huggingface")
store     = Windlass.vectordb("faiss", dimensions=384)
chunker   = Windlass.chunker("semantic", embedder=embedder)
guardrail = Windlass.guardrail(pii=True)
tracer    = Windlass.tracer("langfuse")

Useful when you are embedding one piece of Windlass into a system that already has its own orchestration.

Discovering at runtime

Windlass.list()                  # {kind: [names]} for everything
Windlass.list("retriever")       # ['bm25', 'contextual', 'hybrid', 'vector']
Windlass.kinds()                 # every kind
Windlass.catalog("chunker")      # full specs: description, aliases, required extra
for spec in Windlass.catalog("vectordb"):
    print(f"{spec.name:<12} {spec.extra or 'core':<10} {spec.description}")

Adding your own

See Writing plugins. The short version:

from windlass import register, Retriever, ScoredChunk

@register.retriever("my-search")
class MySearch(Retriever):
    """Queries our existing search service."""

    async def aretrieve_chunks(self, query, k, *, filters=None, **kwargs):
        hits = await search_service.query(query, limit=k)
        return [ScoredChunk(chunk=to_chunk(h), score=h.score) for h in hits]
rag = Windlass.rag().retriever("my-search")

From that point it is indistinguishable from a built-in: it composes into hybrid retrieval, it is traced, it is configurable, and it shows up in windlass list.