feat(telemetry): expose provider request ids on STT/TTS/LLM spans#1319
Merged
Conversation
Port of livekit/agents#5546 to agents-js. Adds `lk.provider_request_ids` (string[], deduped) on the `user_turn` (STT), `tts_request_run` (TTS), and `llm_request_run` (LLM) spans so traces can be cross-referenced with the provider's server-side logs. - LLM: collected from `ChatChunk.id` in `monitorMetrics`, reset per attempt and written on the `llm_request_run` span in finally. - TTS: `noteProviderRequestId()` helper records ids on the current `tts_request_run` (attempt) span; metrics monitor calls it for every unique `segmentId` on emitted audio frames. - STT: `audio_recognition` collects `requestId` from incoming `SpeechEvent`s for the user turn and writes them when the `user_turn` span ends. https://claude.ai/code/session_01TSGPGRzv6SwoTks2rtCTej
🦋 Changeset detectedLatest commit: 99887f9 The changes in this PR will be included in the next version bump. This PR includes changesets to release 27 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
|
theomonnom
approved these changes
Apr 29, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Automated port of livekit/agents#5546 into agents-js.
Adds a new span attribute
lk.provider_request_ids(string[], deduped) on theuser_turn(STT),tts_request_run(TTS), andllm_request_run(LLM) spans for debugging and reporting STT/TTS issues to providers. The id can either be one we sent to the provider (e.g. WScontext_id/segment_id) or one returned by the provider (e.g. responserequest_id/session_id) – both can be cross-referenced with the provider's server-side logs.cc @toubatbrian @livekit/agent-devs
Ported features
agents/src/telemetry/trace_types.ts– newATTR_PROVIDER_REQUEST_IDS = 'lk.provider_request_ids'constant.agents/src/llm/llm.ts–LLMStreamnow collectsChatChunk.idvalues seen inmonitorMetrics, resets the list at the start of each retry attempt, and writes them onto thellm_request_runspan in afinallyblock (mirrors PythonLLM._main_task/_metrics_monitor_task).agents/src/tts/tts.ts–SynthesizeStreamexposes a new protectednoteProviderRequestId(contextId)helper (the JS equivalent of Python'sAudioEmitter._note_provider_request_id). It dedupes and writes onto the currenttts_request_run(attempt) span; the metrics monitor calls it automatically for every uniquesegmentIdit sees on emitted audio frames, and plugins can call it directly when the provider-known id becomes available later.agents/src/voice/audio_recognition.ts– the user-turn pipeline now collectsrequestIdfrom incomingSpeechEvents (deduped) and writes them onto theuser_turnspan when it ends.Implementation nuances vs. Python
AudioEmitter.start_segment()/_note_provider_request_id. agents-js has noAudioEmitter; plugins push frames carryingrequestId/segmentIddirectly into the TTS queue, so the monitor task usesaudio.segmentIdfor automatic collection. A protectednoteProviderRequestIdis still exposed for plugins that learn a provider id later (or want to call it fromrun()directly, matching the Python ergonomics).trace.get_current_span()in_note_provider_request_id; in JS the metrics monitor runs as a separate background task, so the currenttts_request_runspan is captured into a member field (#currentAttemptSpan) at the start of each attempt and cleared infinally.noteProviderRequestIdwrites to the saved span only while it is still recording, with the same best-effort timing as Python._provider_request_idsper attempt and writes infinally; the JS port does the same onattemptSpan. The dedup-and-collect step inmonitorMetricsmirrors the_metrics_monitor_taskchange._on_stt_eventand writes them when the user-turn span ends; the JS port mirrors that exactly inonSTTEvent/_endUserTurnSpan, then resets the list when the user turn ends.Plugin updates skipped (out of scope for JS)
The Python PR also updated three plugins (
openai/stt.py,sarvam/stt.py,sarvam/tts.py,upliftai/tts.py). Status in agents-js:openai/stt.pyis the OpenAI WebSocket transcription session. agents-js's@livekit/agents-plugin-openaiSTT is the Whisper REST client – no equivalent surface to port.upliftaiplugin does not exist in agents-js.sarvamplugin already passesrequestIddirectly onFINAL_TRANSCRIPTevents (no JSON-wrappedoriginal_idbug to fix). It will now flow into the newlk.provider_request_idsattribute via the core change above without any plugin-level edits.Test plan
pnpm build:agentssucceeds.pnpm exec eslintclean for the four touched files.pnpm exec prettier --checkclean for the four touched files.pnpm exec vitest run agents/src/llm(244 passed / 2 skipped).pnpm exec vitest run agents/src/tts agents/src/voice/audio_recognition_span.test.ts(7 passed).lk.provider_request_idson real STT/TTS/LLM spans through the agent playground.https://claude.ai/code/session_01TSGPGRzv6SwoTks2rtCTej
Generated by Claude Code