Skip to content

fix(telemetry): describe option objects in the session report - #7127

Merged
davidzhao merged 4 commits into
mainfrom
dz/telemetry-session-options-describe
Sep 7, 2026
Merged

fix(telemetry): describe option objects in the session report#7127
davidzhao merged 4 commits into
mainfrom
dz/telemetry-session-options-describe

Conversation

@davidzhao

@davidzhao davidzhao commented Sep 5, 2026

Copy link
Copy Markdown
Member

What

session.options in the session report carried the turn detector as its default repr:

turn_detection: "<livekit.agents.inference.eot.detector.TurnDetector object at 0x7fc5518a2a50>"

The OTel exporter stringifies any non-primitive log attribute, so anything left as an object in the options dict ends up like this.

How

  • _serialize_session_options now serializes explicitly: primitives pass through, mappings recurse, any non-string Sequence or Set is serialized elementwise (tts_text_transforms accepts any Sequence), and any other object is reported by class, module.Class. An object that wants its configuration shown implements the telemetry.DescribesOptions protocol, a describe_options() method returning the options worth reporting; it is then rendered as module.Class(k=v, ...). The object decides what is safe to show, so nothing is guessed from public attributes and credentials and endpoints stay out by construction (test included; a failing describe_options() falls back to the class name).
  • Customer-authored prompt text is never written to the report: instructions keys (the keyterm-detection prompt override) are dropped at any depth rather than emitted under an unmarked key.
  • TurnDetector implements describe_options(): model, provider, sample rate, local fallback, and the threshold overrides only when the user set any. Mode strings ("vad", "manual", ...) pass through unchanged. Third-party detectors and models opt in the same way.

Result:

livekit.agents.inference.eot.detector.TurnDetector(model=turn-detector-v1-mini, provider=livekit, sample_rate=16000, local_fallback=True)

with threshold_overrides / backchannel_threshold_overrides appended only when the user set them.

Tests

tests/test_session_options_report.py (unit): default detector description, threshold overrides, no credential leakage, mode strings, plugin-like objects, custom Sequence and Set values, omitted prompt text, nested containers and the keyterms PII alias, and a JSON-safety invariant on the whole serialized dict.

Bottom layer of the tracing coverage stack.

🤖 Generated with Claude Code

@davidzhao
davidzhao marked this pull request as ready for review September 5, 2026 20:53
@davidzhao
davidzhao requested a review from a team as a code owner September 5, 2026 20:53
devin-ai-integration[bot]

This comment was marked as resolved.

@davidzhao
davidzhao force-pushed the dz/telemetry-session-options-describe branch from 2511a5c to d7d15d6 Compare September 5, 2026 21:00
Comment thread livekit-agents/livekit/agents/telemetry/traces.py Outdated
davidzhao and others added 3 commits September 6, 2026 09:45
`session.options` in the session report carried the turn detector as its
default repr (`<livekit.agents.inference.eot.detector.TurnDetector object at
0x...>`), because the OTel exporter stringifies any non-primitive attribute.

Serialize option values explicitly: primitives and containers pass through,
and any other object is rendered from a whitelist of public attributes as
`ClassName(model=..., provider=..., ...)`. The whitelist keeps credentials and
internals out of the report. `TurnDetector` exposes `sample_rate`,
`local_fallback`, and the threshold overrides so the description shows its
config, e.g.

    TurnDetector(model=turn-detector-v1-mini, provider=livekit,
                 sample_rate=16000, local_fallback=True)

with `threshold_overrides` / `backchannel_threshold_overrides` appended only
when the user set them.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
tts_text_transforms accepts any Sequence, so a user-defined one collapsed to
its class name in the session report; serialize elements for every non-string
Sequence and Set instead of only list and tuple.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
stt_context_options.keyterm_detection.instructions is a customer-authored
prompt override and can embed anything about their business or users; the
report has no use for it, so `instructions` keys are dropped at any depth
rather than emitted under an unmarked key.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@davidzhao
davidzhao force-pushed the dz/telemetry-session-options-describe branch from d0c3596 to e7e80a1 Compare September 6, 2026 16:48
Replace the global attribute whitelist with a per-class protocol. An object in
the session options is reported as module.Class; one that implements
telemetry.DescribesOptions (a describe_options() method) as
module.Class(k=v, ...). The object decides what is safe to show, so nothing is
guessed from public attributes and credentials stay out by construction.
TurnDetector reports model, provider, sample rate, local fallback and the
threshold overrides the user set.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 new potential issue.

Devin Review

Comment thread livekit-agents/livekit/agents/telemetry/traces.py
@davidzhao
davidzhao merged commit 01c78e8 into main Sep 7, 2026
26 checks passed
@davidzhao
davidzhao deleted the dz/telemetry-session-options-describe branch September 7, 2026 05:05
if is_given(thresholds.overrides):
options["threshold_overrides"] = thresholds.overrides
if is_given(thresholds.backchannel_overrides):
options["backchannel_threshold_overrides"] = thresholds.backchannel_overrides

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would have made sense to call this threshold_backchannel_overrides, in the style of the rest of the names.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants