Skip to content

fix(voice): propagate ChatMessage.interrupted through proto serializer#5824

Merged
toubatbrian merged 1 commit into
mainfrom
brian/add-interrupted-field
May 23, 2026
Merged

fix(voice): propagate ChatMessage.interrupted through proto serializer#5824
toubatbrian merged 1 commit into
mainfrom
brian/add-interrupted-field

Conversation

@toubatbrian
Copy link
Copy Markdown
Contributor

@toubatbrian toubatbrian commented May 23, 2026

Summary

_chat_item_to_proto in livekit-agents/livekit/agents/voice/remote_session.py omits the interrupted field when converting llm.ChatMessage to its proto form. The model has the field (interrupted: bool = False in livekit-agents/livekit/agents/llm/chat_context.py:320) and the proto schema has it (ChatMessage.interrupted at field 4 in livekit_agent_session.proto), but the serializer drops it on the floor. Result: every conversation_item_added event on the wire reports interrupted=false, even for messages whose model copy was committed with interrupted=True.

Repro

Drive the agent into a partial-speech-then-interrupt scenario — e.g. ask for a long story, then send a new runInput after ~2 s of speaking. Subscribe to AgentSessionMessage.event over the lk.agent.session byte-stream topic. The framework's AgentActivity commits the partial assistant message with interrupted=True (model-side), but the emitted proto event has item.message.interrupted=false on the wire.

After this PR:

// conversation_item_added event for the interrupted partial speech
{
  "item": {
    "message": {
      "role": "ASSISTANT",
      "content": [{ "text": "Alright, picture this: three" }],
      "interrupted": true, // <-- now correctly propagated
    },
  },
}

Fix

         pb_msg = agent_pb.ChatMessage(
             id=item.id,
             role=pb_role,
             content=content,
+            interrupted=item.interrupted,
             metrics=_metrics_to_proto(item.metrics),
         )

Single field added to the ChatMessage constructor. No API change, no behaviour change for the model — only the wire serialization is affected.

Test plan

  • Verified locally against examples/voice_agents/basic_agent.py with an external proto consumer. Before the fix, all messages had interrupted=false. After the fix, the partial assistant message that was interrupted mid-speech shows interrupted=true, matching the JS framework's behaviour.
  • CI: make check (ruff lint + mypy) passes.

The `_chat_item_to_proto` helper in `voice/remote_session.py` constructs
the proto `ChatMessage` without copying `item.interrupted`, so the field
is always false on the wire even when the model has it set. The JS
framework's serializer at `agents-js/agents/src/voice/remote_session.ts`
already passes it through; this aligns Python with that behaviour.
Repro: send a turn that causes the agent to start speaking, then send
another turn before the first finishes. The first message ends up in
chat context with `interrupted=True` (model-side) but the proto
`conversation_item_added` event emits `interrupted=false` to anything
subscribing on the wire (e.g. external test drivers, replay tools).
Fix: pass `interrupted=item.interrupted` into the `ChatMessage` proto
constructor. Single field; no API change.
@chenghao-mou chenghao-mou requested a review from a team May 23, 2026 20:19
Copy link
Copy Markdown
Contributor

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

Choose a reason for hiding this comment

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

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 1 additional finding.

Open in Devin Review

@toubatbrian toubatbrian merged commit fcac691 into main May 23, 2026
26 checks passed
@toubatbrian toubatbrian deleted the brian/add-interrupted-field branch May 23, 2026 20: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