If I trace an agent framework and the model client it uses, are tokens counted twice?
Rius counts each model call once in token and cost totals, even when a framework span and a model client span both report that call’s tokens. The wrapper span, such as LangChain, LiteLLM, LlamaIndex or the Vercel AI SDK, still shows the total for the whole run. A few setups still count a call twice, so check one trace after you set up.
How it works
When a wrapper sits over an instrumented model call, two spans describe the same call. The span for the model call reports its tokens, and the span for the wrapper reports them too. Rius handles this in the SDK:
- Each call is counted once in token and cost totals.
- The wrapper span keeps the run’s total, so you still see what the whole step used.
- The model call span keeps the call’s own tokens, so you can see which call used them.
This applies to wrappers such as LangChain, LiteLLM, LlamaIndex and the Vercel AI SDK. It needs these SDK versions or newer:
- Python:
glassflow-rius1.1.0, or 1.0.2 for LiteLLM and 1.1.1 for LlamaIndex. - TypeScript:
@glassflow-ai/rius1.2.0, or 1.1.0 for the Vercel AI SDK onai7.
With a default (global) init(), every installed integration turns on automatically, so you do not enable the deduplication separately. Cost comes from the same token counts. Rius computes it from the model and token counts, so you never send a cost value, and the totals stay consistent with the counted tokens. Costs are list-price estimates in US dollars.
A few setups still count a call twice. If your trace shows that, keep one layer of instrumentation for that call rather than two.
Set it up
-
Upgrade the SDK to a version at or above the ones listed above. For Python,
pip install glassflow-riusinstalls the SDK, and the extra for each library you use installs that library’s instrumentation. -
Call
init()once at startup. Every installed integration attaches on its own. In Python you can see and control which ones attach:
rius.init() # everything installed
rius.init(instruments=["openai"]) # only OpenAI
rius.init(instruments=[]) # none- In TypeScript 1.8.0 or later,
init({ instruments: [...] })takes the same list. Awaitreadyto see which integrations attached, for example['openai', 'mcp']:
import { init } from '@glassflow-ai/rius'
const client = init()
console.log(await client.ready)-
If a trace shows a call counted twice, limit the layers that report it. In Python, pass the one you want in
instruments. In TypeScript, pass it ininit({ instruments: [...] }). Either way the provider integration is off for the whole process, so direct calls to that provider outside the framework are no longer traced. Trace those as manual generations. -
Run your agent once and open the trace in the Rius console. Compare three things:
- The tokens on the span for one model call.
- The total on the wrapper span above it.
- The token total for the trace.
The wrapper should show the run’s total, and the trace total should match the sum of the distinct model calls, not the model call plus the wrapper. You can also compare a call’s tokens with the usage your provider returns for that call.
The Integrations page lists, for each framework and client, which instrumentation captures its model calls, so you can see which layers can overlap in your stack.
What you get
- Token and cost totals that count each model call once, with no manual deduplication.
- A wrapper span that still shows the run’s total, so a framework step reads as one unit of work.
- A model call span that keeps its own tokens, so you can trace usage down to the call.
- A clear check on any trace: wrapper total on top, per-call tokens underneath, and one total that does not double the two.
- Cost estimates that follow the counted tokens, from the model and token counts on each call.
When something else fits
If you want only the model client’s spans and not the framework’s, in Python limit instruments to that client. If a setup of yours is one of the few that still counts a call twice, keeping a single layer is the fix. The Integrations page covers each integration’s setup and blind spots.
Related
Still stuck? Get help