Skills api-vector-db-chroma
Chroma vector database -- collection management, automatic embedding, metadata filtering, document storage, query patterns
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-chroma/skills/api-vector-db-chroma" ~/.claude/skills/agents-inc-skills-api-vector-db-chroma && rm -rf "$T"
dist/plugins/api-vector-db-chroma/skills/api-vector-db-chroma/SKILL.mdChroma Patterns
Quick Guide: Use
(v3.x) withchromadbfor automatic embedding. Chroma auto-embeds documents if no embeddings are provided -- just pass@chroma-core/default-embedanddocumentstoids. Usecollection.add()for metadata filtering andwherefor document content filtering (whereDocument,$contains). Default distance metric is$regex(Euclidean); usel2for most embedding models viacosine. Query results return nested arrays (configuration: { hnsw: { space: "cosine" } }) because queries are batched -- always accessids: string[][]for a single query. Include only the fields you need via theresults.ids[0]parameter to reduce payload size.include
<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 install
alongside @chroma-core/default-embed
-- the default embedding function ships as a separate package since v3)chromadb
(You MUST access query results as nested arrays --
, results.ids[0]
-- because Chroma batches queries and returns results.documents[0]
not string[][]
)string[]
(You MUST use the
parameter for HNSW settings -- the legacy configuration
approach is deprecated)metadata: { "hnsw:space": "cosine" }
(You MUST use flat metadata values only (string, number, boolean, typed arrays) -- nested objects are not supported and will be rejected)
</critical_requirements>
Examples
- Core Patterns -- Client setup, collection management, add, query, get, update, upsert, delete
- Metadata Filtering -- Filter operators, compound filters, document content filters, whereDocument
- Embedding Functions -- Default, OpenAI, custom embedding functions, provider packages
Additional resources:
- reference.md -- API quick reference, filter operators, include options, limits, production checklist
Auto-detection: Chroma, chromadb, ChromaClient, CloudClient, createCollection, getOrCreateCollection, collection.add, collection.query, collection.get, collection.upsert, queryTexts, queryEmbeddings, nResults, whereDocument, $contains, @chroma-core/default-embed, @chroma-core/openai, EmbeddingFunction, vector database, semantic search, embedding, RAG retrieval, hnsw:space
When to use:
- Semantic search over document embeddings (RAG retrieval)
- Rapid prototyping with automatic embedding generation (no external embedding pipeline needed)
- Metadata-filtered vector search with compound logical operators
- Document content filtering with
and$contains$regex - Local development with in-process or Docker-based Chroma server
Key patterns covered:
- Client setup (HTTP, Cloud, Docker)
- Collection management (create, get, delete, configure HNSW)
- Document CRUD with automatic embedding (add, query, get, update, upsert, delete)
- Metadata filtering (
) with comparison, set, array, and logical operatorswhere - Document content filtering (
) withwhereDocument
and$contains$regex - Embedding function configuration (default, OpenAI, custom)
- Query result handling (nested array structure, include options)
When NOT to use:
- Full-text search with complex boolean ranking (use a dedicated search engine)
- Relational data with joins and transactions (use a relational database)
- Multi-modal image+text embeddings in TypeScript (currently Python-only in Chroma)
- High-scale production with millions of vectors and strict SLAs (evaluate managed vector databases)
<philosophy>
Philosophy
Chroma is a lightweight, developer-friendly embedding database designed for rapid prototyping and production RAG applications. The core principle: pass documents in, get relevant results out -- Chroma handles embedding automatically.
Core principles:
- Documents first, vectors optional -- Unlike most vector databases, Chroma can embed documents automatically using a configured embedding function. You never need to manage embeddings directly unless you want to.
- Collections are self-contained -- Each collection has its own embedding function, distance metric, and HNSW configuration. No global index management needed.
- Metadata is for filtering, documents are for content -- Use
for structured metadata filters andwhere
for full-text content filters. Both can be combined in a single query.whereDocument - Batteries included -- The default embedding function (
viaall-MiniLM-L6-v2
) works out of the box for English text. Swap to OpenAI, Cohere, or any provider with a single package change.@chroma-core/default-embed - Query results are batched -- Chroma supports multiple queries in a single call. Results are always nested arrays (
), even for single queries. Always accessstring[][]
for the first query's results.[0]
<patterns>
Core Patterns
Pattern 1: Client Initialization
Always pass the server URL explicitly from an environment variable -- never rely on the implicit
http://localhost:8000 default. See examples/core.md for HTTP, Cloud, and token-authenticated client examples.
const chromaUrl = process.env.CHROMA_URL; if (!chromaUrl) throw new Error("CHROMA_URL environment variable is required"); return new ChromaClient({ path: chromaUrl });
Pattern 2: Collection with Distance Metric
Use the
configuration parameter for HNSW settings -- never the deprecated metadata: { "hnsw:space": "cosine" } approach. See examples/core.md.
const collection = await client.createCollection({ name: COLLECTION_NAME, configuration: { hnsw: { space: "cosine" } }, });
Pattern 3: Add Documents with Automatic Embedding
Pass
documents and ids -- Chroma embeds automatically. Either documents or embeddings must be provided; metadata alone is insufficient. See examples/core.md.
await collection.add({ ids: articles.map((a) => a.id), documents: articles.map((a) => a.text), metadatas: articles.map((a) => ({ category: a.category })), });
Pattern 4: Query with Metadata and Document Filters
Combine
where (metadata) and whereDocument (content) filters. Results are nested arrays -- always access [0] for single-query results. See examples/metadata-filtering.md for all operators.
const results = await collection.query({ queryTexts: ["machine learning fundamentals"], nResults: N_RESULTS, where: { $and: [{ category: { $eq: "tutorial" } }, { year: { $gte: 2023 } }], }, whereDocument: { $contains: "neural network" }, include: ["documents", "metadatas", "distances"], }); // results.ids[0] -- nested array, access [0] for first query
Pattern 5: Get with Pagination
Use
get() with limit/offset for non-similarity retrieval. Unlike query(), get() returns flat arrays. See examples/core.md.
const results = await collection.get({ where: { category: { $eq: category } }, limit: PAGE_SIZE, offset, include: ["documents", "metadatas"], });
Pattern 6: Upsert for Idempotent Operations
Use
upsert() instead of add() for create-or-update semantics -- safer for pipelines that run multiple times. See examples/core.md.
</patterns>await collection.upsert({ ids: docs.map((d) => d.id), documents: docs.map((d) => d.text), metadatas: docs.map((d) => d.metadata), });
<decision_framework>
Decision Framework
Which Distance Metric?
Which distance metric should I use? |-- Using embeddings from a language model? -> cosine (normalized, most common) |-- Need dot product similarity? -> ip (inner product) |-- Comparing raw feature vectors? -> l2 (Euclidean, Chroma default) '-- Unsure? -> cosine (safe default for most embedding models)
Which Embedding Function?
Which embedding function should I use? |-- Quick prototyping, English text? -> @chroma-core/default-embed (all-MiniLM-L6-v2, runs locally) |-- Need high-quality embeddings? -> @chroma-core/openai (text-embedding-3-small) |-- Have your own embedding pipeline? -> Pass embeddings directly (skip embedding function) |-- Need custom model? -> Implement EmbeddingFunction interface '-- Want all providers? -> npm install @chroma-core/all
Where vs WhereDocument?
How should I filter results? |-- Structured attributes (category, year, status)? -> where (metadata filter) |-- Full-text content search? -> whereDocument ($contains, $regex) |-- Both? -> Combine where + whereDocument in same query '-- Need exact match on specific IDs? -> get({ ids: [...] })
ChromaClient vs CloudClient?
Which client should I use? |-- Local development or self-hosted? -> ChromaClient({ path: "http://localhost:8000" }) |-- Chroma Cloud (managed)? -> CloudClient({ apiKey, tenant, database }) |-- Docker deployment? -> ChromaClient with Docker host URL '-- Testing? -> ChromaClient against local Docker container
</decision_framework>
<red_flags>
RED FLAGS
High Priority Issues:
- Accessing query results as flat arrays instead of nested --
isresults.ids
, notstring[][]
; always usestring[]
for single-query resultsresults.ids[0] - Missing
package -- since v3, the default embedding function ships separately;@chroma-core/default-embednpm install chromadb @chroma-core/default-embed - Using deprecated
for HNSW config -- usemetadata: { "hnsw:space": "cosine" }
insteadconfiguration: { hnsw: { space: "cosine" } } - Nested objects in metadata -- Chroma only supports flat key-value metadata; nested objects are rejected
Medium Priority Issues:
- Not specifying
in queries -- default includes vary (include
returns documents, metadatas, distances;query
returns documents, metadatas); explicitly setget
for clarity and to control payload sizeinclude - Using
(default) whenl2
is appropriate -- most embedding models are normalized for cosine similarity;cosine
may produce worse resultsl2 - Calling
withoutadd()
ordocuments
-- at least one must be provided; metadata alone is insufficientembeddings - Not handling empty results --
may be an empty array; check length before processingresults.ids[0]
Common Mistakes:
- Passing
ANDqueryEmbeddings
together -- use one or the other, not bothqueryTexts - Expecting
to create missing records --update()
silently ignores non-existent IDs; useupdate()
for create-or-update semanticsupsert() - Calling
with no arguments -- deletes nothing (not everything); passdelete()
orids
to target specific recordswhere - Using
/$gt
on string metadata -- comparison operators only work on numeric values (int or float)$lt
Gotchas & Edge Cases:
- HNSW configuration (
,space
,ef_construction
) cannot be changed after collection creation -- you must delete and recreate the collectionmax_neighbors
returns total records in the collection, not filtered counts -- there is no filtered count APIcollection.count()
returns the firstpeek()
items (default 10) in insertion order, not by relevance -- useful for debugging, not queryinglimit
in$contains
is case-sensitive -- searching for "Neural" will not match "neural"whereDocument
in$regex
uses full regex syntax but can be slow on large collectionswhereDocument- Array metadata values (
,string[]
) must be homogeneous -- mixing types within an array is rejectednumber[] - Metadata keys are case-sensitive --
andCategory
are different fieldscategory - The
default is 10 if not specified innResultsquery() - Multimodal embedding (images + text) is currently Python-only -- TypeScript support is not yet available
</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 install
alongside @chroma-core/default-embed
-- the default embedding function ships as a separate package since v3)chromadb
(You MUST access query results as nested arrays --
, results.ids[0]
-- because Chroma batches queries and returns results.documents[0]
not string[][]
)string[]
(You MUST use the
parameter for HNSW settings -- the legacy configuration
approach is deprecated)metadata: { "hnsw:space": "cosine" }
(You MUST use flat metadata values only (string, number, boolean, typed arrays) -- nested objects are not supported and will be rejected)
Failure to follow these rules will cause embedding failures, incorrect result access, deprecated configuration warnings, and rejected metadata.
</critical_reminders>