LlamaIndex (tracing)

LlamaIndex 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.

Create an account at platform.respan.ai and grab an API key.

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

See LlamaIndex gateway setup to route this integration through the Respan gateway.

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

Setup

1

Install packages

$pip install respan-ai respan-instrumentation-llama-index llama-index llama-index-workflows llama-index-llms-openai llama-index-embeddings-openai
2

Set environment variables

$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.

3

Initialize and run

1import asyncio
2
3from workflows import Workflow, step
4from workflows.events import Event, StartEvent, StopEvent
5from respan import Respan
6from respan_instrumentation_llama_index import LlamaIndexInstrumentor
7
8respan = Respan(instrumentations=[LlamaIndexInstrumentor()])
9
10
11class DraftEvent(Event):
12 text: str
13
14
15class DocsWorkflow(Workflow):
16 @step
17 async def draft(self, event: StartEvent) -> DraftEvent:
18 return DraftEvent(text=f"Draft a note about {event.topic}.")
19
20 @step
21 async def finalize(self, event: DraftEvent) -> StopEvent:
22 return StopEvent(result=f"{event.text} Respan traced both steps.")
23
24
25async def main():
26 result = await DocsWorkflow().run(topic="LlamaIndex Workflows")
27 print(result)
28
29
30asyncio.run(main())
4

View your trace

Open the Traces page 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

ParameterTypeDefaultDescription
api_keystr | NoneNoneFalls back to RESPAN_API_KEY env var.
base_urlstr | NoneNoneFalls back to RESPAN_BASE_URL env var.
instrumentationslist[]Plugin instrumentations to activate, for example LlamaIndexInstrumentor().
customer_identifierstr | NoneNoneDefault customer identifier for all spans.
metadatadict | NoneNoneDefault metadata attached to all spans.
environmentstr | NoneNoneEnvironment tag, for example "production".
capture_contentboolTrueLlamaIndexInstrumentor 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.

1from respan import Respan
2from respan_instrumentation_llama_index import LlamaIndexInstrumentor
3
4respan = Respan(
5 instrumentations=[LlamaIndexInstrumentor()],
6 customer_identifier="user_123",
7 metadata={"service": "rag-api", "version": "1.0.0"},
8)

With propagate_attributes

Override per request using a context scope.

1from llama_index.core import Document, SummaryIndex
2from respan import Respan, propagate_attributes, workflow
3from respan_instrumentation_llama_index import LlamaIndexInstrumentor
4
5respan = Respan(instrumentations=[LlamaIndexInstrumentor()])
6
7@workflow(name="rag_request")
8def run_query(question: str):
9 index = SummaryIndex.from_documents([
10 Document(text="Respan captures traces from LlamaIndex applications.")
11 ])
12 return index.as_query_engine().query(question)
13
14def handle_request(user_id: str, question: str):
15 with propagate_attributes(
16 customer_identifier=user_id,
17 thread_identifier="conv_abc_123",
18 metadata={"plan": "pro"},
19 ):
20 response = run_query(question)
21 print(response)
AttributeTypeDescription
customer_identifierstrIdentifies the end user in Respan analytics.
thread_identifierstrGroups related messages into a conversation.
metadatadictCustom 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.

1from llama_index.core import Document, SummaryIndex
2from respan import Respan, task, workflow
3from respan_instrumentation_llama_index import LlamaIndexInstrumentor
4
5respan = Respan(instrumentations=[LlamaIndexInstrumentor()])
6
7@task(name="build_index")
8def build_index():
9 return SummaryIndex.from_documents([
10 Document(text="Respan traces LlamaIndex index and query operations."),
11 Document(text="LlamaIndex combines retrievers, query engines, and agents."),
12 ])
13
14@workflow(name="rag_pipeline")
15def rag_pipeline(question: str):
16 index = build_index()
17 return index.as_query_engine().query(question)
18
19print(rag_pipeline("Summarize the documents."))
20respan.flush()

Examples

Query engine

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

1from llama_index.core import Document, SummaryIndex
2
3index = SummaryIndex.from_documents([
4 Document(text="Respan captures traces for LLM calls and workflow steps."),
5 Document(text="LlamaIndex can combine query engines, retrievers, and tools."),
6])
7query_engine = index.as_query_engine()
8
9response = query_engine.query("What do the documents say?")
10print(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.

1from llama_index.embeddings.openai import OpenAIEmbedding
2
3embedding_model = OpenAIEmbedding(model="text-embedding-3-small")
4embedding = embedding_model.get_text_embedding(
5 "LlamaIndex uses embeddings to retrieve relevant document chunks."
6)
7print(len(embedding))

Tool-use agent

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

1import asyncio
2from llama_index.core.agent.workflow import ReActAgent
3from llama_index.core.tools import FunctionTool
4
5def multiply_numbers(a: int, b: int) -> int:
6 return a * b
7
8multiply_tool = FunctionTool.from_defaults(
9 fn=multiply_numbers,
10 name="multiply_numbers",
11 description="Multiply two integers and return the product.",
12)
13agent = ReActAgent(
14 tools=[multiply_tool],
15 system_prompt="Use tools when arithmetic is required.",
16 streaming=False,
17)
18
19async def main():
20 response = await agent.run(
21 user_msg="Use the multiply_numbers tool to calculate 7 multiplied by 6."
22 )
23 print(response)
24
25asyncio.run(main())