> ## Documentation Index
> Fetch the complete documentation index at: https://docs.zespan.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Vectra

> Trace vectra-js / vectra-py RAG pipelines with ZespanVectraCallbackHandler — ingestion, retrieval, reranking, and generation.

<Note>
  Available for: **Python** and **TypeScript**.
</Note>

[Vectra](https://github.com/iamabhishek-n/vectra-js) is a modular RAG pipeline SDK (`Load → Chunk → Embed → Store → Retrieve → Rerank → Plan → Ground → Generate → Stream`). It dispatches lifecycle events to any object in its `callbacks` config array that implements the matching method — no base class required. `ZespanVectraCallbackHandler` implements that interface directly, so every stage of the pipeline becomes a Zespan span with no changes to how you call Vectra.

## Installation

<CodeGroup>
  ```bash TypeScript theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  npm install @zespan/sdk vectra-js
  ```

  ```bash Python theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  pip install zespan vectra-py
  ```
</CodeGroup>

## Setup

<CodeGroup>
  ```typescript TypeScript theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  import { VectraClient } from "vectra-js";
  import { zespan, ZespanVectraCallbackHandler } from "@zespan/sdk";

  zespan.init({ apiKey: process.env.ZESPAN_API_KEY! });

  const client = new VectraClient({
    embedding: { provider: "openai", apiKey: process.env.OPENAI_API_KEY! },
    llm: { provider: "openai", apiKey: process.env.OPENAI_API_KEY! },
    database: { type: "postgres", clientInstance: pgClient, tableName: "docs" },
    callbacks: [new ZespanVectraCallbackHandler()],
  });
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  import os
  import zespan
  from vectra import VectraClient
  from zespan.integrations.vectra import ZespanVectraCallbackHandler

  zespan.init(api_key=os.environ["ZESPAN_API_KEY"])

  client = VectraClient(
      embedding={"provider": "openai", "api_key": os.environ["OPENAI_API_KEY"]},
      llm={"provider": "openai", "api_key": os.environ["OPENAI_API_KEY"]},
      database={"type": "postgres", "client_instance": pg_client, "table_name": "docs"},
      callbacks=[ZespanVectraCallbackHandler()],
  )
  ```
</CodeGroup>

## Example

<CodeGroup>
  ```typescript TypeScript theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  await client.ingestDocuments("./docs/handbook.pdf");
  const result = await client.queryRAG("What's our refund policy?");
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"one-dark-pro"}}
  client.ingest_documents("./docs/handbook.pdf")
  result = client.query_rag("What's our refund policy?")
  ```
</CodeGroup>

## What gets captured

| Stage                                            | Span kind                                                       | Fields                                           |
| ------------------------------------------------ | --------------------------------------------------------------- | ------------------------------------------------ |
| Ingestion (`ingestDocuments`/`ingest_documents`) | `embedding`                                                     | Chunk count                                      |
| Retrieval + reranking                            | `retriever`                                                     | Query, retrieved count, reranked count           |
| Generation                                       | `llm`                                                           | Prompt/completion text (respects `storePrompts`) |
| Errors                                           | attached to whichever stage was in flight, or a standalone span | Error message                                    |

<Warning>
  Vectra's callback API doesn't pass a per-call request ID into the callback arguments — only the query, prompt, or counts for that stage. The handler correlates a query's retrieval and generation spans using the ambient Zespan trace context, so wrap each request in [`withZespanTrace()`](/sdk/manual-spans) (`with_zespan_context()` in Python) for correct span grouping under concurrent requests. Without an ambient trace, spans fall back to a single shared slot — correct for one in-flight query at a time, not for concurrent ones on the same client.
</Warning>

<Note>
  Vectra's callbacks pass retrieval **counts**, not the retrieved chunks themselves — the retrieval span records how many documents came back, not their content. If you want chunk text on the trace, call [`recordRetrieval(docs, { query })`](/sdk/manual-spans#recording-retrieved-documents) (`record_retrieval` in Python) yourself alongside `queryRAG()`/`query_rag()`.
</Note>
