Skills api-vector-db-weaviate
Weaviate vector database patterns with weaviate-client v3 -- collection management, vectorizer modules, hybrid search, filtering, generative search (RAG), multi-tenancy, batch imports
git clone https://github.com/agents-inc/skills
T=$(mktemp -d) && git clone --depth=1 https://github.com/agents-inc/skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/dist/plugins/api-vector-db-weaviate/skills/api-vector-db-weaviate" ~/.claude/skills/agents-inc-skills-api-vector-db-weaviate && rm -rf "$T"
dist/plugins/api-vector-db-weaviate/skills/api-vector-db-weaviate/SKILL.mdWeaviate Patterns
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
for managed instances orconnectToWeaviateCloud()for Docker. Collections are the central abstraction -- configure vectorizers at collection level, not per-query. UseconnectToLocal()for search,collection.query.*for RAG, andcollection.generate.*for CRUD. Always callcollection.data.*when done. Increase query timeout to 60s+ when using generative search. The v3 client does NOT support browsers or Embedded Weaviate.client.close()
<critical_requirements>
CRITICAL: Before Using This Skill
All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering,
, named constants)import type
(You MUST call
when done with the Weaviate client -- it maintains persistent gRPC connections that will leak if not closed)client.close()
(You MUST configure vectorizers at the COLLECTION level during
-- you cannot add a vectorizer after creation, only add new named vectors)client.collections.create()
(You MUST use a SEPARATE
call with client.collections.use()
for multi-tenant queries -- queries without tenant context on multi-tenant collections will fail).withTenant()
(You MUST increase query timeout to 60+ seconds when using
(RAG) submodule -- generative model calls are slow and the default timeout causes failures)generate.*
</critical_requirements>
Examples
- Core Patterns -- Connection, collection setup, object CRUD, basic search
- Search & Filtering -- nearText, nearVector, hybrid, bm25, filters, generative search (RAG)
- Multi-Tenancy & Batch -- Tenant management, batch imports, cross-references
Additional resources:
- reference.md -- API cheat sheet, vectorizer comparison, data types, decision frameworks
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:
- Semantic search over text, images, or multimodal data
- Retrieval Augmented Generation (RAG) with built-in generative search
- Hybrid search combining vector similarity and keyword (BM25) ranking
- Multi-tenant applications needing isolated vector stores per customer
- Applications requiring built-in vectorization (no external embedding pipeline)
- Real-time similarity search with filtering on structured properties
Key patterns covered:
- weaviate-client v3 connection setup and configuration
- Collection management with vectorizer modules (text2vec-openai, text2vec-cohere, etc.)
- Object CRUD (insert, insertMany, update, replace, deleteById, deleteMany)
- Search types (nearText, nearVector, hybrid, bm25, fetchObjects)
- Filtering with operators (equal, greaterThan, like, containsAny, and/or/not)
- Generative search (RAG) with singlePrompt and groupedTask
- Multi-tenancy with tenant lifecycle management
- Batch imports with insertMany and error handling
- Cross-references between collections
- Named vectors for multi-vector collections
When NOT to use:
- Relational data with complex joins (use a relational database)
- Full-text search without vector component (use a dedicated search engine)
- Key-value caching (use a key-value store)
- Time-series data (use a time-series database)
- Graph traversal queries (use a graph database)
- Browser-side applications (v3 client is Node.js only)
<philosophy>
Philosophy
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:
- Collection-centric design -- All configuration (vectorizer, generative model, reranker, properties) is set at collection creation. Queries operate on collection objects obtained via
.client.collections.use() - Built-in vectorization -- Weaviate can vectorize data automatically using configured modules (text2vec-openai, text2vec-cohere, etc.). You don't need an external embedding pipeline unless you want one.
- Search is a spectrum -- Use
for semantic similarity,nearText
for keyword matching,bm25
for a weighted combination. Thehybrid
parameter controls the vector-vs-keyword balance in hybrid search.alpha - RAG is a search mode, not a separate system -- Switch from
tocollection.query.nearText()
to add LLM generation on top of search results.collection.generate.nearText() - Filters are additive -- Filters narrow results after vector/keyword retrieval. Combine with
andFilters.and()
for complex conditions.Filters.or()
<patterns>
Core Patterns
Pattern 1: Connection Setup
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
Pattern 2: Collection with Vectorizer
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
Pattern 3: Hybrid Search with Filters
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
Pattern 4: Generative Search (RAG)
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>
Decision Framework
Which Search Type?
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?
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)
Single vs Named Vectors?
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
When to Use Multi-Tenancy?
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>
RED FLAGS
High Priority Issues:
- Missing
-- gRPC connections persist and leak memory/file descriptorsclient.close() - Trying to add a default vectorizer after collection creation -- vectorizer must be configured in
. Only named vectors can be added later withcreate()config.addVector() - Querying a multi-tenant collection without
-- all operations fail with an error.withTenant() - Using default query timeout with
-- generative calls need 60+ seconds; default is often too shortgenerate.*
Medium Priority Issues:
- Using
whenreplace()
is intended --update()
deletes all properties not included in the call;replace
mergesupdate - Not checking
response for errors -- partial failures are silent; checkinsertMany
andresponse.hasErrorsresponse.errors - Passing
to hybrid search -- equivalent to pure vector search; usealpha: 1.0
instead for claritynearText - Not specifying
with named vectors -- queries default to the first vector, which may not be the intended onetargetVector
Common Mistakes:
- Using v2 class-based API (
) with v3 client -- the API is completely different; v3 usesclient.schema.classCreator()client.collections.create() - Forgetting to pass API key headers for vectorizer modules --
,X-OpenAI-Api-Key
etc. must be in connection headersX-Cohere-Api-Key - Using
(deprecated) instead ofconnectToWCS()connectToWeaviateCloud() - Adding a property after data import without reindexing -- pre-existing objects won't have that property indexed
Gotchas & Edge Cases:
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 objectsinsertMany
andFilters.and()
take a flat list of filter conditions, NOT nested arrays --Filters.or()
notFilters.and(a, b, c)Filters.and([a, b, c])
withoutfetchObjects()
returns 25 objects by default (server-side default), not all objectslimit- Property names in Weaviate must start with a lowercase letter -- the client silently lowercases the first character
metadata varies by vector distance metric -- cosine distance range [0, 2], not [0, 1]distance
has a server-side maximum of 10,000 objects per call (configurable viadeleteMany
)QUERY_MAXIMUM_RESULTS- Weaviate auto-detects property types on first insert if not defined in the schema -- this can cause type mismatches if first object has atypical data
returnsfetchObjectById
for non-existent IDs, not an empty object -- always check for null before accessing propertiesnull- Cross-references in multi-tenant collections can only reference objects in the same tenant or in non-multi-tenant collections
</red_flags>
<critical_reminders>
CRITICAL REMINDERS
All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering,
, named constants)import type
(You MUST call
when done with the Weaviate client -- it maintains persistent gRPC connections that will leak if not closed)client.close()
(You MUST configure vectorizers at the COLLECTION level during
-- you cannot add a vectorizer after creation, only add new named vectors)client.collections.create()
(You MUST use a SEPARATE
call with client.collections.use()
for multi-tenant queries -- queries without tenant context on multi-tenant collections will fail).withTenant()
(You MUST increase query timeout to 60+ seconds when using
(RAG) submodule -- generative model calls are slow and the default timeout causes failures)generate.*
Failure to follow these rules will cause connection leaks, missing vectorization, multi-tenant query failures, and RAG timeouts.
</critical_reminders>