user_id, model, convo_id); the rest you define yourself with properties={...}. Skip a kwarg and the dashboard column behind it stays empty for that call.
The built-in fields
Each built-in kwarg maps to one OTel attribute and one dashboard column.
The mapping is the same for
track_ai, begin, interaction.update, interaction.finish, and tool_span. Unpassed kwargs are omitted from the span, not set to null.
A few of these fields earn extra attention:
provider has no auto-inference. A model name like claude-3-5-sonnet isn’t auto-tagged as Anthropic, and Bedrock model IDs (anthropic.claude-3-...) are ambiguous on purpose. Pass provider= explicitly: "openai", "anthropic", "google", "aws_bedrock", etc. Bedrock routes through AWS, so a Bedrock call wants provider="aws_bedrock", not "anthropic".
convo_id is the only way to group turns. Without it, multi-turn conversations look like N independent requests. See Sessions and users.
user_id drives user filtering. It’s required to filter the trace list by user, and it’s a pass-through string only. Bento doesn’t store profile data: no email, no name, no traits.
model feeds the cost view. The cost view and per-model breakdowns key off gen_ai.request.model. Without it, spend rolls up under “Unknown”.
Custom attributes via properties
properties covers anything you want to filter or aggregate on that the built-in fields don’t.
properties becomes a top-level OTel attribute with the same name. No namespace is added.
Type fidelity
Property values keep their type when possible, so downstream filters and aggregates work.
The JSON-string fallback is lossless but won’t be filterable as a number or bool. Flatten dicts to multiple keys (
user.tier, user.region) if you need numeric filters.
Span kind
The kind of a span lives inopeninference.span.kind. The SDK sets it for you:
OpenInference defines other kinds (
retriever, embedding, agent, chain). Set them through properties:
What an emitted span looks like
The OTel JSON for atrack_ai call with properties={"experiment_id": 17}:
bento.flush() (or bento.shutdown()) before the process ends.