Turn types
Mark what each LLM call is, so grounding is reported as not-applicable on routers and classifiers instead of scored as zero.
Every turn scored on the dimensions that apply to it, so a routing decision doing its job exactly right stops reading as a critical grounding failure.
- variably-sdk 2.9.1 or later
A multi-step agent calls the LLM for many things — classify an intent, route to a tool, expand a search query, write the actual answer. Only one of those is an answer.
Grounding, hallucination and attribution only mean something on a generative turn. On a JSON routing
decision there are no factual claims to ground, so those scorers would return 0.000 and read as
critical failures on a step that did exactly its job. kind tells the scorer what a turn is, and
the dimensions that do not apply are marked not-applicable instead of zero.
Available from variably-sdk >= 2.9.1, on both observe() and BYOR submissions.
kind="generative" — the default
A narrative answer with factual claims. The actual answer your user sees: chat replies, RAG generations, summaries, anything making claims you want grounded or fact-checked.
final_answer = "Metformin starts at 500mg once daily..."
What gets scored: the full 49-dimension sweep across all six categories — faithfulness, hallucination rate, attribution accuracy, context utilisation, retrieval relevance, plus the quality, safety, semantic and coherence dimensions.
kind="classifier"
An intent, safety or category decision. Use it when the model's job is to classify the input — on-topic or not, safe or not, which category, whether to escalate. The output is usually a JSON control structure.
classifier_output = {"is_relevant": True, "is_safe": True, "should_generate": True}
What gets scored: latency, tokens, cost and variant-level analytics. Grounding, hallucination and attribution are suppressed — there are no factual claims to ground.
kind="router"
A workflow control turn. Use it when the model picks the next step in a pipeline: which agent to invoke, which tool to call, which branch to follow. Like a classifier, framed around graph navigation.
router_output = {"next_node": "retrieval_agent", "reason": "user is asking for facts"}
What gets scored: the same as a classifier — variant and latency analytics, grounding skipped.
kind="tool_use"
A function or tool call. Use it when the model emits a tool call — OpenAI function calling, Anthropic tool use — rather than a narrative response.
tool_call = {"name": "search_database", "arguments": {"query": "metformin dose"}}
What gets scored: latency, tokens and tool-name distribution. Grounding does not apply; there is no narrative output to ground.
kind="transformer"
A query rewrite, expansion or summary. Use it for stages that transform text rather than answer questions: query rewriting before retrieval, intent expansion, conversation summarisation to fit a context window.
expanded_query = "metformin starting dose adult type 2 diabetes Kenya guidelines"
What gets scored: latency, tokens and output-length statistics. Grounding skipped.
A worked example: an agentic RAG pipeline
A typical RAG agent makes at least two LLM calls per user message — a classifier deciding whether to answer, and a generator producing the answer. Mark each for what it is:
from variably import observe
# 1. The classifier turn — decides whether the question is on-topic and safe
classifier_output = your_llm.invoke(classifier_prompt)
observe(
prompt=user_query,
response=str(classifier_output),
session_id=trace_id,
agent_name="gatekeeper",
kind="classifier", # no claims here — grounding is N/A, not zero
)
# 2. The generative turn — the answer the user reads
answer = your_llm.invoke(answer_prompt)
observe(
prompt=user_query,
response=answer,
provider_response=completion,
reference_materials=chunks,
session_id=trace_id,
agent_name="answerer",
is_aggregator=True,
kind="generative", # the default, stated for clarity
)
Without kind on the first call, that pipeline reports a grounding score of 0.000 on half its
traffic, and the average across the trace is wrong in a way that looks like a quality problem.
If your grounding scores are zero and you cannot see why
Check the turns, not the model. A classifier or router scored as if it were prose is the single most common cause of an unexpectedly low grounding score — see Troubleshooting.