fix(voice): don't re-issue in-flight tool calls#1890
fix(voice): don't re-issue in-flight tool calls#1890rosetta-livekit-bot[bot] wants to merge 1 commit into
Conversation
|
| name: fncCall.name, | ||
| args: fncCall.args, | ||
| createdAt: fncCall.createdAt, | ||
| extra: { ...fncCall.extra, [RUNNING_PLACEHOLDER_KEY]: true }, |
There was a problem hiding this comment.
🚩 Placeholder marker key leaks into LLM provider serialization
The __lk_running_placeholder__ key added to FunctionCall.extra (agents/src/voice/generation.ts:110) will be included when the chat context is serialized for the LLM provider, because FunctionCall.toJSON() at agents/src/llm/chat_context.ts:508-509 emits the full extra object whenever it is non-empty. Most providers ignore unrecognized fields, so this is unlikely to cause failures, but it does mean an internal framework marker is exposed in the wire payload. Consider stripping it during serialization or using a Symbol key instead if any provider is strict about extra fields.
Was this helpful? React with 👍 or 👎 to provide feedback.
Summary
Port of livekit/agents#6227.
Testing
Ported from livekit/agents#6227
Original PR description
When a new generation fires while a tool from a previous turn is still running, the in-flight call has no entry in the turn's chat context, so the model re-issues it and duplicates side effects (e.g. booking a flight twice).
This injects an ephemeral in-progress
function_call/function_call_outputpair for the running tool calls (from the session-wide_RunningTasksregistry, covering both activity- and session-scoped executors) into the copy of the chat context fed to the LLM only. It is recomputed every turn and never persisted or forwarded, so it is superseded as soon as the real output lands and a placeholder can never go stale.It also stops spawning a tool-response generation for an interrupted turn: that reply would be dropped by the interrupted check anyway and waste an LLM call. The completed tool outputs are committed to the chat context directly instead, so an interrupted tool's result is preserved rather than lost.