Skip to main content
When 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. On os._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:
Long-running services don’t need this. 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:
The key must start with bl_pk_. Otherwise the SDK raises BentoAuthError("invalid_api_key_format") on construction.

BENTOLABS_BASE_URL points at the wrong host

It defaults to https://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:
If the worker thread isn’t there, 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:
Turn on Python logging to see it:
If you’re hitting this, you’re emitting faster than network egress. Reduce volume or talk to us about higher-throughput tiers.

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. Pass provider="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 passing convo_id. Add the same convo_id to every turn in the conversation, including assistant messages and tool calls.

The user filter doesn’t work

Either user_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 like anthropic.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 are int, 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 a ContextVar, 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 nested bento.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:
Or set it through env vars:
Only 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:
  1. SDK version: python -c "import bentolabs_sdk; print(bentolabs_sdk.SDK_VERSION)"
  2. The track_ai call you’re making (redact secrets)
  3. The output of print([t.name for t in threading.enumerate()]) after init
  4. Anything you see at WARNING-level Python logs