Skip to main content
These helpers set user_id, session_id, and tags after a span is already open, or scope them to one task. The cleanest place to set identity is the getter callables on bento.init(), which fire on every span, including ones captured by an integration. The helpers here cover the cases those getters don’t fit:
  • Identity becomes known mid-flow, such as after authentication inside an open trajectory.
  • A worker receives identity over a queue and the value should scope to one handler invocation.
  • An arbitrary attribute belongs on the currently active span without restructuring the call site.

update_current_trace

Patches the open trajectory’s root span. Applies when identity becomes known mid-flow and belongs at the trace level (traces.user_id, traces.session_id, traces.tags).
The keys are SDK-defined (gen_ai.user.id, gen_ai.conversation.id, langfuse.tags); the values come from the call.
str
Sets gen_ai.user.id on the trajectory root.
str
Sets gen_ai.conversation.id on the trajectory root.
list[str]
Sets langfuse.tags on the trajectory root.
dict
Arbitrary custom dimensions, written through _coerce_property_value so types are preserved.
No-op when no bento.begin(...) is open in the current task. For bare track_ai calls, set the values directly on track_ai instead.

update_current_span

Sets attributes on the currently active OTel span, the innermost open span, which may or may not be the trajectory root. Applies when a property belongs on the inner span and there’s no direct handle to it, such as deep helper functions or callbacks invoked by an integration.
It reads OTel’s current context, so it sees integration-captured spans too. Called inside a callback that ADK invokes, it writes the property onto that span.
dict
Keys/values written to the currently active span. Same type-fidelity rules as track_ai(properties=...); see Properties.

propagate_attributes

Scopes an identity override to the current task. Per-task overrides take precedence over the global getters registered at init(). Applies when the framework-state pattern doesn’t fit, such as a worker that received identity over a message queue and scopes it to one handler invocation.
The block restores the prior values on exit, and identity sources registered at init() resume after it.

Three-value kwargs

Each kwarg accepts three distinct values:

How they compose

The SDK resolves identity in this order, highest priority first:
  1. Explicit kwarg on the call: bento.track_ai(user_id="x", ...) or bento.begin(user_id="x", ...) always wins.
  2. update_current_trace(...) patches set on the trajectory root.
  3. propagate_attributes(...) scope active in the current task.
  4. Init-time getters: bento.init(user_id=lambda: ...) resolved per span.
The first source that returns a non-None value at span-emit time is the one that lands in the dashboard.

See also

Integrations

Identity getters at init(), the zero-code path.

Trajectories

Open a begin() block to host update_current_trace patches.