bento.track_ai is the manual path. Call it once per LLM site you want in Bento. Use it for SDKs without an integration (OpenAI, Anthropic, Bedrock, Vertex, anything else), or alongside an integration for custom events.
Arguments
str
required
Event name, shown as the row title.
str
Your stable user identifier. Pass-through string; no profile data is stored.
str
Conversation or session ID. Same value across turns links them in the timeline view.
str
Model identifier, e.g.
gpt-4o or claude-3-5-sonnet-20241022. Required for cost and per-model breakdowns.str
Provider key. One of
openai, anthropic, google, aws_bedrock, azure_openai, cohere, mistral. Not auto-inferred from model name.str | dict | list
Prompt or input. Strings pass through; dicts and lists are JSON-serialized.
str | dict | list
Model output. Same serialization rules as
input.dict
Custom dimensions. See Properties.
Pass all four
If you skip any of these, the dashboard column behind it stays empty for that call. The defaults you almost always want:Common shapes
A single LLM call
Multi-turn conversation
Pass the sameconvo_id on every turn:
Structured chat messages
Dicts and lists are JSON-serialized:Streaming
Calltrack_ai once after the stream finishes. Accumulate the output, then emit one event:
Parenting
bento.track_ai calls are root spans by default. They detach from any caller’s OTel context, so calling track_ai inside a FastAPI or Django request doesn’t pull the LLM event into that trace.
Inside a bento.begin(...) block, track_ai calls become children of the trajectory instead, so the whole multi-step turn renders as one trace.
See also
Integrations
Drop the per-call wrapping for Google ADK.
Properties
Tag events with arbitrary custom dimensions.
Trajectories
Group multi-step work into one trace.
Attributes mapping
How each argument lands in the dashboard.