Can you deploy python api on livekit cloud. The py...
# ask-ai
g
Can you deploy python api on livekit cloud. The python api also contains the livekit agent
t
Thanks for reaching out, Michael. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Thanks — yes, you can deploy a Python API that contains a LiveKit agent to LiveKit Cloud. What you can do next 1. Add the LiveKit Agents SDK and implement your agent entrypoint (for example using an
AgentSession
and an
rtc_session
handler). 2. Use the LiveKit CLI to register and deploy the agent from your project: ◦
lk agent create
— registers the agent, builds a container (it will generate a Dockerfile if needed), and deploys to LiveKit Cloud. 1. Monitor and manage the deployment with: ◦
lk agent status
◦
lk agent logs
◦ LiveKit Cloud dashboard for metrics and errors If you’d like, tell me: • whether you already have an
AgentSession
entrypoint (paste the minimal snippet), or • the repo layout (files like
Dockerfile
,
requirements.txt
), and I’ll give exact CLI commands or a Dockerfile and minimal example tailored to your project. Sources: Deploying to production | LiveKit Docs | An open source stack for real-time multimodal AI | Voice AI quickstart | LiveKit docs
g
command to set envs from a file
t
You can load env vars from a file when creating or updating an agent using the
--secrets-file
flag. The file should be KEY=VALUE lines (e.g.,
.env
). • Create/deploy agent with file:
Copy code
lk agent create --secrets-file .env
• Update secrets for an existing agent:
Copy code
lk agent update-secrets --secrets-file .env
Note:
LIVEKIT_API_KEY
,
LIVEKIT_API_SECRET
, and
LIVEKIT_URL
are provided by LiveKit Cloud and are excluded from secret uploads. For local testing, you can load the same file with `python-dotenv`:
Copy code
from dotenv import load_dotenv
load_dotenv()
Sources: Server-side | livekit/livekit_composite | DeepWiki | Agents (Python) | livekit/livekit_composite | DeepWiki | Simple Call Answering Agent | LiveKit docs | Company directory phone assistant | LiveKit docs
g
what commands should come before this
lk agent create --secrets-file .env
t
You're asking which commands to run before
lk agent create --secrets-file .env
. Below are the typical prerequisites and commands in order. 1. Install LiveKit CLI (if not installed) • Follow platform installer or package manager for
lk
(one-time). 1. Authenticate with LiveKit Cloud
Copy code
lk cloud auth
1. (Optional) Select or set your cloud project / context
Copy code
lk cloud project list
# if needed
lk cloud project set <PROJECT_ID>
1. Initialize or prepare your agent project (if not already)
Copy code
# create a starter project (example)
uv init livekit-voice-agent --bare
cd livekit-voice-agent
1. Install dependencies for your Python agent
Copy code
# example using pip/poetry/uv
pip install "livekit-agents[silero,turn-detector]~=1.3" "livekit-plugins-noise-cancellation~=0.2" python-dotenv
1. Create and verify your
.env
file (KEY=VALUE lines) • Include any provider keys your agent needs. Note:
LIVEKIT_API_KEY
,
LIVEKIT_API_SECRET
, and
LIVEKIT_URL
are provided by LiveKit Cloud and are excluded when uploading secrets. After these steps you can run:
Copy code
lk agent create --secrets-file .env
If you want, paste your project layout or
.env
contents (redact secrets) and I’ll confirm any missing keys or exact install commands for your setup. Sources: Voice AI quickstart | LiveKit docs | Deploying to production | LiveKit Docs
g
nice
t
Glad it helped — happy to keep assisting. Would you like me to: • Review your
.env
(redact values) for required keys? • Generate a sample
Dockerfile
or
lk
workflow for your project? • Provide exact install commands for your package manager (pip/poetry)? • Or walk through the
lk agent create
output and how to verify the deployment? Pick one and I’ll take it from there.
g
how to view the agent log on the dashboard
t
Good question — here’s how to view your agent logs in the LiveKit Cloud dashboard. 1. Open the LiveKit Cloud dashboard and choose your project. 2. Click the Agents section in the sidebar. 3. Select the agent you deployed. 4. Open the Logs tab in the agent view — it shows info/warn/error/debug messages in chronological order (agent code, media server, and client events). If you want real-time streaming from your terminal, run:
Copy code
lk agent logs <AGENT_NAME_OR_ID> --follow
Would you like me to check a specific agent’s logs now? If so, share the agent name or paste a redacted error snippet and I’ll help interpret it. Sources: https://blog.livekit.io/streamline-troubleshooting-with-agent-observability/#/portal| | Deploying to production | LiveKit Docs
g
can you show me how to deploy the agent using ci/cd - github actions
t
I can show you a ready GitHub Actions workflow to deploy a LiveKit Python agent and explain the prerequisites. Below is a concise example you can drop into
.github/workflows/deploy-agent.yml
. Prerequisites • Run
lk agent create
locally once to generate
livekit.toml
(commit it). • Add repo secrets:
LIVEKIT_API_KEY
,
LIVEKIT_API_SECRET
,
LIVEKIT_URL
, plus any other provider keys (e.g.,
OPENAI_API_KEY
). • Ensure your repo has your agent code and dependencies (pyproject/requirements, optional Dockerfile). Example workflow (.github/workflows/deploy-agent.yml)
Copy code
name: Deploy LiveKit Agent

on:
  push:
    branches: [ main ]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.11'

      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install poetry || true
          # adjust for your project manager:
          poetry install || pip install -r requirements.txt

      - name: Install LiveKit CLI
        run: |
          curl -sSL <https://get.livekit.io> | bash
          echo "$HOME/.local/bin" >> $GITHUB_PATH

      - name: Authenticate LiveKit CLI
        env:
          LIVEKIT_API_KEY: ${{ secrets.LIVEKIT_API_KEY }}
          LIVEKIT_API_SECRET: ${{ secrets.LIVEKIT_API_SECRET }}
          LIVEKIT_URL: ${{ secrets.LIVEKIT_URL }}
        run: |
          # ensure lk can use the provided credentials for cloud operations
          lk cloud auth --api-key "$LIVEKIT_API_KEY" --api-secret "$LIVEKIT_API_SECRET" --url "$LIVEKIT_URL"

      - name: Deploy agent
        env:
          # include any runtime secrets your agent needs
          OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
          OTHER_SECRET: ${{ secrets.OTHER_SECRET }}
        run: |
          # create (first time) or deploy/update
          # use `lk agent deploy` if agent already registered, or `lk agent create --secrets-file .env` if creating.
          # if you maintain secrets in GitHub, you can write them to a temp file:
          cat > .env <<EOF
          OPENAI_API_KEY=${OPENAI_API_KEY}
          OTHER_SECRET=${OTHER_SECRET}
          EOF

          # Deploy (uses livekit.toml to identify agent)
          lk agent deploy --secrets-file .env
Notes and tips • Use
lk agent create --secrets-file .env
locally if you haven't registered the agent yet; commit the generated
livekit.toml
. • The CLI excludes
LIVEKIT_*
vars from secret uploads; provide them via GitHub Secrets for authentication. • For rollbacks, use
lk agent rollback
in a separate workflow if desired. • If you prefer not to write secrets to a file in the workflow, use
lk agent deploy
and rely on secrets configured in the LiveKit Cloud UI. Want this tailored to your repo? Share which package manager you use (pip/poetry), whether you already have
livekit.toml
committed, and which runtime secrets you need; I’ll customize the workflow. Sources: Deploying to production | LiveKit Docs | Examples | livekit/livekit_composite | DeepWiki
g
so you authenticate with the api key
t
Yes — you authenticate with the LiveKit API using three values:
LIVEKIT_API_KEY
,
LIVEKIT_API_SECRET
, and
LIVEKIT_URL
. How to use them in CI/CD (GitHub Actions) • Add these three as GitHub repository Secrets:
LIVEKIT_API_KEY
,
LIVEKIT_API_SECRET
,
LIVEKIT_URL
. • In your workflow, pass them as environment variables to the step that runs the LiveKit CLI. Example snippet:
Copy code
- name: Authenticate LiveKit CLI
  env:
    LIVEKIT_API_KEY: ${{ secrets.LIVEKIT_API_KEY }}
    LIVEKIT_API_SECRET: ${{ secrets.LIVEKIT_API_SECRET }}
    LIVEKIT_URL: ${{ secrets.LIVEKIT_URL }}
  run: |
    lk cloud auth --api-key "$LIVEKIT_API_KEY" --api-secret "$LIVEKIT_API_SECRET" --url "$LIVEKIT_URL"
Notes • The LiveKit CLI (and Cloud) automatically provide
LIVEKIT_*
values to deployed agents, so these are excluded from secret uploads when using
--secrets-file
. • For agent creation/deploy steps that need other runtime secrets (OpenAI, etc.), store those separately in GitHub Secrets and supply them via
--secrets-file
or environment variables in the workflow. Want me to add this exact auth step into your existing workflow file? Paste it and I’ll insert it for you.
g
how will the pipeline knows which project or env to use imageine we want to deploy to staging and prod
t
Good question — here’s how the pipeline knows which LiveKit project/environment to use and a minimal GitHub Actions pattern for staging vs production. Acknowledgement • You want deployments to target different LiveKit projects/environments (e.g., staging vs production). How the pipeline selects the target • Priority order the CLI uses: a. CLI flags (explicit) — e.g.,
--project
,
--api-key
,
--api-secret
,
--url
b. Environment variables —
LIVEKIT_API_KEY
,
LIVEKIT_API_SECRET
,
LIVEKIT_URL
c. Project file —
livekit.toml
in the repo Recommended approach (GitHub Actions) • Store environment-specific credentials as GitHub Secrets (e.g.,
STAGING_LIVEKIT_API_KEY
,
PROD_LIVEKIT_API_KEY
, etc.). • Determine target by branch, workflow input, or environment variable, and pass the appropriate secrets to the
lk
command (either via env vars or explicit flags). Minimal example (branch-based)
Copy code
name: Deploy LiveKit Agent
on:
  push:
    branches: [ main, staging ]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install LiveKit CLI
        run: curl -sSL <https://get.livekit.io> | bash && echo "$HOME/.local/bin" >> $GITHUB_PATH

      - name: Set target env
        id: vars
        run: |
          if [[ "${GITHUB_REF}" == "refs/heads/main" ]]; then
            echo "ENV=production" >> $GITHUB_OUTPUT
          else
            echo "ENV=staging" >> $GITHUB_OUTPUT
          fi

      - name: Deploy
        env:
          # choose secrets based on ENV
          LIVEKIT_URL: ${{ secrets[ format('{0}_LIVEKIT_URL', steps.vars.outputs.ENV | upper) ] }}
          LIVEKIT_API_KEY: ${{ secrets[ format('{0}_LIVEKIT_API_KEY', steps.vars.outputs.ENV | upper) ] }}
          LIVEKIT_API_SECRET: ${{ secrets[ format('{0}_LIVEKIT_API_SECRET', steps.vars.outputs.ENV | upper) ] }}
        run: |
          # authenticate and deploy; explicit flags can also be used:
          lk cloud auth --api-key "$LIVEKIT_API_KEY" --api-secret "$LIVEKIT_API_SECRET" --url "$LIVEKIT_URL"
          lk agent deploy
Alternatives • Use explicit CLI flags in the deploy step: lk agent deploy --project "staging-subdomain" --api-key "$STAGING_KEY" --api-secret "$STAGING_SECRET" --url "$STAGING_URL" • Generate or swap a
livekit.toml
at runtime if you prefer config file-driven selection. Best practices • Keep per-env secrets in GitHub Secrets (e.g.,
PROD_*
,
STAGING_*
). • Restrict production deployments to protected branches or workflows. • Log the chosen environment (non-secret) in CI for traceability. Would you like a version of this workflow that uses workflow inputs instead of branch detection, or that writes
livekit.toml
dynamically? Sources: Server-side | livekit/livekit_composite | DeepWiki | Deploying to production | LiveKit Docs
g
will this help here livekit.toml, can we use livekit.toml to deploy?
t
Yes —
livekit.toml
can be used to drive deployments. What
livekit.toml
does • It contains project and agent metadata (agent id, project subdomain, etc.) that the CLI uses to identify which agent and project to deploy. • When present in the repo,
lk agent deploy
reads
livekit.toml
so you don’t need to pass project flags every time. How to use it for multi-env deployments • Option A — Commit one file per environment and switch in CI: ◦ Keep
livekit.staging.toml
and
livekit.prod.toml
in the repo. ◦ In CI, copy the right file into
livekit.toml
before running
lk agent deploy
. Example:
Copy code
if [ "$TARGET" = "prod" ]; then
      cp livekit.prod.toml livekit.toml
    else
      cp livekit.staging.toml livekit.toml
    fi
    lk agent deploy --secrets-file .env
• Option B — Generate
livekit.toml
in CI: ◦ Use a small template and fill values from GitHub Secrets or workflow inputs, then save to
livekit.toml
. • Option C — Use explicit CLI flags or env vars instead: ◦ Pass
--project
or set
LIVEKIT_API_KEY/SECRET/URL
in CI to override
livekit.toml
. Recommendations • Store per-environment credentials as separate GitHub Secrets (e.g.,
STAGING_*
,
PROD_*
) and use them in CI. • Use branch protections so only main can deploy production. • Prefer copying or generating
livekit.toml
in CI so the repo doesn’t contain secret or mutable env-specific state. Want a small GitHub Actions snippet that swaps
livekit.toml
based on branch or workflow input? I can generate it for your repo structure.
g
yes, also what should the content of livekit.toml be
t
Below is a minimal example
livekit.toml
and a short GitHub Actions snippet that swaps it for staging vs production. Example
livekit.toml
(minimal)
Copy code
[project]
subdomain = "your-project-subdomain"  # project subdomain or identifier

[agent]
id = "your-agent-id"                  # agent id assigned when created
name = "my-agent"                     # optional friendly name
version = "1.0.0"                     # optional
Optional fields you may include •
[agent].env
— maps keys to values that will be set for the agent at deploy time (avoid secrets in repo). •
[agent].replicas
— desired replica count. •
[agent].resources
— CPU/memory hints if supported. Example CI pattern: swap files in GitHub Actions
Copy code
- name: Prepare livekit.toml for target
  run: |
    if [[ "${GITHUB_REF}" == "refs/heads/main" ]]; then
      cp livekit.prod.toml livekit.toml
    else
      cp livekit.staging.toml livekit.toml
    fi

- name: Deploy agent
  env:
    LIVEKIT_API_KEY: ${{ secrets.STAGING_LIVEKIT_API_KEY }}   # choose secrets per env
    LIVEKIT_API_SECRET: ${{ secrets.STAGING_LIVEKIT_API_SECRET }}
    LIVEKIT_URL: ${{ secrets.STAGING_LIVEKIT_URL }}
  run: |
    lk cloud auth --api-key "$LIVEKIT_API_KEY" --api-secret "$LIVEKIT_API_SECRET" --url "$LIVEKIT_URL"
    lk agent deploy --secrets-file .env
Notes • Do not store secrets in `livekit.toml`; keep env-specific credentials in GitHub Secrets and pass them in CI. •
livekit.toml
created by
lk agent create
includes full metadata — you can edit or generate it in CI as needed. If you want, paste your current
livekit.toml
(redact secrets) and I’ll review it or generate staging/prod variants.
g
Getting this error during deploy, can you give a simple deployment file , was getting this error Run lk cloud auth --api-key "$LIVEKIT_API_KEY" --api-secret "$LIVEKIT_API_SECRET" --url "$LIVEKIT_URL" < /dev/null lk cloud auth --api-key "$LIVEKIT_API_KEY" --api-secret "$LIVEKIT_API_SECRET" --url "$LIVEKIT_URL" < /dev/null lk project add \ --api-key "$LIVEKIT_API_KEY" \ --api-secret "$LIVEKIT_API_SECRET" \ --url "$LIVEKIT_URL" \ --default staging < /dev/null || echo "Project may already be configured" shell: /usr/bin/bash -e {0} env: PYTHON_VERSION: 3.11 LIVEKIT_API_KEY: * LIVEKIT_API_SECRET: * LIVEKIT_URL: * VOICE_API_BASE_URL: * huh: could not open a new TTY: open /dev/tty: no such device or address Error: Process completed with exit code 1.
Copy code
- name: Install LiveKit CLI
        run: |
          curl -sSL <https://get.livekit.io/cli> | bash
          lk --version

- name: Authenticate and configure LiveKit
        env:
          LIVEKIT_API_KEY: ${{ env.LIVEKIT_API_KEY }}
          LIVEKIT_API_SECRET: ${{ env.LIVEKIT_API_SECRET }}
          LIVEKIT_URL: ${{ env.LIVEKIT_URL }}
        run: |
          lk cloud auth --api-key "$LIVEKIT_API_KEY" --api-secret "$LIVEKIT_API_SECRET" --url "$LIVEKIT_URL" < /dev/null
          lk project add \
            --api-key "$LIVEKIT_API_KEY" \
            --api-secret "$LIVEKIT_API_SECRET" \
            --url "$LIVEKIT_URL" \
            --default ${{ needs.determine-environment.outputs.environment }} < /dev/null || echo "Project may already be configured"


- name: Prepare livekit.toml
        run: |
          ENV="${{ needs.determine-environment.outputs.environment }}"
          if [ "$ENV" = "production" ] && [ -f "livekit.prod.toml" ]; then
            cp livekit.prod.toml livekit.toml
            echo ":white_check_mark: Using livekit.prod.toml"
          elif [ "$ENV" = "staging" ] && [ -f "livekit.staging.toml" ]; then
            cp livekit.staging.toml livekit.toml
            echo ":white_check_mark: Using livekit.staging.toml"
          else
            echo ":warning: Using default livekit.toml"
          fi

- name: Set agent environment variables
        env:
          LIVEKIT_URL: ${{ env.LIVEKIT_URL }}
          LIVEKIT_API_KEY: ${{ env.LIVEKIT_API_KEY }}
          LIVEKIT_API_SECRET: ${{ env.LIVEKIT_API_SECRET }}
          VOICE_API_BASE_URL: ${{ env.VOICE_API_BASE_URL }}
        run: |
          lk agent env set LIVEKIT_URL="$LIVEKIT_URL" || true
          lk agent env set LIVEKIT_API_KEY="$LIVEKIT_API_KEY" || true
          lk agent env set LIVEKIT_API_SECRET="$LIVEKIT_API_SECRET" || true
          lk agent env set OPENAI_API_KEY="${{ secrets.OPENAI_API_KEY }}" || true
          lk agent env set DEEPGRAM_API_KEY="${{ secrets.DEEPGRAM_API_KEY }}" || true
          lk agent env set ELEVENLABS_API_KEY="${{ secrets.ELEVENLABS_API_KEY }}" || true
          lk agent env set ANTHROPIC_API_KEY="${{ secrets.ANTHROPIC_API_KEY }}" || true
          lk agent env set VOICE_API_BASE_URL="$VOICE_API_BASE_URL" || true
          lk agent env set VOICE_API_VERSION="${{ secrets.VOICE_API_VERSION || 'v2' }}" || true
          lk agent env set GCP_SERVICE_CREDENTIALS='${{ secrets.GCP_SERVICE_CREDENTIALS }}' || true
          lk agent env set FIREBASE_CREDENTIALS='${{ secrets.FIREBASE_CREDENTIALS }}' || true

- name: Deploy agent
        run: |
          if lk agent status > /dev/null 2>&1; then
            echo "Agent exists, deploying update..."
            lk agent deploy < /dev/null
          else
            echo "Agent does not exist, creating new agent..."
            lk agent create < /dev/null
          fi

- name: Verify deployment
        run: |
          echo "Checking agent status..."
          lk agent status || echo ":warning: Could not get agent status"
          sleep 30
          STATUS=$(lk agent status --json 2>/dev/null | jq -r '.status' || echo "unknown")
          if [ "$STATUS" != "running" ] && [ "$STATUS" != "unknown" ]; then
            echo ":warning: Warning: Agent status is $STATUS"
          else
            echo ":white_check_mark: Agent deployment completed"
          fi

      - name: View recent logs
        run: lk agent logs --tail 50 || echo "Could not retrieve logs"
        continue-on-error: true

      - name: Deployment notification
        if: always()
        run: |
          if [ "${{ job.status }}" = "success" ]; then
            echo ":white_check_mark: Deployed to ${{ needs.determine-environment.outputs.environment }}"
          else
            echo ":x: Deployment failed to ${{ needs.determine-environment.outputs.environment }}"
          fi
          echo "Commit: ${{ github.sha }}"
        continue-on-error: true
t
Thanks — that TTY error happens because
lk cloud auth
is interactive. Use non-interactive auth (flags or env vars) and avoid commands that open a TTY. Below is a simple, working GitHub Actions workflow that: • Installs the LiveKit CLI • Authenticates non-interactively via CLI flags or env vars • Creates or deploys the agent without interactive prompts • Passes runtime secrets securely Save as .github/workflows/deploy-agent.yml:
Copy code
name: Deploy LiveKit Agent

on:
  push:
    branches: [ main, staging ]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Install LiveKit CLI
        run: |
          curl -sSL <https://get.livekit.io/cli> | bash
          echo "$HOME/.local/bin" >> $GITHUB_PATH
          lk --version

      - name: Prepare env (choose staging/prod)
        id: env
        run: |
          if [[ "${GITHUB_REF##*/}" == "main" ]]; then
            echo "TARGET=production" >> $GITHUB_OUTPUT
          else
            echo "TARGET=staging" >> $GITHUB_OUTPUT
          fi

      - name: Deploy agent (non-interactive)
        env:
          # Provide per-env secrets in GitHub (e.g., PROD_* and STAGING_*)
          LIVEKIT_URL: ${{ secrets[ format('{0}_LIVEKIT_URL', steps.env.outputs.TARGET | upper) ] }}
          LIVEKIT_API_KEY: ${{ secrets[ format('{0}_LIVEKIT_API_KEY', steps.env.outputs.TARGET | upper) ] }}
          LIVEKIT_API_SECRET: ${{ secrets[ format('{0}_LIVEKIT_API_SECRET', steps.env.outputs.TARGET | upper) ] }}
          OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
          DEEPGRAM_API_KEY: ${{ secrets.DEEPGRAM_API_KEY }}
        run: |
          # Create or ensure livekit.toml exists (adjust subdomain)
          if [ ! -f livekit.toml ]; then
            cat > livekit.toml <<EOF
[project]
subdomain = "your-project-subdomain"
EOF
          fi

          # Use CLI flags to avoid any interactive auth
          if lk agent status --api-key "$LIVEKIT_API_KEY" --api-secret "$LIVEKIT_API_SECRET" --url "$LIVEKIT_URL" >/dev/null 2>&1; then
            echo "Agent exists — deploying update..."
            lk agent deploy \
              --api-key "$LIVEKIT_API_KEY" \
              --api-secret "$LIVEKIT_API_SECRET" \
              --url "$LIVEKIT_URL" \
              --secrets OPENAI_API_KEY="$OPENAI_API_KEY",DEEPGRAM_API_KEY="$DEEPGRAM_API_KEY"
          else
            echo "Creating new agent..."
            lk agent create \
              --api-key "$LIVEKIT_API_KEY" \
              --api-secret "$LIVEKIT_API_SECRET" \
              --url "$LIVEKIT_URL" \
              --secrets OPENAI_API_KEY="$OPENAI_API_KEY",DEEPGRAM_API_KEY="$DEEPGRAM_API_KEY"
          fi

      - name: Verify & tail logs
        env:
          LIVEKIT_API_KEY: ${{ secrets.LIVEKIT_API_KEY }}
          LIVEKIT_API_SECRET: ${{ secrets.LIVEKIT_API_SECRET }}
          LIVEKIT_URL: ${{ secrets.LIVEKIT_URL }}
        run: |
          lk agent status --api-key "$LIVEKIT_API_KEY" --api-secret "$LIVEKIT_API_SECRET" --url "$LIVEKIT_URL" || true
          lk agent logs --tail 50 --api-key "$LIVEKIT_API_KEY" --api-secret "$LIVEKIT_API_SECRET" --url "$LIVEKIT_URL" || true
Key fixes for your original error • Do not run
lk cloud auth
in CI — it is interactive and opens a TTY. • Use
--api-key
,
--api-secret
, and
--url
flags (or env vars) to authenticate non-interactively. • Prefer
--secrets
or
--secrets-file
during create/deploy to upload runtime secrets; do not store secrets in committed files. • If you need per-environment
livekit.toml
, swap or generate it in CI before deploy. If you want, paste your repo structure or the exact branch names and I’ll generate a ready-to-commit workflow that maps your STAGING/PROD GitHub secrets (e.g., STAGING_LIVEKIT_API_KEY, PROD_LIVEKIT_API_KEY). Sources: Agents (Python) | livekit/livekit_composite | DeepWiki
g
what about the livekit.toml, still needed?
t
Short answer: livekit.toml is helpful but not strictly required — the CLI can be driven entirely by flags/env vars. Use it when you want checked-in, reproducible agent/project metadata; omit it if you prefer to pass project credentials and options from CI. When to keep livekit.toml • Useful if you want a committed, versioned source of truth for project/agent metadata (agent id, project subdomain, defaults). • Makes
lk agent deploy
simple in CI because the CLI can infer project/agent from the file. • Good for teams that swap built artifacts between environments (you can maintain per-env TOML variants). When you can skip it • If your CI supplies
--api-key
,
--api-secret
,
--url
, and any other flags, the CLI will work without livekit.toml. • This is common when you want to fully drive environment selection from CI (branch, workflow input, or secrets). Recommended patterns • Per-environment TOML files: keep
livekit.staging.toml
and
livekit.prod.toml
and copy the right one into
livekit.toml
in CI before deploy. • Dynamic generation: template
livekit.toml
in CI using secrets/inputs and write it to workspace. • Flags-first CI: omit TOML and always call
lk agent deploy/create
with
--api-key/--api-secret/--url
(this avoids needing to manage TOML files). Minimal livekit.toml (if you use one)
Copy code
[project]
subdomain = "your-project-subdomain"

[agent]
id = "your-agent-id"
name = "my-agent"
version = "1.0.0"
Which to choose? • If you want simpler CI commands and a stable mapping in repo: use
livekit.toml
. • If you want fully ephemeral, secrets-driven CI: pass flags/env vars and skip TOML. Want me to generate the CI step that either swaps a per-env TOML or replaces it with a generated file? Tell me which you prefer and your branch names.
g
in this deploy.yaml file looks like its not used?
t
You're right — in the workflow you pasted, I don't see any step that actually uses or writes
livekit.toml
(other than the "Prepare livekit.toml" copy step earlier you shared). If you want the deploy step to rely on
livekit.toml
, add an explicit step that ensures the correct file exists before calling
lk agent create
/
lk agent deploy
. Two simple options to fix it (pick one): 1) Swap a per-env TOML into place (if you keep per-env files)
Copy code
- name: Prepare livekit.toml
  run: |
    if [ "${{ needs.determine-environment.outputs.environment }}" = "production" ]; then
      cp livekit.prod.toml livekit.toml
    else
      cp livekit.staging.toml livekit.toml
    fi
Place this step before the Deploy agent step. 2) Generate
livekit.toml
in CI (no checked-in file)
Copy code
- name: Generate livekit.toml
  run: |
    cat > livekit.toml <<EOF
[project]
subdomain = "${{ secrets.LIVEKIT_SUBDOMAIN }}"
[agent]
id = "${{ secrets.LIVEKIT_AGENT_ID }}"
EOF
Also run this before deploy. Populate subdomain/agent-id from secrets or workflow inputs. Notes • If you prefer not to use
livekit.toml
, the deploy/create commands will still work if you pass
--api-key
,
--api-secret
, and
--url
(which your workflow already does). In that case you can remove the prepare/generate steps. • If you want, tell me which option you prefer and your environment names and I’ll return the exact snippet merged into your workflow.
g
thanks, seems to work, curious how it will for prod, the prod deploy is a manual deploy. for staging we already have this livekit.staging.toml file gotten from the first time we deploy yhe agent using cli by running lk deploy agent How will this work for prod? step
Copy code
- name: Prepare livekit.toml
        run: |
          ENV="${{ needs.determine-environment.outputs.environment }}"
          if [ "$ENV" = "production" ] && [ -f "livekit.prod.toml" ]; then
            cp livekit.prod.toml livekit.toml
            echo ":white_check_mark: Using livekit.prod.toml"
          elif [ "$ENV" = "staging" ] && [ -f "livekit.staging.toml" ]; then
            cp livekit.staging.toml livekit.toml
            echo ":white_check_mark: Using livekit.staging.toml"
          else
            echo ":warning: Using default livekit.toml"
          fi
logs
Copy code
ENV="staging"
  if [ "$ENV" = "production" ] && [ -f "livekit.prod.toml" ]; then
    cp livekit.prod.toml livekit.toml
    echo ":white_check_mark: Using livekit.prod.toml"
  elif [ "$ENV" = "staging" ] && [ -f "livekit.staging.toml" ]; then
    cp livekit.staging.toml livekit.toml
    echo ":white_check_mark: Using livekit.staging.toml"
  else
    echo ":warning: Using default livekit.toml"
  fi
  shell: /usr/bin/bash -e {0}
  env:
    PYTHON_VERSION: 3.11
    LIVEKIT_API_KEY: ***
    LIVEKIT_API_SECRET: ***
    LIVEKIT_URL: ***
    VOICE_API_BASE_URL: ***
:white_check_mark: Using livekit.staging.toml
t
Great — glad staging works. Regarding prod: you can handle it two ways depending on your workflow (manual vs automatic). Here’s how it will behave and simple options to support a manual production deploy. Acknowledgement • Your workflow already copies the correct TOML for staging. For production you need a
livekit.prod.toml
(or to generate one) so the same step picks it up when ENV=production. Options for production 1) Manual GitHub Actions deploy (recommended if you want control) • Add a manual trigger and require the production
livekit.prod.toml
be present (committed or stored as a secret/template). • Example job trigger:
Copy code
on:
  workflow_dispatch:
    inputs:
      environment:
        required: true
        type: choice
        options: [staging, production]
• Your existing Prepare step will copy
livekit.prod.toml
when
environment=production
. Then the deploy step runs and uses that file. 2) Create
livekit.prod.toml
from the agent created in prod • Run
lk agent create
or
lk agent deploy
once manually against the production project. That generates the canonical
livekit.toml
you can save as
livekit.prod.toml
. • Store it in the repo (if safe) or keep it encrypted/templated and generate it in CI from secrets:
Copy code
cat > livekit.prod.toml <<EOF
[project]
subdomain = "${{ secrets.PROD_LIVEKIT_SUBDOMAIN }}"
[agent]
id = "${{ secrets.PROD_AGENT_ID }}"
EOF
3) Avoid committing TOML at all (flag-driven) • Have CI pass
--api-key/--api-secret/--url
(and
--project
if needed) to
lk agent deploy
. This makes
livekit.toml
optional and is useful if you want all prod config driven by secrets and the manual trigger controls environment. Key notes • If production deploy is manual, use workflow_dispatch and require approvers or protected branch checks to limit who can run it. • Ensure you store prod credentials as separate secrets (e.g.,
PROD_LIVEKIT_API_KEY
) and wire them into the workflow when environment=production. • If you generated
livekit.prod.toml
from a manual
lk
run, the file will include the correct agent id/subdomain so CI can call
lk agent deploy
without extra flags. If you want, I can: • Generate a full example workflow with a manual
workflow_dispatch
prod deploy that swaps
livekit.prod.toml
and uses prod secrets, or • Show the exact commands to generate
livekit.prod.toml
from your local machine (paste your current
livekit.staging.toml
as reference). Which do you prefer?
g
which is the best option using the toml files or doing everthing in the ci
t
Good question — both approaches work; the best choice depends on team preferences. Here’s a concise comparison and my recommendation. Quick summary • Use per-env TOML files when you want a human-readable, versioned mapping of agent/project metadata in the repo. • Use CI-driven flags/env-vars when you want secrets and environment selection fully controlled by the pipeline (no checked-in env files). Pros / cons 1) Per-environment livekit.toml (livekit.staging.toml, livekit.prod.toml) • Pros: ◦ Simple CI: just copy the right file and run
lk agent deploy
. ◦ Reproducible, auditable agent/project metadata stored in repo. ◦ Easier for teams that want explicit agent IDs/subdomains tracked. • Cons: ◦ Risk of stale or leaked sensitive info if you commit too much (avoid secrets in TOML). ◦ Needs management of multiple files when agent metadata changes. 2) CI-driven (no TOML; pass flags/envs) • Pros: ◦ Secrets remain in CI secret store only; no repo files to manage. ◦ Flexible: same workflow can target any environment using secrets or inputs. ◦ Good for ephemeral or heavily automated pipelines. • Cons: ◦ Slightly more complex CI logic (you must construct flags or generate TOML on the fly). ◦ Agent metadata is implicit (driven by secrets/flags), less visible in repo. My recommendation (balanced / safe) • Store non-secret metadata in per-env TOML templates (livekit.staging.toml / livekit.prod.toml) but do NOT commit secrets. • Keep production deploy manual (workflow_dispatch) and protect it with branch/reviewer rules. • In CI, copy the appropriate TOML into place OR generate it from secrets, then call
lk agent deploy
with
--api-key/--api-secret/--url
drawn from per-env GitHub Secrets. ◦ This gives reproducibility (TOML) + secure secrets handling (CI secrets). ◦ Example: copy livekit.prod.toml -> livekit.toml, then run
lk agent deploy --api-key "$PROD_KEY" --api-secret "$PROD_SECRET" --url "$PROD_URL" --secrets ...
If you prefer, I can: • Generate a ready-to-use workflow that implements this hybrid pattern (templated TOML + per-env secrets + manual prod trigger). Which branch names and secret names do you use for staging/prod?
g
okay thanks 🙂
can you pass toml file to agent deploy the first time creating the agent for prod
t
Yes — you can use a
livekit.toml
on the first creation/deploy for prod. The CLI reads
livekit.toml
in the repo, so just ensure the file is present (or written) before running
lk agent create
or
lk agent deploy
. Simple steps (one-time create for prod) 1. Place or generate
livekit.prod.toml
in the repo (or keep it in CI secrets/templates). Ensure it has the correct project subdomain and the agent id if you already have one, e.g.:
Copy code
[project]
subdomain = "your-prod-subdomain"

[agent]
id = "your-agent-id"   # optional for create; useful for later deploys
name = "prod-agent"
1. In CI (or locally) copy it to
livekit.toml
and run create:
Copy code
cp livekit.prod.toml livekit.toml
lk agent create \
  --api-key "$PROD_LIVEKIT_API_KEY" \
  --api-secret "$PROD_LIVEKIT_API_SECRET" \
  --url "$PROD_LIVEKIT_URL" \
  --secrets-file .env
Notes • If
livekit.toml
contains an
agent.id
,
lk agent create
will register/update that agent; omitting
agent.id
lets the CLI generate an ID and write a
livekit.toml
locally. • Pass credentials via flags or env vars in CI to avoid interactive auth. • Use
--secrets-file
or
--secrets
to upload runtime secrets (do not commit secrets into TOML). • After the first create, commit the generated
livekit.toml
(or save it as
livekit.prod.toml
) so future CI deploys can use
lk agent deploy
without extra flags. If you want, I can produce the exact GitHub Actions snippet that copies
livekit.prod.toml
, injects prod secrets, and runs
lk agent create
as a manual
workflow_dispatch
step. Which do you prefer?
g
what should be inside it
t
Use a minimal
livekit.toml
that declares the project subdomain and (optionally) the agent metadata. Do NOT put secrets in it. Minimal example (suitable for creating the agent the first time):
Copy code
[project]
subdomain = "your-prod-subdomain"

[agent]
name = "my-prod-agent"    # optional friendly name
# omit `id` when creating first time — the CLI will generate one and write it back
If you already have an agent ID (e.g., exported from a manual create), include it so CI can target the same agent:
Copy code
[project]
subdomain = "your-prod-subdomain"

[agent]
id = "generated-agent-id"
name = "my-prod-agent"
version = "1.0.0"
Optional non-secret fields you may include: •
[agent].replicas
— desired replica count •
[agent].resources
— CPU/memory hints (if used) •
[agent].env
— non-secret defaults (avoid sensitive values) How to use in CI for first-time prod create 1. Ensure
livekit.prod.toml
(above) is copied to
livekit.toml
in the workspace. 2. Run non-interactive create with CI secrets: lk agent create --api-key "$PROD_LIVEKIT_API_KEY" --api-secret "$PROD_LIVEKIT_API_SECRET" --url "$PROD_LIVEKIT_URL" --secrets-file .env Notes • Keep secrets (API keys, provider keys) in your CI secret store and pass via
--secrets-file
or `--secrets`; do not commit them into TOML. • After
lk agent create
the CLI will write the generated
agent.id
into
livekit.toml
— save that as
livekit.prod.toml
for future deploys. Sources: Deploying to production | LiveKit Docs | Examples | livekit/livekit_composite | DeepWiki | Custom agent deployments | LiveKit docs
g
samle command with the toml file
t
Use
livekit.toml
in the workspace and pass credentials non-interactively via flags or env vars. Example — first-time create (copies prod TOML, creates agent, uploads secrets):
Copy code
cp livekit.prod.toml livekit.toml

# create agent (non-interactive)
lk agent create \
  --api-key "$PROD_LIVEKIT_API_KEY" \
  --api-secret "$PROD_LIVEKIT_API_SECRET" \
  --url "$PROD_LIVEKIT_URL" \
  --secrets-file .env
Example — subsequent deploy using the committed/generated `livekit.toml`:
Copy code
# ensure livekit.toml present (contains [project] subdomain and [agent].id)
lk agent deploy \
  --api-key "$PROD_LIVEKIT_API_KEY" \
  --api-secret "$PROD_LIVEKIT_API_SECRET" \
  --url "$PROD_LIVEKIT_URL" \
  --secrets-file .env
Notes • Do not put secrets in `livekit.toml`; keep them in
.env
or CI secrets. • For CI, set
PROD_LIVEKIT_API_KEY
,
PROD_LIVEKIT_API_SECRET
,
PROD_LIVEKIT_URL
as protected secrets and run the same commands in a workflow step.
g
I am talking about a manual create in the CLI, can you pass the toml file for the first time locally
t
Yes — you can use a local
livekit.toml
for a manual, first-time
lk agent create
. The CLI will read
livekit.toml
from the current directory; you don’t pass it as a flag. Steps (local, manual) 1. Create
livekit.toml
in your project root. Minimal example:
Copy code
[project]
subdomain = "your-prod-subdomain"

[agent]
name = "my-prod-agent"
# omit `id` for first-time create so the CLI generates one
1. Prepare a
.env
(or provide secrets via env vars) with runtime secrets (do NOT store these in the TOML):
Copy code
OPENAI_API_KEY=...
DEEPGRAM_API_KEY=...
# etc.
1. Run the create command from the directory containing `livekit.toml`:
Copy code
# using .env file for secrets
lk agent create \
  --api-key "$PROD_LIVEKIT_API_KEY" \
  --api-secret "$PROD_LIVEKIT_API_SECRET" \
  --url "$PROD_LIVEKIT_URL" \
  --secrets-file .env
What happens • The CLI reads
livekit.toml
, registers the agent, generates an
agent.id
, and updates/writes
livekit.toml
with that id. • Save that updated file (or copy it to
livekit.prod.toml
) for future CI deploys. Notes • Don’t put API keys or other secrets in
livekit.toml
. Use
--secrets-file
or CI secret stores. • If you already have an
agent.id
, include it in
livekit.toml
to target the same agent on create/deploy. Want me to generate a
livekit.prod.toml
for your subdomain/name?
g
can I generate the livekit.prod.toml without deplying the agent, to have name and id
t
Short answer: No — you cannot get a real agent ID without creating the agent. The agent ID is assigned by LiveKit Cloud during
lk agent create
, so a true
livekit.prod.toml
with a valid
agent.id
only exists after a create/deploy. What you can do instead • Manual template: create a
livekit.prod.toml
template with the project subdomain and agent name (omit
id
) and run
lk agent create
to generate the real file:
Copy code
[project]
  subdomain = "your-prod-subdomain"

  [agent]
  name = "my-prod-agent"
After
lk agent create
the CLI will write the generated
agent.id
into `livekit.toml`; copy or save that as
livekit.prod.toml
. • Create once locally (recommended): run the one-time local create (manual or via a protected workflow) to generate the full
livekit.toml
, then save it as
livekit.prod.toml
for CI use. • Manual authoring if you already know the ID: if you already have an agent id (from dashboard or prior deploy), you can manually create `livekit.prod.toml`:
Copy code
[project]
  subdomain = "your-prod-subdomain"

  [agent]
  id = "existing-agent-id"
  name = "my-prod-agent"
• CI generation after create: run a protected/manual create step in CI that writes the generated
livekit.toml
to an artifact or secret store for future deploys. If you want, I can: • Generate a template
livekit.prod.toml
for you, or • Provide the exact
lk agent create
command you should run locally to produce the final file. Which do you prefer? Sources: Deploying to production | LiveKit Docs | Voice AI quickstart | LiveKit docs | Google AI and LiveKit | LiveKit Docs
g
best wayt to prevent calls from being routed to the agent basically to make it inactive
t
Good question — here are the practical ways to make an agent inactive so calls stop routing to it. Choose the one that fits your setup. 1) Remove or update the dispatch rule (recommended for inbound calls) • Delete the dispatch rule that routes calls to the agent, or remove the agent from the rule’s
room_config.agents
. No dispatch rule → no routing. • CLI example: ◦ List:
lk sip dispatch list
◦ Delete:
lk sip dispatch delete <DISPATCH_RULE_ID>
2) Scale down or stop the agent process • Stop the agent service or scale replicas to zero. If the agent isn’t running it can’t accept jobs. • For LiveKit Cloud, deploy with fewer replicas or stop the agent. 3) Remove agent from explicit dispatch configuration • If you use explicit agent dispatch, remove the agent name from the dispatch config so it’s not selectable: ◦ Update rule JSON: set
room_config.agents = []
or remove the agent entry, then redeploy the rule. 4) Prevent registration (code-level) • Add a runtime flag or config so the agent does not register/join rooms (e.g., skip the
AgentSession
start). This is useful for graceful disable during maintenance. Best practice • For temporary disablement, update/delete the dispatch rule. For maintenance windows or long-term disablement, both stop the agent process and update dispatch rules. • Keep dispatch rule changes and prod disabling behind protected workflows or approvals to avoid accidental outages. If you tell me which dispatch method you use (SIP dispatch rules, explicit agent dispatch, or direct API assignments) and whether the agent runs in LiveKit Cloud, I can give the exact CLI/API command or a small script to make it inactive. Sources: Creating SIP Inbound Trunks and Dispatch Rules with Python SDK | Python SDKs | livekit/livekit_composite | DeepWiki | Agents telephony integration | LiveKit docs | Server lifecycle | LiveKit docs | Deploying to production | LiveKit Docs
g
there should be an easy way to do it
t
You’re right — the simplest, one-line way to stop calls routing to an agent is to remove or disable the dispatch rule that sends calls to it. Quick option (recommended): • Delete the dispatch rule: lk sip dispatch delete <DISPATCH_RULE_ID> Or disable/update it (non-destructive): • Remove the agent from the rule’s room_config.agents or change the rule so it no longer matches incoming calls. If you tell me which dispatch type you use (SIP dispatch, explicit agent dispatch, or direct API assignment) and the rule id or agent name, I’ll give the exact command/snippet to run.
g
does livekit have the concept of versioning, call you rollback a deployment?
t
Yes — LiveKit versions agent deployments and supports rollbacks. What you can do • List past versions: lk agent versions • Roll back to the previous (or a specific) version: lk agent rollback Notes • Rollbacks use the same rolling update strategy as deployments, so active sessions are drained gracefully. • Instant rollback is available on paid LiveKit Cloud plans; on free plans you must revert code and redeploy manually. Want the exact commands added to your CI (or a protected rollback workflow)? I can generate that for your repo/branch setup. Sources: Deploying to production | LiveKit Docs | server-sdk-go | livekit/livekit_composite | DeepWiki
g
all this must be done in the CLI?
t
No — you don’t have to do everything in the CLI. Options and where they fit: • CLI (recommended for local / quick ops): best for init, one-off create, inspect (
lk agent create/deploy/status/logs/rollback
). • CI/CD (recommended for automated workflows): install
lk
in pipeline and run
lk agent deploy/create
non-interactively or generate
livekit.toml
in CI. Good for automated builds, secrets from CI, and protected prod deploys. • Server SDK / API (programmatic control): use LiveKit Server SDKs to script management, update dispatch rules, or call admin APIs from your services. • Dashboard (web UI): view logs, metrics, and some management actions; good for monitoring and manual inspection. When to use what: • Local dev / first-time create: CLI. • Reproducible automated deploys and rollbacks: CI/CD calling CLI (or API) with secrets. • Dynamic or embedded management (e.g., auto-scaling, programmatic dispatch changes): Server SDK/API. • Quick checks and log viewing: Dashboard. If you tell me which parts you want to avoid the CLI for (deploy, rollback, env updates, logs, or disabling agents), I’ll give the exact CI or API snippet to implement it. Sources: Examples | livekit/livekit_composite | DeepWiki | Testing and evaluation | LiveKit docs | Python SDKs | livekit/livekit_composite | DeepWiki | An open source stack for real-time multimodal AI | Agent session | LiveKit docs
g
how will you implement rollback into the pipeline
t
You can implement rollback in CI by invoking the LiveKit CLI rollback command from a protected workflow or a manual workflow_dispatch job. Key ideas: require manual approval for prod rollbacks, pass non-interactive credentials, and record which version to roll back to. Minimal GitHub Actions patterns 1) Manual rollback (safe for production) • Trigger: workflow_dispatch with an input for target version (or use "previous"). • Protection: restrict who can run the workflow (branch protection / required reviewers). • Action: call
lk agent rollback
with flags to avoid interactive auth. Example workflow (drop into .github/workflows/rollback.yml):
Copy code
name: Rollback LiveKit Agent

on:
  workflow_dispatch:
    inputs:
      environment:
        required: true
        type: choice
        options: [staging, production]
      version:
        required: false
        description: 'Version ID to roll back to (omit to rollback one step)'

jobs:
  rollback:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Install LiveKit CLI
        run: |
          curl -sSL <https://get.livekit.io/cli> | bash
          echo "$HOME/.local/bin" >> $GITHUB_PATH
          lk --version

      - name: Set env for target
        run: echo "running rollback"

      - name: Run rollback
        env:
          # Use per-env secrets: e.g., STAGING_LIVEKIT_API_KEY or PROD_LIVEKIT_API_KEY
          LIVEKIT_API_KEY: ${{ secrets[ format('{0}_LIVEKIT_API_KEY', github.event.inputs.environment | upper) ] }}
          LIVEKIT_API_SECRET: ${{ secrets[ format('{0}_LIVEKIT_API_SECRET', github.event.inputs.environment | upper) ] }}
          LIVEKIT_URL: ${{ secrets[ format('{0}_LIVEKIT_URL', github.event.inputs.environment | upper) ] }}
        run: |
          if [ -n "${{ github.event.inputs.version }}" ]; then
            lk agent rollback --version "${{ github.event.inputs.version }}" \
              --api-key "$LIVEKIT_API_KEY" --api-secret "$LIVEKIT_API_SECRET" --url "$LIVEKIT_URL"
          else
            lk agent rollback \
              --api-key "$LIVEKIT_API_KEY" --api-secret "$LIVEKIT_API_SECRET" --url "$LIVEKIT_URL"
          fi
2) Automated rollback on failure (optional, use cautiously) • Trigger: run as a follow-up job when a deploy job fails. • Action: use
lk agent rollback
to revert to previous stable version. • Require safeguards (only run on staging or in controlled contexts). Example snippet to run after a failed deploy:
Copy code
# in deploy job: set outputs or fail
# fallback job:
jobs:
  rollback-on-failure:
    if: failure()
    runs-on: ubuntu-latest
    needs: deploy
    steps:
      - name: Install LiveKit CLI
        run: curl -sSL <https://get.livekit.io/cli> | bash && echo "$HOME/.local/bin" >> $GITHUB_PATH

      - name: Rollback to previous
        env:
          LIVEKIT_API_KEY: ${{ secrets.STAGING_LIVEKIT_API_KEY }}
          LIVEKIT_API_SECRET: ${{ secrets.STAGING_LIVEKIT_API_SECRET }}
          LIVEKIT_URL: ${{ secrets.STAGING_LIVEKIT_URL }}
        run: |
          lk agent rollback --api-key "$LIVEKIT_API_KEY" --api-secret "$LIVEKIT_API_SECRET" --url "$LIVEKIT_URL"
Best practices • Use manual rollback (workflow_dispatch) for production and protect who can run it. • Log the rollback reason and version (use workflow inputs or issue/PR link). • Prefer
lk agent rollback
(uses rolling strategy and drains sessions) over redeploying older code manually. • Keep per-environment secrets separate (e.g., PROD_*, STAGING_*). • Optionally list versions before rollback:
lk agent versions --api-key ...
to confirm target version. If you want, I can: • Generate a ready-to-use rollback workflow tailored to your branch names and secret names, or • Add an approval step for production (required reviewers) in the workflow. Which would you like?
g
for the manual rollback, how to specify version?
t
Yes — use the
--version
flag with
lk agent rollback
. Quick notes and examples. 1) List available versions:
Copy code
lk agent versions --api-key "$KEY" --api-secret "$SECRET" --url "$URL"
2) Roll back to a specific version:
Copy code
lk agent rollback --version 3 --api-key "$KEY" --api-secret "$SECRET" --url "$URL"
3) GitHub Actions manual rollback (workflow_dispatch input)
Copy code
on:
  workflow_dispatch:
    inputs:
      environment:
        required: true
        type: choice
        options: [staging, production]
      version:
        required: true
        description: 'Version number to roll back to'

jobs:
  rollback:
    runs-on: ubuntu-latest
    steps:
      - name: Install LiveKit CLI
        run: curl -sSL <https://get.livekit.io/cli> | bash && echo "$HOME/.local/bin" >> $GITHUB_PATH

      - name: Rollback agent
        env:
          LIVEKIT_API_KEY: ${{ secrets[ format('{0}_LIVEKIT_API_KEY', github.event.inputs.environment | upper) ] }}
          LIVEKIT_API_SECRET: ${{ secrets[ format('{0}_LIVEKIT_API_SECRET', github.event.inputs.environment | upper) ] }}
          LIVEKIT_URL: ${{ secrets[ format('{0}_LIVEKIT_URL', github.event.inputs.environment | upper) ] }}
        run: |
          lk agent rollback --version "${{ github.event.inputs.version }}" \
            --api-key "$LIVEKIT_API_KEY" --api-secret "$LIVEKIT_API_SECRET" --url "$LIVEKIT_URL"
Best practices • Run
lk agent versions
first to pick a valid version. • Protect the workflow (approvals / limited runner access) for production rollbacks. • Log the rollback reason and version in the workflow inputs or commit message. Want me to add confirmation logic (show versions, ask to confirm) into the workflow? Sources: Agents Framework | livekit/livekit_composite | DeepWiki | Voice AI quickstart | LiveKit docs | Testing and evaluation | LiveKit docs
g
Can you write a guide on deployment and rollback. A short guide
t
Below is a short, practical guide for deploying and rolling back LiveKit agents (local CLI and CI/CD). Steps, commands, and key best practices — concise and ready to use. Deploy (one-time local create) 1. Prepare files ◦ Create local `livekit.toml`:
Copy code
[project]
     subdomain = "your-prod-subdomain"

     [agent]
     name = "my-prod-agent"
     # omit id for first-time create
• Prepare
.env
(or keep secrets in your CI secret store) with provider keys (do NOT put LiveKit credentials here). 1. Create agent (non-interactive)
Copy code
lk agent create \
     --api-key "$PROD_LIVEKIT_API_KEY" \
     --api-secret "$PROD_LIVEKIT_API_SECRET" \
     --url "$PROD_LIVEKIT_URL" \
     --secrets-file .env
• CLI writes generated
agent.id
into
livekit.toml
. Save it as
livekit.prod.toml
for CI. Deploy (CI/CD, repeatable) 1. Store per-env secrets in CI (e.g.,
PROD_LIVEKIT_API_KEY
,
PROD_LIVEKIT_API_SECRET
,
PROD_LIVEKIT_URL
, and provider keys). 2. Ensure
livekit.toml
exists in workspace (copy
livekit.prod.toml
→
livekit.toml
or generate it). 3. Run non-interactive deploy step:
Copy code
lk agent deploy \
     --api-key "$PROD_LIVEKIT_API_KEY" \
     --api-secret "$PROD_LIVEKIT_API_SECRET" \
     --url "$PROD_LIVEKIT_URL" \
     --secrets-file .env
1. Monitor: ◦
lk agent status --api-key ...
◦
lk agent logs --tail 50 --api-key ...
Rollback (manual via CLI or CI) 1. List versions to choose target:
Copy code
lk agent versions --api-key "$KEY" --api-secret "$SECRET" --url "$URL"
1. Roll back to a specific version:
Copy code
lk agent rollback --version <VERSION> --api-key "$KEY" --api-secret "$SECRET" --url "$URL"
1. If you omit
--version
,
lk agent rollback
typically reverts one step back. 2. Best practice: run rollback from a protected manual workflow (workflow_dispatch) in CI for production. CI Patterns & Tips • Avoid interactive auth in CI: do NOT run `lk cloud auth`; pass credentials via flags or env vars. • Per-environment handling: ◦ Option A (recommended hybrid): keep
livekit.staging.toml
/
livekit.prod.toml
templates and copy the appropriate one to
livekit.toml
in CI, then pass per-env secrets. ◦ Option B: skip TOML, drive everything via flags/env vars in CI. • Secrets: keep LIVEKIT_* and provider keys in CI secret store; use
--secrets
or
--secrets-file
when deploying. • Protect production: require manual trigger or approvals for prod deploys/rollbacks, restrict who can run them. • Verify after deploy/rollback:
lk agent status
and
lk agent logs
. Quick Safety Checklist before prod actions • Use prod-only secrets (
PROD_*
) and protected workflow. • Confirm the target version with
lk agent versions
. • Notify team / record reason in workflow input. If you’d like, I can generate: • A ready-to-commit GitHub Actions deploy workflow that copies
livekit.prod.toml
and deploys, and • A separate manual rollback workflow with a version input and approval gate. Which one do you want first?
g
where can I see how long it took an agent to connect to the call
t
You can see/measure agent connection time two ways — via the LiveKit Cloud analytics UI, or by instrumenting your agent and logs. 1) Dashboard (easy, no code) • Open LiveKit Cloud → your project → Participants/Analytics. • Select the agent participant; the analytics show connection timing/latency metrics (time to connect, handshake/ICE timing, etc.). 2) Agent-side logging (precise, customizable) • Record timestamps around the connect flow in your agent code (before and after the call to join/connect). • Add them to logs or diagnostic fields using
ctx.log_context_fields
(or your logger). Example pattern: ◦ start = now() ◦ await session.start(...) / await ctx.connect() ◦ connected = now() ◦ log duration = connected - start • These logs show exact connect duration per call and can be aggregated in your logging/observability system. 3) SDK events (if applicable) • If your agent uses the client SDK, time the events from WebSocket/handshake → JoinResponse → Connected to get end-to-end connection time. Where to look after instrumenting • LiveKit dashboard participant analytics for built-in metrics. • Agent logs (CLI:
lk agent logs
, or dashboard Logs tab) for your custom timing fields. If you want, I can: • Provide a one-line code snippet for timing in your agent language (Python or Node), or • Point to where the participant analytics live in the dashboard UI for your account — tell me which you prefer. Sources: Say hello to improved Cloud analytics | Job lifecycle | LiveKit docs | client-sdk-js | livekit/livekit_composite | DeepWiki
g
Dashboard (easy, no code) • Open LiveKit Cloud → your project → Participants/Analytics. • Select the agent participant; the analytics show connection timing/latency metrics (time to connect, handshake/ICE timing, etc.). be specific, where to find it
t
I can be specific — here’s the exact place to look in the LiveKit Cloud dashboard for an agent’s connection timing and related metrics. 1. Open the LiveKit Cloud dashboard and choose your project (the project that runs the agent). 2. In the left-hand sidebar, click “Participants” (or “Analytics” then “Participants” if your dashboard groups analytics). 3. Find and select the agent participant entry (search by agent name or participant ID). This opens the participant detail view. 4. In the participant detail view: ◦ Open the “Analytics” or “Metrics” tab (often shown alongside “Logs”). ◦ Look for timing metrics such as “Time to connect”, “Handshake time”, and ICE/connectivity breakdown. These are shown as per-participant latency/connection metrics in that tab. 1. If you need raw events or exact timestamps, open the “Logs” tab for that participant — logs include connection events you can use to compute durations. If your dashboard layout differs, tell me whether you see “Participants”, “Analytics”, or “Logs” in the sidebar and I’ll point to the exact tab in your UI.
g
Call overview Call ID YYYYY Started at Dec 4, 2025, 90903 PM Ended at Dec 4, 2025, 91008 PM Duration 1 min Session — Status there are calls that have a duration of 1min, Call ID XXXXX Started at Dec 4, 2025, 45629 PM Ended at Dec 4, 2025, 45714 PM Duration 45 sec Session — Status Closed PCAP FOR these two calls, it took the agent 45 sec and 1min resp to connect to the call. weve been having this issue where LiveKit agent taking >30 seconds to connect call
t
Thanks — I see the problem: agents are joining very late (30–60s) or not creating a session at all. Here’s a short troubleshooting guide with immediate checks and fixes. Immediate checks • Confirm whether a session was created for the call in the dashboard. Your Call Overview shows "Session —", which means the agent did not register for that call. • Check agent logs for those timestamps: use the dashboard Logs tab or
lk agent logs --tail 200 --api-key ...
for the agent around the call start time. • Run
lk agent status
to confirm the agent service is healthy and has ready replicas. Quick diagnostic steps 1. Enable Agent Observability (if not enabled) ◦ Turn on Agent Observability in the project settings (Data & Privacy) so sessions, traces, audio, and timestamps are recorded. 1. Inspect session trace ◦ Open the call -> Session -> Agent insights / Timeline to see exactly when the agent joined relative to call start. 1. Correlate logs to timeline ◦ From agent logs, look for connect/join events and any errors like “Room connection not established within 10 seconds” or repeated retries. 1. Check scaling / cold starts ◦ If your agent scales to zero, first request triggers a cold start. Look for long startup logs (model loading, container cold-start) right before the join time. 1. Check dispatch rules & availability ◦ Ensure dispatch rules target an available agent name and that there are ready replicas for that agent. ◦ If using explicit dispatch, verify the dispatch call happens promptly when the call arrives. Common causes & fixes • Cold starts: keep at least one warm replica or increase minimum replicas to avoid cold boot delay. • Insufficient replicas / resource limits: increase replicas or CPU/memory so agents start faster. • Long initialization: optimize agent startup (lazy-load heavy models, reduce init work before joining). • Dispatch timing: trigger agent dispatch earlier (when token generated or on inbound webhook) so agent can start joining immediately. • Network or TURN delays: ensure TURN/ICE candidates are healthy; check ICE/handshake times in participant analytics. • Worker errors: address any repeated connection/timeouts found in logs (fix retry/backoff or resource exhaustion). Short-term mitigations • Keep a warm instance (replicas >=1) for critical production agents. • Add a quick health-check endpoint and alert on slow join times. • Temporarily route calls to a fallback handler while diagnosing. If you want, I can: • Provide the exact log patterns/strings to search for (Python or Node agent). • Suggest a minimal change (e.g., set replicas=1 in livekit.toml or CI deploy) to eliminate cold starts and show the expected improvement. Which would you like me to do next? Sources: https://blog.livekit.io/streamline-troubleshooting-with-agent-observability/#/portal/signup| | Web and mobile frontends | LiveKit docs | Deploying to production | LiveKit Docs | Agents Framework | livekit/livekit_composite | DeepWiki | examples/frontdesk | livekit/livekit_composite | DeepWiki
g
could it be memory usage
t
Yes — high memory usage can cause slow agent startup and delays joining calls. Here’s how memory impacts connection time, what to check, and quick mitigations. Why memory can cause slow connects • Cold start overhead: if the agent must allocate large models or warm caches, memory pressure increases startup time. • OOM / restarts: low memory can cause crashes/restarts, so the agent restarts and only joins after a restart completes. • GC / swapping: high memory use triggers garbage collection or OS swapping which stalls the agent process. • Resource contention: other processes on the same host/container can reduce available RAM and slow initialization. What to check now • Agent logs around the call start: look for OOM, crash, restart, large GC pauses, or long model-load messages. • Deployment replica status:
lk agent status
(or Cloud dashboard) — check ready/failed replicas. • Host/container metrics: memory usage, swap, and restart counts in your cloud provider or LiveKit Cloud dashboard metrics. • Process-level memory inside the agent (if you can ssh or use metrics): peak RSS and allocations during startup. How to monitor in LiveKit Cloud / CI • Dashboard: check agent instance health, replica counts, and logs for restarts. • Logs: tail logs with
lk agent logs
and search for memory/OOM/GC messages. • If you have custom metrics/observability (Prometheus, Cloud metrics), surface memory usage and restart counts. Quick mitigations (fast to try) • Increase container memory limit or agent resources in your deployment (set higher memory in
livekit.toml
or in your deployment config). • Keep warm instances: set replicas >= 1 so you avoid cold starts. • Lazy-load heavy models: move large model loading to after join or load on demand. • Reduce memory footprint: swap to smaller models, reduce concurrency, or optimize initialization. • Add retries/backoff and faster failure detection so a failed join doesn't block long. • If OOMs occur, increase memory immediately and redeploy. Longer-term fixes • Profile memory usage during startup locally to identify hot allocations. • Add memory and startup time SLOs and alerts in CI/monitoring. • Use multiple lightweight workers instead of one heavy instance. If you’d like, tell me: • Which agent runtime (Python/Node), memory limit currently set, and whether you see OOMs in logs — I’ll give exact config lines to raise memory or a minimal code change to lazy-load models.