I develop LiveKit Agent with Python SDK. Our docke...
# ask-ai
b
I develop LiveKit Agent with Python SDK. Our dockerfile runs download-files command while building image and it fails because it references undefined environment variables. They are defined when running, but I do not want to define them on building phase. How can I avoid this error and run download-files command successfully.
✅ 1
t
Thanks for reaching out, toshi. I'm an AI assistant and I'm here to help. Give me a moment while I research this topic.
Thanks — I understand you’re running
download-files
during your Docker build and it fails because your code reads runtime environment variables that aren’t set at build time. I’ll walk you through the cause and a safe fix so
download-files
can run during image build without needing runtime secrets. Acknowledging the issue • You’re seeing errors during the build step that runs
download-files
because some code is trying to read environment variables (like
LIVEKIT_API_KEY
,
LIVEKIT_API_SECRET
,
LIVEKIT_URL
) at import/module load time. • The
download-files
command itself only downloads model files and does not need LiveKit credentials. What’s causing the failure • Your agent code (for example in
agent.py
) likely accesses
os.getenv()
or calls
load_dotenv()
at the top level or during module import. That runs during the build step and fails because those env vars aren’t defined there. • Any initialization logic that uses runtime-only environment values must be deferred until the actual runtime entrypoint. How to fix it (recommended) 1. Move all environment-variable access into the runtime-entrypoint or functions that run only at runtime. ◦ Do not call
os.getenv()
or
load_dotenv()
at module scope. ◦ Call them inside your
entrypoint
/
main()
async function or wherever you establish a LiveKit connection. Example pattern (conceptual):
Copy code
# agent.py (top-level imports only)
from livekit.agents import AgentSession
from livekit.plugins import silero
from livekit.plugins.turn_detector.multilingual import MultilingualModel

# no os.getenv or load_dotenv here

async def entrypoint(ctx):
    import os
    livekit_url = os.getenv("LIVEKIT_URL")    # safe here
    api_key = os.getenv("LIVEKIT_API_KEY")
    api_secret = os.getenv("LIVEKIT_API_SECRET")

    session = AgentSession(
        vad=silero.VAD.load(),
        turn_detection=MultilingualModel(),
        # other runtime config
    )
    await session.start(...)
1. If you use
load_dotenv()
, call it inside the runtime entrypoint (not at import time). 2. Keep model/plugin initialization that is safe for build-time (e.g., loading plugin classes or calling their
load()
methods if they only fetch local model files) at module level only if those actions don’t require runtime secrets. Otherwise defer them too. Dockerfile notes (example) • Install dependencies first, copy sources, then run `download-files`: 1. COPY dependency manifest and install deps 2. COPY source code 3. RUN your agent CLI command to download files Example sequence:
Copy code
COPY pyproject.toml .
RUN uv sync --locked

COPY src/ src/
RUN uv run src/agent.py download-files
This will succeed provided your modules no longer access runtime env vars at import time. Extra tips • Use
.dockerignore
to keep secrets like
.env
out of the image. • If you must have conditional code paths (build vs runtime), you can detect when running
download-files
by checking sys.argv in the entry module and avoid importing runtime-only code during that command. If you’d like, share a short snippet of your
agent.py
(the top-level imports and any top-level
os.getenv()
or
load_dotenv()
calls). I can point out the exact lines to move so
download-files
will run cleanly during build. Sources: Silero VAD plugin | LiveKit Documentation | Server startup modes | LiveKit Documentation | Build a healthcare intake assistant with an Anam avatar | LiveKit
b
Creating this agent server wrapper and avoid loading environment variables when it receives download-files command. Does this idea sound good?
Copy code
import sys
from livekit import agents


if __name__ == "__main__":
    if len(sys.argv) >= 2 and sys.argv[1] == "download-files":
        agents.cli.run_app(agents.AgentServer())
    else:
        from agent_server import server

        agents.cli.run_app(server)
t
Thanks — this is a good direction. Your wrapper correctly avoids importing the main server (and any runtime env-var access) when the
download-files
command is used. A few small suggestions will make it safer and clearer. Why your approach works • Checking
sys.argv
before importing
agent_server
prevents module-level code in
agent_server
from running during the build step. • That lets
download-files
run without requiring runtime environment variables. Suggestions to strengthen it • Be explicit about only performing the minimal imports needed for the download command so nothing else triggers environment access. • Prefer checking the command name robustly (in case other CLI scaffolding is added). • Add a short comment so future readers know this guard is there to allow build-time downloads without secrets. Suggested revision with comments:
Copy code
import sys
from livekit import agents

# Run minimal LiveKit AgentServer for the CLI download step
if __name__ == "__main__":
    # If invoked as `python -m yourmodule download-files` or similar
    if len(sys.argv) >= 2 and sys.argv[1] == "download-files":
        # Only import/run the small CLI path that performs model downloads.
        agents.cli.run_app(agents.AgentServer())
    else:
        # Import the full server implementation (which may read runtime env vars)
        from agent_server import server
        agents.cli.run_app(server)
Extra defensive tips • If
agent_server
has any module-level side effects, move those into a function (e.g.,
create_server()
), and import only that function where needed. This reduces risk if someone later adds env access at module scope. • Consider checking for other CLI subcommands you might add in the future; centralizing command dispatch in one place helps maintain behavior. • If you use
load_dotenv()
anywhere, ensure it’s only called inside the runtime path (not at module import). If you want, paste the top of your
agent_server.py
(the imports and any top-level code). I can point out anything that would still run during build and suggest how to move it into runtime-only code. , with interactive elements