> ## Documentation Index
> Fetch the complete documentation index at: https://lemonslice.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Send your avatar to a Zoom call

> Send your LemonSlice avatar to a Zoom, Google Meet, Teams, or Webex meeting

## Overview

With our [LiveKit Agents integration](/docs/livekit), you can easily send a LemonSlice avatar into a video call hosted on a third-party platform. Supported platforms are **Zoom**, **Google Meet**, **Microsoft Teams**, and **Webex**. The avatar appears on camera, listens to the meeting, and responds with low-latency voice and animation.

Joining a call is as simple as adding a single line of code to your LiveKit agent. LemonSlice handles the rest: connecting to the call, feeding meeting audio into your agent, and publishing the synced avatar audio and video into the meeting.

<div className="meeting-platforms not-prose">
  <div className="meeting-platforms-label">Supported platforms</div>

  <div className="meeting-logos">
    <div className="meeting-logo">
      <img src="https://mintcdn.com/lemonslice/56kJVL9zGkbRQXHr/images/meetings/zoom-icon.png?fit=max&auto=format&n=56kJVL9zGkbRQXHr&q=85&s=890c05d92096be6035f7ed838ceb5b16" alt="" width="512" height="512" data-path="images/meetings/zoom-icon.png" />

      <span>Zoom</span>
    </div>

    <div className="meeting-logo">
      <img src="https://mintcdn.com/lemonslice/56kJVL9zGkbRQXHr/images/meetings/google-meet.svg?fit=max&auto=format&n=56kJVL9zGkbRQXHr&q=85&s=c9786ab78c3af6663b5382addda197ce" alt="" width="24" height="24" data-path="images/meetings/google-meet.svg" />

      <span>Google Meet</span>
    </div>

    <div className="meeting-logo">
      <img src="https://mintcdn.com/lemonslice/56kJVL9zGkbRQXHr/images/meetings/microsoft-teams.svg?fit=max&auto=format&n=56kJVL9zGkbRQXHr&q=85&s=506f78a38457c01e0e189939975c205a" alt="" width="24" height="24" data-path="images/meetings/microsoft-teams.svg" />

      <span>Microsoft Teams</span>
    </div>

    <div className="meeting-logo">
      <img src="https://mintcdn.com/lemonslice/56kJVL9zGkbRQXHr/images/meetings/webex.png?fit=max&auto=format&n=56kJVL9zGkbRQXHr&q=85&s=902f39864f2139763bb43072f5d0bbbd" alt="" width="128" height="128" data-path="images/meetings/webex.png" />

      <span>Webex</span>
    </div>
  </div>
</div>

<video controls playsInline>
  <source src="https://mintcdn.com/lemonslice/56kJVL9zGkbRQXHr/videos/zoom-meeting.webm?fit=max&auto=format&n=56kJVL9zGkbRQXHr&q=85&s=31816d37d024bc05a8a0f4616b4da263" type="video/webm" data-path="videos/zoom-meeting.webm" />

  <source src="https://mintcdn.com/lemonslice/56kJVL9zGkbRQXHr/videos/zoom-meeting.mp4?fit=max&auto=format&n=56kJVL9zGkbRQXHr&q=85&s=08646ac83ecf5b5a3f0e405a73504b0b" type="video/mp4" data-path="videos/zoom-meeting.mp4" />
</video>

## How it works

1. Start a normal LiveKit `AvatarSession` with the desired session parameters (see our [LiveKit guide](/docs/livekit) for details).
2. Call `join_meeting` with the meeting URL. LemonSlice joins the call as a bot and opens a relay WebSocket that streams mixed meeting audio into your agent for STT (bypassing LiveKit room audio).
3. LemonSlice publishes the synced avatar audio/video stream into the meeting.
4. Optionally, enable `listen_to_meeting_chat` so chat messages from the meeting are passed to the agent as user input.

| Platform            | Example meeting URL                                                              |
| ------------------- | -------------------------------------------------------------------------------- |
| **Zoom**            | `https://us06web.zoom.us/j/12345678901?pwd=AbCdEfGhIjKlMnOp`                     |
| **Google Meet**     | `https://meet.google.com/abc-defg-hij`                                           |
| **Microsoft Teams** | `https://teams.live.com/meet/1234567890123?p=AbCdEfGhIjKlMnOpQr`                 |
| **Webex**           | `https://company.webex.com/company/j.php?MTID=m0123456789abcdef0123456789abcdef` |

## Requirements

| SDK                                           | Minimum version |
| --------------------------------------------- | --------------- |
| Python (`livekit-plugins-lemonslice`)         | **1.6.5+**      |
| Node.js (`@livekit/agents-plugin-lemonslice`) | **1.5.3+**      |

<CodeGroup>
  ```shell PYTHON theme={null}
  # When using PIP
  pip install "livekit-agents[lemonslice]>=1.6.5"

  # When using UV
  uv add "livekit-agents[lemonslice]>=1.6.5"
  ```

  ```shell NODE.JS theme={null}
  pnpm add @livekit/agents-plugin-lemonslice@^1.5.3
  ```
</CodeGroup>

## Usage

After `avatar.start(...)`, call `join_meeting`, then start the agent session with the room options returned by the avatar. Those options disable LiveKit room audio I/O so the agent listens to the meeting relay instead.

<CodeGroup>
  ```python LiveKit (Python) highlight={8-13,18} theme={null}
  from livekit.plugins import lemonslice

  avatar = lemonslice.AvatarSession(
      agent_image_url=lemonslice_image_url,
  )
  await avatar.start(session, room=ctx.room)

  await avatar.join_meeting(
      meeting_url,
      bot_name="My Avatar",
      listen_to_meeting_chat=True,
  )
  room_options = avatar.room_options()

  await session.start(
      agent=agent,
      room=ctx.room,
      room_options=room_options,
  )
  ```

  ```javascript LiveKit (Node.js) highlight={8-13,18-19} theme={null}
  import * as lemonslice from '@livekit/agents-plugin-lemonslice';

  const avatar = new lemonslice.AvatarSession({
    agentImageUrl,
  });
  await avatar.start(session, ctx.room);

  await avatar.joinMeeting(meetingUrl, {
    botName: 'My Avatar',
    listenToMeetingChat: true,
  });

  const roomOpts = avatar.roomOptions();

  await session.start({
    agent,
    room: ctx.room,
    inputOptions: roomOpts.inputOptions,
    outputOptions: roomOpts.outputOptions,
  });
  ```
</CodeGroup>

<Tip>
  Pass the meeting URL (and optional `bot_name` / `listen_to_meeting_chat`) via LiveKit [job metadata](https://docs.livekit.io/agents/server/job/#metadata) when you dispatch the agent, so the same worker can join different calls.
</Tip>

Example dispatch:

```bash theme={null}
lk dispatch create \
  --new-room \
  --agent-name zoom-bot \
  --metadata '{"meeting_url":"<MEETING LINK>", "bot_name": "My Avatar", "listen_to_meeting_chat": true}'
```

## Toggle listening behavior

After `join_meeting`, the plugin attaches a `MeetingAudioInput` to `session.input.audio` so the agent hears the meeting. To temporarily stop (or resume) listening without leaving the call, swap that input for a silent one:

<CodeGroup>
  ```python LiveKit (Python) theme={null}
  import asyncio

  from livekit.agents.voice.io import AudioInput

  meeting_audio = session.input.audio  # MeetingAudioInput after join_meeting

  class SilentAudioInput(AudioInput):
      def __init__(self) -> None:
          super().__init__(label="silent")

      async def __anext__(self):
          await asyncio.get_running_loop().create_future()  # never yields

  silent = SilentAudioInput()

  def set_meeting_listening(on: bool) -> None:
      session.input.audio = meeting_audio if on else silent
  ```

  ```javascript LiveKit (Node.js) theme={null}
  import { voice } from '@livekit/agents';

  await avatar.joinMeeting(meetingUrl, { /* ... */ });
  const meetingAudio = session.input.audio; // MeetingAudioInput
  const silent = new (class extends voice.AudioInput {})();

  function setMeetingListening(on: boolean) {
    session.input.audio = on ? meetingAudio : silent;
  }
  ```
</CodeGroup>

## End-to-end examples

| Language    | Example                                                                                                                                                                        |
| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Python**  | [07-livekit-zoom](https://github.com/lemonsliceai/lemonslice-examples/tree/main/07-livekit-zoom) in the LemonSlice examples repo                                               |
| **Node.js** | [`lemonslice_realtime_avatar_meeting.ts`](https://github.com/livekit/agents-js/blob/main/examples/src/lemonslice_realtime_avatar_meeting.ts) in the LiveKit Agents JS examples |

Both show a full worker that reads `meeting_url` from job metadata, joins the call, and starts the agent session with meeting-aware room options.
