Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
import os

# Load the project .env first (the ACP process does the same), then map the
# LiteLLM proxy key: the worker process runs the model calls, so copy
# LITELLM_API_KEY to OPENAI_API_KEY before importing project code (some
# frameworks build their OpenAI client at import time). Without this the
# worker raises "Missing credentials".
from dotenv import load_dotenv

load_dotenv() # the project .env, before any project code runs

_litellm_key = os.environ.get("LITELLM_API_KEY")
if _litellm_key and not os.environ.get("OPENAI_API_KEY"):
os.environ["OPENAI_API_KEY"] = _litellm_key

import asyncio

from agentex.lib.core.temporal.activities import get_all_activities
Expand All @@ -15,6 +30,7 @@ from agentex.lib.core.temporal.plugins.openai_agents.models.temporal_streaming_m
from project.workflow import {{ workflow_class }}
from project.activities import get_weather


environment_variables = EnvironmentVariables.refresh()

logger = make_logger(__name__)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,22 @@ class and registers every model/tool activity the TemporalAgent needs —
so we don't have to enumerate activities by hand here.
"""

import os

# Load the project .env first (the ACP process does the same), then map the
# LiteLLM proxy key: the worker process runs the model calls, so copy
# LITELLM_API_KEY to OPENAI_API_KEY before importing project code (some
# frameworks build their OpenAI client at import time). Without this the
# worker raises "Missing credentials".
from dotenv import load_dotenv

load_dotenv() # the project .env, before any project code runs

_litellm_key = os.environ.get("LITELLM_API_KEY")
if _litellm_key and not os.environ.get("OPENAI_API_KEY"):
os.environ["OPENAI_API_KEY"] = _litellm_key


import asyncio

from project.workflow import {{ workflow_class }}
Expand All @@ -19,6 +35,7 @@ from agentex.lib.environment_variables import EnvironmentVariables
from agentex.lib.core.temporal.activities import get_all_activities
from agentex.lib.core.temporal.workers.worker import AgentexWorker


environment_variables = EnvironmentVariables.refresh()
logger = make_logger(__name__)

Expand Down
16 changes: 16 additions & 0 deletions tests/lib/cli/test_init_templates.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,3 +137,19 @@ def test_requirements_include_langgraph_plugin_and_temporal(self, tmp_path: Path
requirements = (project_dir / "requirements.txt").read_text()
assert "temporalio[langgraph]>=1.27.0" in requirements
assert "langchain-openai" in requirements


@pytest.mark.parametrize("template_type", [TemplateType.TEMPORAL_OPENAI_AGENTS, TemplateType.TEMPORAL_PYDANTIC_AI])
def test_temporal_worker_maps_litellm_key(tmp_path: Path, template_type: TemplateType):
"""Temporal workers that call OpenAI-compatible models must see OPENAI_API_KEY.

These templates' .env.example only set LITELLM_API_KEY. The model call runs
in the worker process, started separately from the ACP process, so the
worker entrypoint needs the LITELLM_API_KEY -> OPENAI_API_KEY mapping or it
fails with "Missing credentials".
"""
project_dir = _render_project(tmp_path, template_type)
src = (project_dir / "project" / "run_worker.py").read_text()
assert 'os.environ["OPENAI_API_KEY"] = _litellm_key' in src, f"{template_type.value} run_worker.py lacks the LITELLM_API_KEY mapping"
assert "load_dotenv()" in src, f"{template_type.value} run_worker.py does not load the project .env"
assert src.index("load_dotenv()") < src.index('_litellm_key = os.environ.get("LITELLM_API_KEY")'), "mapping must run after load_dotenv()"