src/skills/api-vector-db-weaviate/SKILL.md
Weaviate vector database patterns with weaviate-client v3 -- collection management, vectorizer modules, hybrid search, filtering, generative search (RAG), multi-tenancy, batch imports
npx skillsauth add agents-inc/skills api-vector-db-weaviateInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Quick Guide: Use Weaviate for semantic search and RAG applications. Use weaviate-client (v3.x) as the TypeScript client -- it uses gRPC for performance and provides full type safety with generics. Connect via
connectToWeaviateCloud()for managed instances orconnectToLocal()for Docker. Collections are the central abstraction -- configure vectorizers at collection level, not per-query. Usecollection.query.*for search,collection.generate.*for RAG, andcollection.data.*for CRUD. Always callclient.close()when done. Increase query timeout to 60s+ when using generative search. The v3 client does NOT support browsers or Embedded Weaviate.
<critical_requirements>
All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering,
import type, named constants)
(You MUST call client.close() when done with the Weaviate client -- it maintains persistent gRPC connections that will leak if not closed)
(You MUST configure vectorizers at the COLLECTION level during client.collections.create() -- you cannot add a vectorizer after creation, only add new named vectors)
(You MUST use a SEPARATE client.collections.use() call with .withTenant() for multi-tenant queries -- queries without tenant context on multi-tenant collections will fail)
(You MUST increase query timeout to 60+ seconds when using generate.* (RAG) submodule -- generative model calls are slow and the default timeout causes failures)
</critical_requirements>
Additional resources:
Auto-detection: Weaviate, weaviate-client, connectToWeaviateCloud, connectToLocal, nearText, nearVector, hybrid search, bm25, vector database, semantic search, RAG, generative search, generate.nearText, insertMany, vectorizer, text2vec, multi-tenancy, withTenant, collection.query, collection.generate, collection.data
When to use:
Key patterns covered:
When NOT to use:
Weaviate is a vector database that stores data objects alongside their vector embeddings. The core principle: configure once at the collection level, then query with simple method calls.
Core principles:
client.collections.use().nearText for semantic similarity, bm25 for keyword matching, hybrid for a weighted combination. The alpha parameter controls the vector-vs-keyword balance in hybrid search.collection.query.nearText() to collection.generate.nearText() to add LLM generation on top of search results.Filters.and() and Filters.or() for complex conditions.Connect to Weaviate Cloud or local Docker instance. Always close the client when done. See examples/core.md for full examples.
// Good Example -- Cloud connection with API key headers
import weaviate from "weaviate-client";
const QUERY_TIMEOUT_SECONDS = 30;
const INSERT_TIMEOUT_SECONDS = 120;
async function createWeaviateClient() {
const client = await weaviate.connectToWeaviateCloud(
process.env.WEAVIATE_URL!,
{
authCredentials: new weaviate.ApiKey(process.env.WEAVIATE_API_KEY!),
headers: {
"X-OpenAI-Api-Key": process.env.OPENAI_API_KEY!,
},
timeout: {
query: QUERY_TIMEOUT_SECONDS,
insert: INSERT_TIMEOUT_SECONDS,
},
},
);
return client;
}
export { createWeaviateClient };
Why good: Environment variables for credentials, explicit timeouts, API key headers for vectorizer modules
// Bad Example -- Missing cleanup, no timeout config
import weaviate from "weaviate-client";
const client = await weaviate.connectToLocal();
// No client.close() -- gRPC connections leak
// No timeout config -- generative queries will timeout
Why bad: Missing client.close() leaks gRPC connections, default timeout too short for RAG queries
Configure vectorizer and properties at creation time. See examples/core.md for named vectors and advanced configuration.
// Good Example -- Collection with vectorizer and generative model
import { vectors, dataType, generative } from "weaviate-client";
await client.collections.create({
name: "Article",
vectorizers: vectors.text2VecOpenAI({
model: "text-embedding-3-small",
}),
generative: generative.openAI({
model: "gpt-4o",
}),
properties: [
{ name: "title", dataType: dataType.TEXT },
{ name: "body", dataType: dataType.TEXT },
{ name: "category", dataType: dataType.TEXT },
{ name: "publishedAt", dataType: dataType.DATE },
],
});
Why good: Vectorizer and generative model configured at collection level, typed properties with explicit data types
// Bad Example -- Trying to add vectorizer after creation
await client.collections.create({ name: "Article" });
// No way to add a vectorizer to an existing collection without named vectors
// Must delete and recreate, or use addVector() for named vectors only
Why bad: Vectorizer must be set at creation time; cannot be added to an existing default vector after the fact
Combine vector and keyword search with property filters. See examples/search.md for all search types.
// Good Example -- Hybrid search with filter
import { Filters } from "weaviate-client";
const articles = client.collections.use("Article");
const SEARCH_LIMIT = 10;
const HYBRID_ALPHA = 0.75; // Favor vector search
const result = await articles.query.hybrid("machine learning trends", {
alpha: HYBRID_ALPHA,
limit: SEARCH_LIMIT,
filters: Filters.and(
articles.filter.byProperty("category").equal("technology"),
articles.filter
.byProperty("publishedAt")
.greaterThan(new Date("2024-01-01")),
),
returnMetadata: ["score", "explainScore"],
});
for (const obj of result.objects) {
console.log(obj.properties.title, obj.metadata?.score);
}
Why good: Named constants for limits and alpha, combined filter with Filters.and(), metadata for debugging relevance
Switch from query.* to generate.* for RAG. See examples/search.md for singlePrompt and groupedTask patterns.
// Good Example -- RAG with single prompt per result
const articles = client.collections.use("Article");
const RAG_RESULT_LIMIT = 5;
const result = await articles.generate.nearText(
"climate change policy",
{
singlePrompt: "Summarize this article in one sentence: {title} - {body}",
},
{
limit: RAG_RESULT_LIMIT,
returnMetadata: ["distance"],
},
);
for (const obj of result.objects) {
console.log("Source:", obj.properties.title);
console.log("Generated:", obj.generative?.text);
}
Why good: Uses property interpolation {title} in prompt, accesses generated text via obj.generative?.text
// Bad Example -- Using query instead of generate for RAG
const result = await articles.query.nearText("climate change", { limit: 5 });
// Then manually calling OpenAI API with results
// Weaviate does this natively with generate.*
Why bad: Misses Weaviate's built-in RAG -- extra network hops, no automatic prompt interpolation
</patterns><decision_framework>
What kind of search do I need?
├─ Natural language query, semantic meaning? -> nearText (requires vectorizer module)
├─ Have pre-computed vector embedding? -> nearVector
├─ Exact keyword matching? -> bm25
├─ Both semantic and keyword relevance? -> hybrid (alpha controls blend)
├─ Just list/filter objects without search? -> fetchObjects
└─ Search + LLM generation? -> generate.nearText / generate.hybrid
Which vectorizer module should I use?
├─ OpenAI models (text-embedding-3-small/large)? -> text2VecOpenAI
├─ Cohere models (embed-v3)? -> text2VecCohere
├─ Self-hosted models? -> text2VecOllama or text2VecTransformers
├─ Bring your own embeddings? -> none (use selfProvided for named vectors)
├─ Multimodal (images + text)? -> multi2VecClip or multi2VecBind
└─ Multiple embedding strategies? -> Named vectors (array of vectorizers)
How many vector representations do I need?
├─ One embedding per object (most common)? -> Single default vectorizer
├─ Different embeddings for different properties? -> Named vectors
├─ Mix of auto-vectorized and self-provided? -> Named vectors with selfProvided
└─ Different models for different search use cases? -> Named vectors
Do I need data isolation?
├─ Each customer/user needs isolated data? -> Enable multi-tenancy
├─ Shared dataset, filter by user? -> Single tenant with filters
├─ Need to offload inactive tenants? -> Multi-tenancy with tenant states
└─ Small number of distinct datasets? -> Separate collections may be simpler
</decision_framework>
<red_flags>
High Priority Issues:
client.close() -- gRPC connections persist and leak memory/file descriptorscreate(). Only named vectors can be added later with config.addVector().withTenant() -- all operations fail with an errorgenerate.* -- generative calls need 60+ seconds; default is often too shortMedium Priority Issues:
replace() when update() is intended -- replace deletes all properties not included in the call; update mergesinsertMany response for errors -- partial failures are silent; check response.hasErrors and response.errorsalpha: 1.0 to hybrid search -- equivalent to pure vector search; use nearText instead for claritytargetVector with named vectors -- queries default to the first vector, which may not be the intended oneCommon Mistakes:
client.schema.classCreator()) with v3 client -- the API is completely different; v3 uses client.collections.create()X-OpenAI-Api-Key, X-Cohere-Api-Key etc. must be in connection headersconnectToWCS() (deprecated) instead of connectToWeaviateCloud()Gotchas & Edge Cases:
insertMany uses server-side batching but the TS client does NOT have a streaming batch API -- for very large imports (100K+), chunk into batches of 100-1000 objectsFilters.and() and Filters.or() take a flat list of filter conditions, NOT nested arrays -- Filters.and(a, b, c) not Filters.and([a, b, c])fetchObjects() without limit returns 25 objects by default (server-side default), not all objectsdistance metadata varies by vector distance metric -- cosine distance range [0, 2], not [0, 1]deleteMany has a server-side maximum of 10,000 objects per call (configurable via QUERY_MAXIMUM_RESULTS)fetchObjectById returns null for non-existent IDs, not an empty object -- always check for null before accessing properties</red_flags>
<critical_reminders>
All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering,
import type, named constants)
(You MUST call client.close() when done with the Weaviate client -- it maintains persistent gRPC connections that will leak if not closed)
(You MUST configure vectorizers at the COLLECTION level during client.collections.create() -- you cannot add a vectorizer after creation, only add new named vectors)
(You MUST use a SEPARATE client.collections.use() call with .withTenant() for multi-tenant queries -- queries without tenant context on multi-tenant collections will fail)
(You MUST increase query timeout to 60+ seconds when using generate.* (RAG) submodule -- generative model calls are slow and the default timeout causes failures)
Failure to follow these rules will cause connection leaks, missing vectorization, multi-tenant query failures, and RAG timeouts.
</critical_reminders>
development
Material Design component library for Vue 3
development
VitePress 1.x — Vue-powered static site generator for documentation sites, built on Vite
tools
Docusaurus 3.x documentation framework — site configuration, docs/blog plugins, sidebars, versioning, MDX, swizzling, and deployment
development
TanStack Form patterns - useForm, form.Field, validators, arrays, linked fields, createFormHook, type safety