Skip to main content

Trace Spans

This page is the reference for the spans Agentic GraphRAG records when you pass it a tracer. The library emits every span name, attribute, and provider value below.

Tracing is opt-in per object. A tracer of None opens no recorded span and costs nothing. Agentic GraphRAG never installs a global provider. You inject the tracer you want. See Trace an agent run for how to build and pass one.

How the span families nest​

Each box is a span family. An arrow points from a parent span to the spans that nest below it.

BoxSpan names
Graph call rootagrag.ingestion.add, update, delete_document, consolidate, detect_communities, and the other root spans in "Ingestion root spans"
Extraction spansagrag.extraction.*
Cutover jobagrag.ingestion.cutover_job and agrag.ingestion.ingest_chunks
Resolution, Merge, Storage spansagrag.resolution.*, agrag.merge.*, agrag.storage.*
Community spansagrag.community.*
LLM spansagrag.llm.call, agrag.llm.attempt, agrag.llm.request
Agent tool callThe OpenInference TOOL span of an agent run
Search root and retriever spansagrag.retrieval.search and the spans in "The retrieval span tree"
Store and embedding spansagrag.graphdb.*, agrag.vectordb.*, agrag.embedding.*, only when you pass the same tracer to the stores and the embedder

The LLM span tree​

Every BAML-backed path produces the same three spans, nested. BAML collects data during the attempt. The path writes the request span after the attempt finishes. The span carries the real request and response.

agrag.extraction.extract_chunk (INTERNAL)
agrag.extraction.baml (INTERNAL)
agrag.llm.call (INTERNAL)
agrag.llm.attempt (INTERNAL)
agrag.llm.request (CLIENT, kind LLM)
SpanKindAttributes
agrag.llm.callINTERNALagrag.llm.function, agrag.llm.attempt_count
agrag.llm.attemptINTERNALagrag.llm.attempt (1-based)
agrag.llm.requestCLIENTthe table below

agrag.llm.function is the BAML function name, such as ExtractEntitiesAndRelations. The attempt span records the exception when an attempt fails. The call span reports ERROR when the call as a whole fails.

Ingestion spans​

SpanAttributes
agrag.ingestion.load_documentagrag.source_uri, agrag.loader_name, agrag.normalization (JSON)
agrag.ingestion.chunk_documentagrag.document_key, agrag.chunker.strategy, agrag.chunker.hash, agrag.chunker.settings (JSON), agrag.chunker.rule (a rule index or fallback), agrag.chunks_produced
agrag.storage.embed_chunksagrag.embedding.heading_context (bool, whether the embedder got the heading path)

Ingestion root spans​

Every public Graph call opens one root span. The spans in the sections below nest under it.

SpanOpens whenAttributes
agrag.ingestion.openGraph.open runsnone
agrag.ingestion.resume_incomplete_jobsGraph.open recovers document jobs that an earlier run left unfinishednone
agrag.ingestion.addGraph.add runsnone
agrag.ingestion.updateGraph.update runsnone
agrag.ingestion.delete_documentGraph.delete_document runsnone
agrag.ingestion.consolidateGraph.consolidate runsnone
agrag.ingestion.detect_communitiesGraph.detect_communities runsnone
agrag.ingestion.reevaluateGraph.reevaluate runsagrag.entity_count
agrag.ingestion.deactivate_matchGraph.deactivate_match runsagrag.match_id
agrag.ingestion.cutover_jobAn add, update, or delete runs as one document jobagrag.verb, agrag.document_key, agrag.job_id
agrag.ingestion.ingest_chunksThe shared step that resolves, merges, and stores extracted chunksnone

The ingestion span tree​

One add call with one chunk and the local extractor produces this tree. load_document appears only for source= input. Store and embedding spans (agrag.graphdb.*, agrag.embedding.*, and agrag.vectordb.* when a vector store is set) nest below the step that calls them.

agrag.ingestion.add
agrag.ingestion.load_document only with source=
agrag.ingestion.chunk_document
agrag.extraction.extract_chunk one per chunk
agrag.extraction.gliner or agrag.extraction.baml, agrag.extraction.escalating
agrag.extraction.model_load first call only
agrag.ingestion.cutover_job
agrag.ingestion.ingest_chunks
agrag.resolution.global_exact_match
agrag.resolution.candidate_generation
agrag.resolution.resolve
agrag.resolution.exact_fuzzy_pass
agrag.resolution.embedding_tier
agrag.resolution.precluster_tier
agrag.resolution.llm_tier only with boundary pairs
agrag.resolution.llm_batch
agrag.merge.merge_group one per entity group
agrag.storage.upsert_chunks
agrag.storage.upsert_documents
agrag.storage.embed_chunks
agrag.storage.upsert_relations
agrag.storage.upsert_mentioned_in
agrag.storage.embed_survivors
agrag.merge.rebuild_components

Resolution, merge, and storage spans​

SpanAttributes
agrag.resolution.global_exact_matchagrag.mention_count, agrag.exact_match_hits
agrag.resolution.candidate_generationagrag.mention_count, agrag.persisted_candidate_count, agrag.in_batch_candidate_count
agrag.resolution.resolveagrag.entity_count, agrag.pair_count, agrag.ambiguous_count, agrag.failed_llm_requests, agrag.cap_truncated_pairs
agrag.resolution.exact_fuzzy_passagrag.pair_count, agrag.exact_match_count, agrag.fuzzy_fast_path_count, agrag.fuzzy_uncertain_count
agrag.resolution.embedding_tieragrag.fuzzy_uncertain_count, agrag.hard_merge_count, agrag.ambiguous_count
agrag.resolution.precluster_tieragrag.boundary_pairs_before, agrag.auto_merged_count, agrag.boundary_pairs_after
agrag.resolution.llm_tieragrag.boundary_pair_count, agrag.selected_pair_count, agrag.cap_truncated_pairs, agrag.ambiguous_count, agrag.failed_llm_requests
agrag.resolution.llm_batchagrag.batch_size, agrag.uncertain_count
agrag.merge.merge_groupagrag.mention_count, agrag.conflicts_resolved
agrag.merge.rebuild_componentsagrag.component_count
agrag.merge.rebuild_componentagrag.member_count
agrag.merge.deactivate_componentagrag.match_id
agrag.storage.upsert_chunksagrag.record_count, agrag.nodes_written
agrag.storage.upsert_documentsagrag.record_count, agrag.nodes_written
agrag.storage.upsert_relationsagrag.record_count, agrag.relationships_written
agrag.storage.upsert_mentioned_inagrag.record_count, agrag.relationships_written
agrag.storage.embed_survivorsnone
agrag.community.embed_batchagrag.batch_size

agrag.resolution.llm_tier and agrag.resolution.llm_batch open only when boundary pairs reach the model. Like agrag.resolution.llm_verify, a failed model call there counts as agrag.failed_llm_requests and does not set the span to ERROR.

Graph store spans​

The Neo4j store opens these spans. Reads and writes carry the query text and the value of every parameter except vectors. A trace shows what each query asked for.

SpanAttributes
agrag.graphdb.build_drivernone
agrag.graphdb.execute_readdb.system.name, db.namespace, db.query.text, db.query.parameter.<name> for each non-vector parameter, agrag.transactional (inside a transaction)
agrag.graphdb.execute_writethe same as execute_read
agrag.graphdb.transactionnone
agrag.graphdb.upsert_nodesdb.collection.name (the label), agrag.record_count, agrag.written, agrag.failures_count, db.operation.batch.size (only for a write of more than one record)
agrag.graphdb.upsert_relationsagrag.record_count, agrag.written, agrag.failures_count, db.operation.batch.size (only for a write of more than one record)
agrag.graphdb.load_entitiesagrag.requested_count, agrag.loaded_count
agrag.graphdb.vector_searchdb.collection.name (the label), agrag.limit, agrag.k_final, agrag.index_missing (when the index does not exist. The search then returns no hits)

Vector store spans​

Qdrant, Weaviate, and Milvus open the same names. db.system.name is qdrant, weaviate, or milvus. Only Qdrant opens query_points, one for each arm of its two-search hybrid query.

SpanAttributes
agrag.vectordb.build_clientnone
agrag.vectordb.upsertdb.collection.name, agrag.record_count
agrag.vectordb.upsert_batchdb.system.name, db.collection.name, agrag.batch_size
agrag.vectordb.searchdb.system.name, db.collection.name, agrag.limit
agrag.vectordb.hybrid_searchdb.collection.name, agrag.limit, agrag.alpha
agrag.vectordb.query_pointsdb.system.name, db.collection.name, agrag.query_arm (dense or sparse)
agrag.vectordb.scrolldb.system.name, db.collection.name, agrag.limit
agrag.vectordb.retrievedb.system.name, db.collection.name
agrag.vectordb.countdb.system.name, db.collection.name
agrag.vectordb.deletedb.system.name, db.collection.name
agrag.vectordb.commit_pendingdb.collection.name, agrag.job_id
agrag.vectordb.delete_pendingdb.collection.name, agrag.job_id

Embedding spans​

SpanAttributes
agrag.embedding.model_loadagrag.model
agrag.embedding.embedagrag.text_count, agrag.cache_hit_count, agrag.model (dense embedder, every call)
agrag.embedding.encodeagrag.text_count, agrag.cache_hit_count (dense embedder, cache misses only)
agrag.embedding.query_embedagrag.text_count (keyword embedder for Qdrant hybrid search)

Retrieval loading spans and the agent span​

SpanAttributes
agrag.retrieval.load_communitiesagrag.requested_count, agrag.loaded_count
agrag.retrieval.load_resolved_entitiesagrag.requested_count, agrag.loaded_count
agrag.retrieval.community_contextagrag.seed_count, agrag.top_k
agrag.agents.runnone. Only the simple agent (used when the agents extra is not installed) opens it. The full loop opens OpenInference spans instead.

Domain spans by path​

Each LLM path also opens one small domain span carrying its own ids and counts.

PathDomain spanAttributes
Extraction, BAMLagrag.extraction.bamlagrag.chunk_id, agrag.entities_extracted, agrag.relations_extracted, agrag.extraction.heading_context (bool, whether a section line was sent)
Extraction, GLiNERagrag.extraction.gliner, and agrag.extraction.model_load around the one-time model buildthe same counts. agrag.model is on the load span
Extraction, escalatingagrag.extraction.escalatingagrag.chunk_id, agrag.escalated (bool)
Resolutionagrag.resolution.llm_verifyagrag.pair_count, agrag.match_count, agrag.uncertain_count, agrag.request_failed (bool)
Mergeagrag.merge.resolve_descriptionagrag.description_count, agrag.summarized (bool)
Communityagrag.community.report_batchagrag.batch_size
Chunk retrievalagrag.retrieval.load_parentsagrag.parent_count, agrag.result.count, retrieval.documents (JSON array of attached parent chunks)
Text2cypheragrag.retrieval.generate_cypheragrag.is_repair (bool)
Judgeagrag.eval.judgeagrag.eval.judge_model

Two of these are conditional:

  • agrag.merge.resolve_description opens only when the field conflicted. The field conflicted when more than one distinct candidate exists. A field every mention agrees on adds no span.
  • agrag.retrieval.generate_cypher opens on every generation, and agrag.is_repair tells a first attempt from a retry after a failure.

agrag.resolution.llm_verify never carries an ERROR status. A failed LLM call resolves to NO_MATCH, not an error. The span stays UNSET and sets agrag.request_failed instead.

The retrieval span tree​

One search call fans out to the recipe's retrievers concurrently. Their spans are siblings under the root. The agrag.graphdb.*, agrag.vectordb.* and agrag.embedding.* spans nest below these whenever the caller passed the same tracer to the stores and the embedder.

agrag.retrieval.search RETRIEVER
agrag.retrieval.entity RETRIEVER, one per retriever
agrag.retrieval.allowed_entity_ids only with a document scope
agrag.retrieval.entity_search
agrag.retrieval.vector_search one per adaptive pass
agrag.retrieval.active_member_ids
agrag.graphdb.load_entities
agrag.retrieval.resolved_entity_search
agrag.retrieval.chunk RETRIEVER
agrag.retrieval.vector_search
agrag.retrieval.load_chunks
agrag.retrieval.community RETRIEVER
agrag.retrieval.text2cypher RETRIEVER
agrag.retrieval.generate_cypher
agrag.retrieval.execute_cypher one per attempt
agrag.graphdb.load_entities one per entity row
agrag.retrieval.fuse
agrag.retrieval.bfs RETRIEVER, when recipe.bfs
agrag.retrieval.community_expand when recipe.community_expand
agrag.retrieval.rerank.cross_encoder or rerank.node_distance
agrag.retrieval.rerank.model_load only on a cache miss

agrag.retrieval.find_entity and agrag.retrieval.traverse are RETRIEVER roots for direct calls that bypass search. agrag.retrieval.list_relationship_types returns strings and carries no kind. Inside an agent run, the whole tree nests under the OpenInference TOOL span of the tool call that made it.

Attributes​

SpanAttributes
agrag.retrieval.searchagrag.recipe.methods, agrag.recipe.limit, agrag.recipe.bfs, agrag.recipe.community_expand, agrag.recipe.reranker, agrag.failed_methods (when a method failed)
retrievers (entity, chunk, community, text2cypher, bfs)agrag.limit. bfs also agrag.seed_count, agrag.depth, agrag.direction. text2cypher also agrag.cypher
agrag.retrieval.find_entity / traverseagrag.seed_ids, agrag.relation_type, agrag.direction, agrag.depth, agrag.limit, agrag.community_expand on traverse
agrag.retrieval.list_relationship_typesagrag.seed_ids, agrag.relation_type_filter, agrag.direction, agrag.result_count, agrag.result_types
agrag.retrieval.vector_searchagrag.collection, agrag.store (vector_store or graph_native), agrag.labels, agrag.limit, agrag.hit_count, agrag.hit_ids, agrag.hit_scores
agrag.retrieval.entity_search / resolved_entity_searchagrag.limit, agrag.passes, agrag.hit_count
agrag.retrieval.load_*agrag.requested_count, agrag.loaded_count
agrag.retrieval.allowed_entity_idsagrag.document_count, agrag.entity_count
agrag.retrieval.active_member_idsagrag.requested_count, agrag.superseded_count
agrag.retrieval.execute_cypheragrag.is_repair, agrag.row_count
agrag.retrieval.fuseagrag.rrf_k, agrag.fuse.methods, agrag.fuse.method_counts
agrag.retrieval.community_expand / community_contextagrag.seed_count, agrag.top_k, agrag.added_count on community_expand
agrag.retrieval.rerank.cross_encoderagrag.model, agrag.input_count, agrag.min_score (when set), agrag.skipped (when the extra is missing)
agrag.retrieval.rerank.model_loadagrag.model
agrag.retrieval.rerank.node_distanceagrag.seed_count, agrag.input_count, agrag.path_query_count

Result attributes​

Every span that returns a list records its results in full:

  • agrag.result_count, and arrays agrag.result_ids, agrag.result_scores, agrag.result_kinds and agrag.result_texts holding every result, with no text cap. Array attributes are not subject to the SDK's per-span attribute limit.
  • For the first 20 results, the span also carries the OpenInference flattened names retrieval.documents.N.document.id, .document.content, .document.score and .document.metadata (a JSON object with kind and method). Trace viewers draw these names as a retrieval panel.

The span records the query and the scope. input.value and agrag.query carry the query text. agrag.filters carries the scope as JSON, and an empty scope counts. A step that falls back to empty (a failed load, a reranker without its extra) records the exception as an event on the narrowest span. That span's status stays UNSET.

The agrag.llm.request span​

This is the only span a BAML path tags with the OpenInference LLM kind.

AttributeValue
openinference.span.kind"LLM"
span kindCLIENT
llm.providerOpenInference value mapped from BAML's provider id, table below
llm.model_namethe model named in the response body, else the model in the request body
llm.token_count.prompt / .completionUsage.input_tokens / output_tokens, omitted when None
llm.token_count.totalprompt plus completion, only when both are present
llm.token_count.prompt_details.cache_readUsage.cached_input_tokens, only when greater than 0
agrag.llm.usage_missingtrue when the call succeeded and every usage field was None
input.value, input.mime_typethe request body text, application/json
output.value, output.mime_typethe response body text, application/json, or text/plain if it does not parse
http.response.status_codethe response status
error.typethe status as a string, when it is 400 or higher
agrag.llm.baml_providerBAML's raw provider id
agrag.llm.client_namethe client that made the request
agrag.llm.requested_modelthe model in the request body
agrag.llm.selectedwhether BAML used this call's reply

The span's status is ERROR when the status is 400 or higher, or when the call got no response at all.

Provider mapping​

BAML's provider ids map to the same OpenInference values the agent path emits. The same configuration reports the same provider either way.

BAML provider idllm.provider
openai, openai-generic, openai-responsesopenai
azure-openaiazure
anthropicanthropic
google-ai, vertex-aigoogle
aws-bedrockaws

An id outside this table stays unchanged. A newly added provider still produces a usable span.

Counting calls and tokens​

To count the LLM calls in a trace, count the spans tagged with the OpenInference LLM kind:

def count_llm_calls(spans):
return sum(
1
for span in spans
if span.attributes.get("openinference.span.kind") == "LLM"
)

Token counts live only on agrag.llm.request spans and on the agent and judge LLM spans. The parent spans never carry them. A sum of llm.token_count.prompt over every span with that kind is exact. Nothing counts twice.

What is recorded, and what is not​

Nothing withholds text. agrag.llm.request records the full request and response bodies, and the agent and judge spans record the question, tool inputs and evidence text. The OpenInference redaction environment variables no longer change any span, on any path. To record less, scrub attributes in a SpanProcessor you configure, or run without a tracer.

No span records two things: the request headers, which carry the provider key, and the request URL. Graph store spans record the query text and the value of every parameter except vectors. A parameter can hold source text or entity names.

Known limits​

  • An unparsable reply looks successful: BAML coerces a reply it cannot parse into an empty result rather than raising. The span's status is therefore UNSET. output.value is the evidence that the reply was not usable.
  • Retries below BAML are invisible: LangChain and the provider SDKs retry internally, and one agent or judge LLM span can cover several HTTP requests. The agrag.llm.request spans, read from BAML's collector, are exact for the requests BAML itself made.
  • Token semantics match an OpenAI-compatible endpoint only. For anthropic, google-ai, vertex-ai, aws-bedrock and azure-openai, the counts are whatever BAML's Usage reports.
  • The SDK caps attributes at 128 by default. A long agent run can reach that limit. The SDK then drops attributes without a warning. Raise SpanLimits.max_attributes on your provider. Use a sampling processor in production.
  • BAML error text includes the request URL: it reaches output.value, exception events and StageFailure.error_message. Never put a provider key in a base_url query string.