Skip to content

Commit 0a24841

Browse files
committed
fix(cli): apply .env after the built-in local defaults
Loading .env before env_vars meant env.update(env_vars) clobbered any overlapping key, so a custom REDIS_URL or TEMPORAL_ADDRESS in .env had no effect. Apply .env after the defaults, below the manifest env block and the shell, and keep ENVIRONMENT pinned to development; add a regression test. Claude-Session: https://claude.ai/code/session_01HCVKnA7LeJZ44nxZz1uzF3
1 parent 02cc9f0 commit 0a24841

2 files changed

Lines changed: 31 additions & 10 deletions

File tree

‎src/agentex/lib/cli/handlers/run_handlers.py‎

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -413,16 +413,6 @@ def create_agent_environment(manifest: AgentManifest, manifest_dir: Path | None
413413
# Start with current environment
414414
env = dict(os.environ)
415415

416-
# Local development: load the .env next to manifest.yaml into BOTH the ACP and
417-
# worker processes (the docs promise this). Variables already set in the shell
418-
# win, matching python-dotenv's default. Without this, a value in .env only
419-
# reaches a process if some import happens to call load_dotenv() first.
420-
if manifest_dir is not None:
421-
env_file = Path(manifest_dir) / ".env"
422-
if env_file.is_file():
423-
for key, value in dotenv_values(env_file).items():
424-
if value is not None and key not in env:
425-
env[key] = value
426416

427417
agent_config = manifest.agent
428418

@@ -469,6 +459,23 @@ def create_agent_environment(manifest: AgentManifest, manifest_dir: Path | None
469459

470460
env.update(env_vars)
471461

462+
# Local development: load the .env next to manifest.yaml into BOTH the ACP and
463+
# worker processes (the docs promise this). Precedence, highest first: the
464+
# manifest's env block, variables already set in the shell, then .env, then
465+
# the built-in local defaults above (so .env can point at a custom Redis or
466+
# Temporal). ENVIRONMENT stays "development": that is what makes this a
467+
# local run. Without this block a value in .env only reaches a process if
468+
# some import happens to call load_dotenv() first.
469+
if manifest_dir is not None:
470+
env_file = Path(manifest_dir) / ".env"
471+
if env_file.is_file():
472+
manifest_env = agent_config.env or {}
473+
for key, value in dotenv_values(env_file).items():
474+
if value is None or key == "ENVIRONMENT":
475+
continue
476+
if key in os.environ or key in manifest_env:
477+
continue
478+
env[key] = value
472479
return env
473480

474481

‎tests/lib/cli/test_run_handlers_env.py‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,17 @@ def test_missing_dotenv_and_no_manifest_dir_are_fine(project_dir: Path, monkeypa
6565

6666
assert "FROM_DOTENV" not in create_agent_environment(manifest, manifest_dir=project_dir)
6767
assert "FROM_DOTENV" not in create_agent_environment(manifest)
68+
69+
70+
def test_dotenv_overrides_builtin_local_defaults_but_not_environment(project_dir: Path, monkeypatch: pytest.MonkeyPatch):
71+
""".env may point local runs at a custom Redis/Temporal; ENVIRONMENT stays development."""
72+
(project_dir / ".env").write_text("REDIS_URL=redis://custom:6380\nTEMPORAL_ADDRESS=temporal.internal:7233\nENVIRONMENT=production\n")
73+
for key in ("REDIS_URL", "TEMPORAL_ADDRESS", "ENVIRONMENT"):
74+
monkeypatch.delenv(key, raising=False)
75+
manifest = load_agent_manifest(file_path=str(project_dir / "manifest.yaml"))
76+
77+
env = create_agent_environment(manifest, manifest_dir=project_dir)
78+
79+
assert env["REDIS_URL"] == "redis://custom:6380"
80+
assert env["TEMPORAL_ADDRESS"] == "temporal.internal:7233"
81+
assert env["ENVIRONMENT"] == "development"

0 commit comments

Comments
 (0)