> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://respan.ai/docs/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://respan.ai/_mcp/server.

# LlamaIndex (tracing)

> Trace LlamaIndex Core and standalone Workflows with Respan using one native instrumentation package.

[LlamaIndex](https://www.llamaindex.ai/) is a framework for building LLM applications with your own data. The existing `respan-instrumentation-llama-index` package traces both LlamaIndex Core and the standalone `llama-index-workflows` runtime, including workflow runs and steps, indexes, query engines, retrievers, LLM calls, embeddings, and agent tool use.

#### Set up Respan

Create an account at [platform.respan.ai](https://platform.respan.ai) and grab an [API key](https://platform.respan.ai/platform/api/api-keys).

Run `npx @respan/cli setup` to set up with your coding agent.

#### Use Respan Gateway

See [LlamaIndex gateway setup](/docs/gateway/llama-index) to route this integration through the Respan gateway.

#### Example projects

* Example repo root: `respan-example-projects/python/tracing/llama-index`

## Setup

#### Install packages

```bash
pip install respan-ai respan-instrumentation-llama-index llama-index llama-index-workflows llama-index-llms-openai llama-index-embeddings-openai
```

#### Set environment variables

```bash
export OPENAI_API_KEY="YOUR_OPENAI_API_KEY"
export RESPAN_API_KEY="YOUR_RESPAN_API_KEY"
```

`OPENAI_API_KEY` is used for the LlamaIndex OpenAI LLM. `RESPAN_API_KEY` exports traces to Respan.

#### Initialize and run

```python
import asyncio

from workflows import Workflow, step
from workflows.events import Event, StartEvent, StopEvent
from respan import Respan
from respan_instrumentation_llama_index import LlamaIndexInstrumentor

respan = Respan(instrumentations=[LlamaIndexInstrumentor()])


class DraftEvent(Event):
    text: str


class DocsWorkflow(Workflow):
    @step
    async def draft(self, event: StartEvent) -> DraftEvent:
        return DraftEvent(text=f"Draft a note about {event.topic}.")

    @step
    async def finalize(self, event: DraftEvent) -> StopEvent:
        return StopEvent(result=f"{event.text} Respan traced both steps.")


async def main():
    result = await DocsWorkflow().run(topic="LlamaIndex Workflows")
    print(result)


asyncio.run(main())
```

#### View your trace

Open the [Traces page](https://platform.respan.ai/platform/traces) to see a workflow root with nested step spans. LlamaIndex Core operations appear in the same trace tree when a workflow step invokes a query engine, retriever, LLM, embedding model, agent, or tool.

## Configuration

| Parameter             | Type           | Default | Description                                                                                                                                   |
| --------------------- | -------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `api_key`             | `str \| None`  | `None`  | Falls back to `RESPAN_API_KEY` env var.                                                                                                       |
| `base_url`            | `str \| None`  | `None`  | Falls back to `RESPAN_BASE_URL` env var.                                                                                                      |
| `instrumentations`    | `list`         | `[]`    | Plugin instrumentations to activate, for example `LlamaIndexInstrumentor()`.                                                                  |
| `customer_identifier` | `str \| None`  | `None`  | Default customer identifier for all spans.                                                                                                    |
| `metadata`            | `dict \| None` | `None`  | Default metadata attached to all spans.                                                                                                       |
| `environment`         | `str \| None`  | `None`  | Environment tag, for example `"production"`.                                                                                                  |
| `capture_content`     | `bool`         | `True`  | `LlamaIndexInstrumentor` option. Set to `False` to omit workflow inputs/results, prompts, responses, document content, and embedding vectors. |

## Attributes

### In Respan()

Set defaults at initialization. These apply to all spans emitted by the LlamaIndex instrumentor.

```python
from respan import Respan
from respan_instrumentation_llama_index import LlamaIndexInstrumentor

respan = Respan(
    instrumentations=[LlamaIndexInstrumentor()],
    customer_identifier="user_123",
    metadata={"service": "rag-api", "version": "1.0.0"},
)
```

### With propagate\_attributes

Override per request using a context scope.

```python
from llama_index.core import Document, SummaryIndex
from respan import Respan, propagate_attributes, workflow
from respan_instrumentation_llama_index import LlamaIndexInstrumentor

respan = Respan(instrumentations=[LlamaIndexInstrumentor()])

@workflow(name="rag_request")
def run_query(question: str):
    index = SummaryIndex.from_documents([
        Document(text="Respan captures traces from LlamaIndex applications.")
    ])
    return index.as_query_engine().query(question)

def handle_request(user_id: str, question: str):
    with propagate_attributes(
        customer_identifier=user_id,
        thread_identifier="conv_abc_123",
        metadata={"plan": "pro"},
    ):
        response = run_query(question)
        print(response)
```

| Attribute             | Type   | Description                                           |
| --------------------- | ------ | ----------------------------------------------------- |
| `customer_identifier` | `str`  | Identifies the end user in Respan analytics.          |
| `thread_identifier`   | `str`  | Groups related messages into a conversation.          |
| `metadata`            | `dict` | Custom key-value pairs. Merged with default metadata. |

## Decorators (optional)

Respan decorators are not required for LlamaIndex instrumentation. Core query engines, retrievers, agents, tools, embeddings, and LLM calls are captured automatically. Standalone Workflows runs and `@step` methods also emit their own workflow and task spans. Use Respan `@workflow` and `@task` only when you want an additional application-level grouping around several operations.

```python
from llama_index.core import Document, SummaryIndex
from respan import Respan, task, workflow
from respan_instrumentation_llama_index import LlamaIndexInstrumentor

respan = Respan(instrumentations=[LlamaIndexInstrumentor()])

@task(name="build_index")
def build_index():
    return SummaryIndex.from_documents([
        Document(text="Respan traces LlamaIndex index and query operations."),
        Document(text="LlamaIndex combines retrievers, query engines, and agents."),
    ])

@workflow(name="rag_pipeline")
def rag_pipeline(question: str):
    index = build_index()
    return index.as_query_engine().query(question)

print(rag_pipeline("Summarize the documents."))
respan.flush()
```

## Examples

### Query engine

Query engines are captured with nested retriever, synthesizer, and LLM spans.

```python
from llama_index.core import Document, SummaryIndex

index = SummaryIndex.from_documents([
    Document(text="Respan captures traces for LLM calls and workflow steps."),
    Document(text="LlamaIndex can combine query engines, retrievers, and tools."),
])
query_engine = index.as_query_engine()

response = query_engine.query("What do the documents say?")
print(response)
```

### Embeddings

Embedding calls are captured as `embedding` logs. When content capture is enabled, the full returned vector is recorded in the canonical entity output so retrieval behavior can be reproduced and inspected.

```python
from llama_index.embeddings.openai import OpenAIEmbedding

embedding_model = OpenAIEmbedding(model="text-embedding-3-small")
embedding = embedding_model.get_text_embedding(
    "LlamaIndex uses embeddings to retrieve relevant document chunks."
)
print(len(embedding))
```

### Tool-use agent

LlamaIndex ReAct agents emit agent, tool, and LLM spans in the same trace tree.

```python
import asyncio
from llama_index.core.agent.workflow import ReActAgent
from llama_index.core.tools import FunctionTool

def multiply_numbers(a: int, b: int) -> int:
    return a * b

multiply_tool = FunctionTool.from_defaults(
    fn=multiply_numbers,
    name="multiply_numbers",
    description="Multiply two integers and return the product.",
)
agent = ReActAgent(
    tools=[multiply_tool],
    system_prompt="Use tools when arithmetic is required.",
    streaming=False,
)

async def main():
    response = await agent.run(
        user_msg="Use the multiply_numbers tool to calculate 7 multiplied by 6."
    )
    print(response)

asyncio.run(main())
```