track_ai data doesn’t show up or lands wrong, the cause is usually one of a handful of things. Find your symptom below.
Nothing shows up in the dashboard
Walk these five top to bottom. The fix is almost always one of them.You didn’t call flush() before exit
The exporter batches spans. Onos._exit(), a Lambda timeout, or a script that ends right after track_ai, the daemon worker is killed before its next 5-second tick and the queue is lost. Flush before you exit:
atexit runs the shutdown for you.
BENTOLABS_API_KEY isn’t set in the running process
Setting it in~/.zshrc doesn’t help if your IDE or CI launched the process from a different env. Check it from inside the process:
bl_pk_. Otherwise the SDK raises BentoAuthError("invalid_api_key_format") on construction.
BENTOLABS_BASE_URL points at the wrong host
It defaults tohttps://api.bentolabs.ai. If you set it for local dev and forgot to unset it in production, your spans go nowhere. Print what the SDK resolved:
The daemon worker isn’t running
List the threads after init and look for the worker:init() failed silently (a suppressed exception in your code) or you called SDK functions before init resolved.
Spans are being dropped
The queue holds 2048 spans. Past that, drops are logged at WARNING level:Fields look wrong in the dashboard
The spans arrived, but a column is empty or a value lands in the wrong place. Match your symptom below.The provider column is empty
Bento doesn’t infer the provider from the model name. Passprovider="anthropic" (or openai, google, aws_bedrock, and so on) on every track_ai call. See Attributes.
A conversation appears as N separate rows
You’re not passingconvo_id. Add the same convo_id to every turn in the conversation, including assistant messages and tool calls.
The user filter doesn’t work
Eitheruser_id is missing, or you’re passing it as a property (properties={"user_id": ...}). It has to be the top-level user_id= kwarg so it lands on gen_ai.user.id.
A Bedrock model shows up under ‘anthropic’ instead of ‘aws_bedrock’
Bedrock model IDs likeanthropic.claude-3-sonnet-20240229-v1:0 look like Anthropic to us but route through AWS. Pass provider="aws_bedrock" explicitly.
Custom properties show as strings even though you passed ints
Properties that areint, float, bool, or str keep their type. Dicts and mixed lists fall back to a JSON string. See Properties → Type fidelity.
Spans nest weirdly
The spans show up, but the tree isn’t what you expected. The three common shapes, and what’s behind each:track_ai calls don’t show as children of your begin() block
Check your task context. The trajectory’s parent context lives in aContextVar, which is per-thread for sync code and per-task for asyncio. Calling track_ai from a new thread or a concurrent.futures worker that didn’t inherit your context produces a root span instead. See the threading model for the full rules.
track_ai inside a FastAPI handler steals your framework span
It doesn’t.track_ai and begin both detach from the caller’s OTel context on purpose, so your customer’s FastAPI or Django instrumentation isn’t pulled into our trace. To make the Bento span a child of a parent OTel span, set its traceparent explicitly through the lower-level OTel transport.
finish() raises RuntimeError ‘out of order’
A nestedbento.begin() is still open. Trajectories must be finished LIFO. Use with bento.begin(...) as i: to guarantee correct nesting; the context manager handles cleanup on exception too.
Local development
Point the SDK at your local backend:http:// and https:// schemes are accepted. A typo like BENTOLABS_BASE_URL=localhost:8080 (no scheme) raises ValueError on resolution.
Still stuck
Email support@bentolabs.ai with:- SDK version:
python -c "import bentolabs_sdk; print(bentolabs_sdk.SDK_VERSION)" - The
track_aicall you’re making (redact secrets) - The output of
print([t.name for t in threading.enumerate()])after init - Anything you see at WARNING-level Python logs