Skip to content

feat: Add instrumentation for LiveKit cascade mode - #2633

Merged
Luca Forstner (lforst) merged 6 commits into
mainfrom
delner/livekit-cascade
Oct 21, 2026
Merged

Luca Forstner (lforst) merged 6 commits into
mainfrom
delner/livekit-cascade

Conversation

@delner

@delner David Elner (delner) commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor
  • Trace LiveKit voice sessions in Braintrust, connecting user and agent turns with speech recognition, model responses, speech synthesis, and tool calls.

  • Support automatic instrumentation and a new wrapLiveKit wrapper:

    import { wrapLiveKit } from "braintrust";
    import * as agents from "@livekit/agents";
    
    const { voice } = wrapLiveKit(agents); // Adds Braintrust tracing.
    const session = new voice.AgentSession({ stt, llm, tts });
  • With BRAINTRUST_CAPTURE_ATTACHMENTS=true, capture incoming audio and agent audio actually played, linking recordings to speech spans and accounting for interruptions.

  • Add streamingAttachmentBufferBytes to configure audio attachment segment size, defaulting to 4 MiB.

session                              # Entire voice conversation
|
+-- user_turn
|   +-- user_speech                   # What the user said
|   `-- stt                          # Speech-to-text transcription
|
+-- agent_turn
|   +-- llm_response                 # Model requests a tool call
|   +-- lookup_order [tool]           # Tool execution (named after the tool)
|   +-- llm_response                 # Model answers using the tool result
|   +-- tts                          # Text-to-speech generation
|   `-- agent_speech                  # Speech actually played to the user
|
`-- ...                              # Further user and agent turns

With audio capture enabled:
  session                            -> Audio recording attachments
  turn and speech spans              -> Relevant ranges in those recordings

@lforst Luca Forstner (lforst) left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I find all the code to process WAVs a bit overkill and I think it could be solved more cleanly. I left a counter-proposal in slack: https://braintrustdata.slack.com/archives/C083GCUTVDZ/p1792414129468479?thread_ts=1792378384.092499&cid=C083GCUTVDZ

Comment thread js/package.json Outdated
Comment thread js/src/audio/audio-worker.ts Outdated
Comment thread js/src/exports.ts Outdated
Comment thread js/src/node/config.ts Outdated
Comment thread js/src/instrumentation/registry.ts Outdated
Comment thread js/src/instrumentation/braintrust-plugin.ts Outdated
Comment thread js/src/instrumentation/braintrust-plugin.ts Outdated
Comment thread js/src/instrumentation/livekit/runtime.ts Outdated
Comment thread js/src/instrumentation/plugins/livekit-channels.ts Outdated
Comment thread js/src/instrumentation/livekit/runtime.ts Outdated
Luca Forstner (lforst) added a commit that referenced this pull request Oct 20, 2026
Luca Forstner (lforst) added a commit that referenced this pull request Oct 21, 2026
@lforst Luca Forstner (lforst) changed the title Add audio instrumentation for LiveKit cascade mode feat: Add instrumentation for LiveKit cascade mode Oct 21, 2026
Luca Forstner (lforst) added a commit that referenced this pull request Oct 21, 2026
Luca Forstner (lforst) added a commit that referenced this pull request Oct 21, 2026
Luca Forstner (lforst) added a commit that referenced this pull request Oct 21, 2026
Luca Forstner (lforst) added a commit that referenced this pull request Oct 21, 2026
Rewrites the LiveKit plugin around a single Recording per session and a
Playback per audio sink, and trims PcmAudio down to positioned writes.

Recording now only turns on with BRAINTRUST_CAPTURE_ATTACHMENTS, and
integrations.livekit is a plain boolean like every other integration. The
LiveKitOptions object, the per-side audio env vars and the allowPii/OTel
content gating are gone.

The trace follows the voice design doc more closely: the root span is now
`session`, final transcripts get their own `stt` spans with `transcribed_by`
links, and recordings carry `timeline.basis` and `sources[].boundary`. Links
still go in `metadata.links` because native rows have no top-level links field.

Also fixes the output hook receiving `AgentOutput` instead of the session in
auto mode, stops tool-only responses from logging an empty assistant message,
and only re-publishes selections for spans that actually changed.
The helper's methods took no parameters, so tsconfig.test.json rejected calls that pass attributes, statuses and times.
@lforst
Luca Forstner (lforst) merged commit dc16b5e into main Oct 21, 2026
57 checks passed
@lforst
Luca Forstner (lforst) deleted the delner/livekit-cascade branch October 21, 2026 15:24
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.

2 participants