LangChain, Vercel AI SDK, LlamaIndex, and Mastra emit token-usage events you subscribe to; raw OpenAI and DSPy expose usage on the response or compile loop but leave runtime aggregation to you.
Think of receipts at a diner. Some restaurants email you the receipt automatically when you leave (LangChain, Vercel AI SDK, LlamaIndex, Mastra). Others print it and leave it on the table. You can read it and file it, but if you forget, no record exists (raw OpenAI SDK). DSPy is a restaurant that tracks your bill carefully during a tasting menu (the compile loop) but leaves you to track everyday meals on your own. All of them know the price; only some hand it to you without asking.
Concept explanation~2 min read
Everything you need to truly understand this topic: intuition, mechanics, step by step explanation, code, formulas, and worked example. Click to expand.
Concept explanation~2 min read
Everything you need to truly understand this topic: intuition, mechanics, step by step explanation, code, formulas, and worked example. Click to expand.
Cost tracking is one of the most under-modeled production concerns in LLM stacks, and the framework taxonomy directly affects how much glue code you write. The multi-select tests whether you can distinguish 'the SDK exposes usage on the response' from 'the framework emits a usage event you subscribe to'. A small distinction that scales into either zero or hundreds of lines of instrumentation.
The answer is four out of six. Identifying which four is the entry-level test; articulating the capture vs aggregation distinction and the OpenTelemetry production pattern is the senior signal.
Mental model: capture is the framework's job, aggregation and dashboarding are yours. Frameworks that auto-capture save instrumentation glue; they do not save you from owning the cost-tracking pipeline.
The four that auto-surface usage
LangChain
Three complementary channels:
AIMessage.usage_metadataon the response (post-v0.3). The cleanest path for non-streaming calls.with_usage_metadata()for streaming chains, since token deltas are partial and the aggregate only lands at the end.- Callback handlers (the
on_llm_endhook on BaseCallbackHandler) carry usage in the response. LangSmith and Langfuse subscribe to these to render per-trace cost.
Set LANGCHAIN_TRACING_V2=true and the LangSmith trace surface gives you per-step usage for every chain without writing any code.
Vercel AI SDK
The TypeScript-first answer. streamText emits a finish part with:
finish: {
usage: { promptTokens, completionTokens, totalTokens },
finishReason: 'stop' | 'tool_calls' | 'length' | ...,
// toolUsage when tools ran
}
generateText returns the same shape synchronously. Setting experimental_telemetry: { isEnabled: true } emits OpenTelemetry GenAI spans for backend dashboards.
LlamaIndex
TokenCountingHandler is a CallbackManager handler that aggregates usage across the QueryEngine pipeline:
from llama_index.core.callbacks import CallbackManager, TokenCountingHandler
token_counter = TokenCountingHandler()
Settings.callback_manager = CallbackManager([token_counter])
# ... run queries ...
print(token_counter.total_llm_token_count)
print(token_counter.total_embedding_token_count)
Less granular than LangChain's per-span breakdown, but the right shape for RAG pipelines where you want one aggregate for the full retrieve and synthesize cycle.
Mastra
Native OTel from the start. Every agent call emits a GenAI semantic-convention span:
gen_ai.system: openai
gen_ai.request.model: gpt-5.5
gen_ai.usage.input_tokens: 1234
gen_ai.usage.output_tokens: 567
Wire OTel to Langfuse, Phoenix, Honeycomb, or a Datadog APM and usage shows up alongside traces with zero per-call instrumentation.
Situations where this technique stops working.
2–4 min · Everything important, quickly.
Real products, models, and research that use this idea.
- LangSmith and Langfuse render LangChain usage_metadata as cost per trace without extra wiring once you set the LANGCHAIN_TRACING_V2 env var.
- Vercel AI SDK ships experimental_telemetry that emits OTel GenAI spans, Vercel's own demos pipe these into a Langfuse dashboard.
What an interviewer would ask next. Try answering before peeking at the approach.
QHow would you aggregate token usage per user per feature across a stack that uses both LangChain and Vercel AI SDK?
Route both into a common OpenTelemetry pipeline. LangChain emits via the LangSmith or OTel exporter; Vercel AI SDK emits via experimental_telemetry. Tag every span with user_id and feature_id as span attributes. Aggregate in a backend (Langfuse, Phoenix, or a SQL query over a span-export store) by those attributes. The framework boundary disappears at the dashboard layer.
Red flags & common mistakes
The phrases that signal junior thinking. Click to expand.
Red flags & common mistakes
The phrases that signal junior thinking. Click to expand.
Assuming the framework solves cost reporting end to end. It captures usage; you still own aggregation, attribution, and the dashboard.
60 second bullets to scan on the way to the call.
The four frameworks that auto-surface usage and how each one exposes it
Why raw OpenAI SDK is exposing but not surfacing
Primary sources. Browse if you want the original framing.
Same topic, related formats. Practice these next.