Skip to content

feat(agents): add warm transfer task#1458

Open
rosetta-livekit-bot[bot] wants to merge 10 commits into
mainfrom
seed-yet-adverts
Open

feat(agents): add warm transfer task#1458
rosetta-livekit-bot[bot] wants to merge 10 commits into
mainfrom
seed-yet-adverts

Conversation

@rosetta-livekit-bot
Copy link
Copy Markdown
Contributor

Summary

  • Add beta WarmTransferTask workflow for SIP-based human handoffs.
  • Export warm transfer types through the beta workflow barrels.
  • Add SIP warm-transfer env vars to Turbo's declared env list and include a changeset.

Validation

  • pnpm --filter @livekit/agents build
  • pnpm --filter @livekit/agents build:types
  • pnpm --filter @livekit/agents lint (passes with existing warnings)
  • pnpm --filter @livekit/agents api:check (blocked by existing API Extractor export * as limitation in dist/index.d.ts)

devin-ai-integration[bot]

This comment was marked as resolved.

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 11, 2026

🦋 Changeset detected

Latest commit: 9e82f41

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 31 packages
Name Type
@livekit/agents Major
@livekit/agents-plugin-anam Major
@livekit/agents-plugin-assemblyai Major
@livekit/agents-plugin-baseten Major
@livekit/agents-plugin-bey Major
@livekit/agents-plugin-cartesia Major
@livekit/agents-plugin-cerebras Major
@livekit/agents-plugin-deepgram Major
@livekit/agents-plugin-elevenlabs Major
@livekit/agents-plugin-fishaudio Major
@livekit/agents-plugin-google Major
@livekit/agents-plugin-hedra Major
@livekit/agents-plugin-hume Major
@livekit/agents-plugin-inworld Major
@livekit/agents-plugin-lemonslice Major
@livekit/agents-plugin-liveavatar Major
@livekit/agents-plugin-livekit Major
@livekit/agents-plugin-minimax Major
@livekit/agents-plugin-mistral Major
@livekit/agents-plugin-mistralai Major
@livekit/agents-plugin-neuphonic Major
@livekit/agents-plugin-openai Major
@livekit/agents-plugin-phonic Major
@livekit/agents-plugin-resemble Major
@livekit/agents-plugin-rime Major
@livekit/agents-plugin-runway Major
@livekit/agents-plugin-sarvam Major
@livekit/agents-plugin-silero Major
@livekit/agents-plugins-test Major
@livekit/agents-plugin-trugen Major
@livekit/agents-plugin-xai Major

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

devin-ai-integration[bot]

This comment was marked as resolved.

devin-ai-integration[bot]

This comment was marked as resolved.

chenghao-mou and others added 5 commits May 17, 2026 15:14
The `_humanAgentFailed` promise and its `_resolveHumanAgentFailed`
resolver were declared as class field initializers. With `target: es2022`,
ESM class fields use `[[Define]]` semantics: each declaration installs an
own-property on the instance, so `_resolveHumanAgentFailed!: () => void;`
overwrote the resolver that was just assigned inside the Promise
executor of the previous field. The resolver was therefore `undefined`
for the task's lifetime, and the human agent room disconnect handler
crashed with `TypeError: this._resolveHumanAgentFailed is not a function`.

Move both assignments into the constructor body, where plain
`this.x = …` is not subject to `[[Define]]`.

Co-authored-by: Cursor <cursoragent@cursor.com>
`AgentActivity.generateReply` defaulted `toolChoice` to `'none'` whenever
it detected we were "inside a tool", using `functionCallStorage` (a
Node.js `AsyncLocalStorage`). ALS contexts propagate across every
`await`, including into a child `AgentSession` spawned from inside a
tool's `execute` (e.g. the supervisor session in
`beta.WarmTransferTask`). The child session's regular user-turn replies
therefore inherited the parent's tool context, the framework forced
`toolChoice: 'none'`, and `executeToolsTask` dropped every tool call the
child agent emitted — including `connect_to_caller`, leaving the caller
on hold indefinitely.

Switch the check to per-task info (`Task.current()` +
`_getActivityTaskInfo`), which is scoped to the owning activity and
does not leak across sessions. Matches Python's
`_get_activity_task_info(task).function_call` behaviour.

Co-authored-by: Cursor <cursoragent@cursor.com>
- Disconnect _humanAgentRoom in setResult; AgentSession.shutdown() closes
  RoomIO but does not disconnect the underlying Room, so each completed
  transfer would otherwise leak a WebSocket to the supervisor room.
- Replace the chained INSTRUCTIONS_TEMPLATE substitutions with a single
  regex pass using function replacements. Avoids JavaScript replace
  string interpreting dollar-sign patterns from user content, and stops
  earlier substitutions from hijacking later placeholders such as
  {extra} appearing inside the conversation history.

Co-authored-by: Cursor <cursoragent@cursor.com>
@chenghao-mou chenghao-mou requested a review from a team May 17, 2026 16:34
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.

1 participant