Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.bentolabs.ai/llms.txt

Use this file to discover all available pages before exploring further.

The BentoLabs dashboard (conversation timelines, cost breakdowns, user analytics, agent behavior views) is built from four primitives the SDK emits as you run your app. Once you know what each one represents, you can predict how any chart in the product is computed.

The four primitives

Trajectory

One run of your agent. The root span of a trace.bento.begin(...) · @bento.interaction

Span

One step inside a trajectory. An LLM call, a tool call, or anything you choose to time.bento.track_ai(...) · bento.tool_span(...) · @bento.tool

Attribute

A typed key/value pair on a span. Becomes a column or filter in the dashboard.Kwargs on the calls above, plus properties={...}

Session

All trajectories that share a convo_id. A server-side grouping, not an SDK object.Pass the same convo_id on every call.
Under the hood these are OpenTelemetry spans with OpenInference and GenAI semantic conventions. You can ignore that unless you’re wiring BentoLabs into an existing OTel pipeline.

How they nest

Session                  ← grouped server-side by convo_id
├── Trajectory A         ← one agent run, opened by bento.begin
│   ├── LLM span         ← bento.track_ai
│   ├── Tool span        ← bento.tool_span or @bento.tool
│   └── LLM span         ← bento.track_ai
└── Trajectory B         ← next turn, same convo_id
    └── ...
A bare track_ai call with no surrounding begin is its own one-span trajectory. You don’t have to open a trajectory to record an LLM call.

What gets emitted

Every call produces one OTel span. The attributes below land in dashboard columns. Everything else lives in the per-span attributes JSON.
ConceptOTel attributeDashboard column
Span namespan.nameSpan name
Usergen_ai.user.idUser
Conversationgen_ai.conversation.idSession
Modelgen_ai.request.modelModel
Providergen_ai.systemProvider
Inputinput.valueInput
Outputoutput.valueOutput
Span kindopeninference.span.kindKind
Custom(your properties keys)Attributes JSON
See Attributes for the per-kwarg breakdown.

Span kinds

The openinference.span.kind attribute drives icons, colors, and filters in the dashboard.
KindEmitted byMeaning
(default)bento.track_aiA model call. Carries gen_ai.* attributes.
toolbento.tool_span, @bento.tool, interaction.tool_spanA tool or function call.
OpenInference defines other kinds (retriever, embedding, agent, chain). Set them by passing openinference.span.kind in properties.

Sessions are server-side

There is no Session object in the SDK. A session is whatever trajectories share the same convo_id string.
bento.track_ai(event="turn_1", convo_id="chat_99", user_id="user_42", ...)
bento.track_ai(event="turn_2", convo_id="chat_99", user_id="user_42", ...)
Both turns land under one session in the dashboard. user_id works the same way: a free-form string passed on every call. We do not store profile data. See Sessions and users for ID-choosing rules.

Already on OpenTelemetry?

Drop in BentoLabsSpanProcessor and skip the analytics layer entirely. Any span you emit with OpenInference or GenAI semantic conventions lands in the right dashboard column. See OTel transport.