From fbd89c9360b62d25c5ea8a9367dd32f2ec980655 Mon Sep 17 00:00:00 2001 From: Kian Jones <11655409+kianjones9@users.noreply.github.com> Date: Wed, 10 Dec 2025 17:16:10 -0800 Subject: [PATCH] fix: replace all 'PRODUCTION' references with 'prod' for consistency (#6627) * fix: replace all 'PRODUCTION' references with 'prod' for consistency Problem: Codebase had 11 references to 'PRODUCTION' (uppercase) that should use 'prod' (lowercase) for consistency with the deployment workflows and environment normalization. Changes across 8 files: 1. Source files (using settings.environment): - letta/functions/function_sets/multi_agent.py - letta/services/tool_manager.py - letta/services/tool_executor/multi_agent_tool_executor.py - letta/services/helpers/agent_manager_helper.py All checks changed from: settings.environment == "PRODUCTION" To: settings.environment == "prod" 2. OTEL resource configuration: - letta/otel/resource.py - Updated _normalize_environment_tag() to handle 'prod' directly - Removed 'PRODUCTION' -> 'prod' mapping (no longer needed) - Updated device.id check from _env != "PRODUCTION" to _env != "prod" 3. Test files: - tests/managers/conftest.py - Fixture parameter changed from "PRODUCTION" to "prod" - tests/managers/test_agent_manager.py (3 occurrences) - tests/managers/test_tool_manager.py (2 occurrences) All test checks changed to use "prod" Result: Complete consistency across the codebase: - All environment checks use "prod" instead of "PRODUCTION" - Normalization function simplified (no special case for PRODUCTION) - Tests use correct "prod" value - Matches deployment workflow configuration from PR #6626 This completes the environment naming standardization effort. * fix: update settings.py environment description to use 'prod' instead of 'PRODUCTION' The field description still referenced PRODUCTION as an example value. Updated to use lowercase 'prod' for consistency with actual usage. Before: "Application environment (PRODUCTION, DEV, CANARY, etc. - normalized to lowercase for OTEL tags)" After: "Application environment (prod, dev, canary, etc. - lowercase values used for OTEL tags)" --- letta/functions/function_sets/multi_agent.py | 2 +- letta/otel/resource.py | 22 +++++++++---------- .../services/helpers/agent_manager_helper.py | 2 +- .../multi_agent_tool_executor.py | 2 +- letta/services/tool_manager.py | 2 +- letta/settings.py | 2 +- tests/managers/conftest.py | 2 +- tests/managers/test_agent_manager.py | 6 ++--- tests/managers/test_tool_manager.py | 4 ++-- 9 files changed, 22 insertions(+), 22 deletions(-) diff --git a/letta/functions/function_sets/multi_agent.py b/letta/functions/function_sets/multi_agent.py index 2bfdff03..100bf737 100644 --- a/letta/functions/function_sets/multi_agent.py +++ b/letta/functions/function_sets/multi_agent.py @@ -134,7 +134,7 @@ def send_message_to_agent_async(self: "Agent", message: str, other_agent_id: str Returns: str: A confirmation message indicating the message was successfully sent. """ - if settings.environment == "PRODUCTION": + if settings.environment == "prod": raise RuntimeError("This tool is not allowed to be run on Letta Cloud.") message = ( diff --git a/letta/otel/resource.py b/letta/otel/resource.py index 3932ca18..bcc8cd7e 100644 --- a/letta/otel/resource.py +++ b/letta/otel/resource.py @@ -14,27 +14,27 @@ def _normalize_environment_tag(env: str) -> str: """ Normalize environment value for OTEL deployment.environment tag. Maps internal environment values to abbreviated lowercase tags for Datadog. - + Examples: - PRODUCTION -> prod DEV -> dev - CANARY -> canary - LOCAL-TEST -> local-test + DEVELOPMENT -> dev + STAGING -> dev + prod -> prod (already normalized) + canary -> canary + local-test -> local-test """ if not env: return "unknown" - + env_upper = env.upper() - + # Map known values to abbreviated forms - if env_upper == "PRODUCTION": - return "prod" - elif env_upper == "DEV" or env_upper == "DEVELOPMENT": + if env_upper == "DEV" or env_upper == "DEVELOPMENT": return "dev" elif env_upper == "STAGING": return "dev" # Staging maps to dev else: - # For other values (canary, local-test, etc.), use lowercase as-is + # For other values (prod, canary, local-test, etc.), use lowercase as-is return env.lower() @@ -50,7 +50,7 @@ def get_resource(service_name: str) -> Resource: if _env: resource_dict["deployment.environment"] = _normalize_environment_tag(_env) # Only add device.id in non-production environments (for debugging) - if _env != "PRODUCTION": + if _env != "prod": resource_dict["device.id"] = uuid.getnode() # MAC address as unique device identifier, _resources[(service_name, _env)] = Resource.create(resource_dict) return _resources[(service_name, _env)] diff --git a/letta/services/helpers/agent_manager_helper.py b/letta/services/helpers/agent_manager_helper.py index 845d93ce..63fb7590 100644 --- a/letta/services/helpers/agent_manager_helper.py +++ b/letta/services/helpers/agent_manager_helper.py @@ -1298,7 +1298,7 @@ def calculate_base_tools(is_v2: bool) -> Set[str]: def calculate_multi_agent_tools() -> Set[str]: """Calculate multi-agent tools, excluding local-only tools in production environment.""" - if settings.environment == "PRODUCTION": + if settings.environment == "prod": return set(MULTI_AGENT_TOOLS) - set(LOCAL_ONLY_MULTI_AGENT_TOOLS) else: return set(MULTI_AGENT_TOOLS) diff --git a/letta/services/tool_executor/multi_agent_tool_executor.py b/letta/services/tool_executor/multi_agent_tool_executor.py index 2e6a3815..901e2022 100644 --- a/letta/services/tool_executor/multi_agent_tool_executor.py +++ b/letta/services/tool_executor/multi_agent_tool_executor.py @@ -127,7 +127,7 @@ class LettaMultiAgentToolExecutor(ToolExecutor): } async def send_message_to_agent_async(self, agent_state: AgentState, actor: User, message: str, other_agent_id: str) -> str: - if settings.environment == "PRODUCTION": + if settings.environment == "prod": raise RuntimeError("This tool is not allowed to be run on Letta Cloud.") # 1) Build the prefixed system‐message diff --git a/letta/services/tool_manager.py b/letta/services/tool_manager.py index 246f493b..de3ff428 100644 --- a/letta/services/tool_manager.py +++ b/letta/services/tool_manager.py @@ -638,7 +638,7 @@ class ToolManager: # TODO: This requires a deeper rethink about how we keep all our internal tools up-to-date if not after and upsert_base_tools: existing_tool_names = {tool.name for tool in tools} - base_tool_names = LETTA_TOOL_SET - set(LOCAL_ONLY_MULTI_AGENT_TOOLS) if settings.environment == "PRODUCTION" else LETTA_TOOL_SET + base_tool_names = LETTA_TOOL_SET - set(LOCAL_ONLY_MULTI_AGENT_TOOLS) if settings.environment == "prod" else LETTA_TOOL_SET missing_base_tools = base_tool_names - existing_tool_names # If any base tools are missing, upsert all base tools diff --git a/letta/settings.py b/letta/settings.py index ce096c8b..fbafb26d 100644 --- a/letta/settings.py +++ b/letta/settings.py @@ -235,7 +235,7 @@ class Settings(BaseSettings): cors_origins: Optional[list] = cors_origins environment: Optional[str] = Field( default=None, - description="Application environment (PRODUCTION, DEV, CANARY, etc. - normalized to lowercase for OTEL tags)", + description="Application environment (prod, dev, canary, etc. - lowercase values used for OTEL tags)", ) # SSE Streaming keepalive settings diff --git a/tests/managers/conftest.py b/tests/managers/conftest.py index 15e3f564..6e56cdcd 100644 --- a/tests/managers/conftest.py +++ b/tests/managers/conftest.py @@ -773,7 +773,7 @@ def dummy_successful_response() -> BetaMessageBatchIndividualResponse: # ====================================================================================================================== -@pytest.fixture(params=[None, "PRODUCTION"]) +@pytest.fixture(params=[None, "prod"]) def set_letta_environment(request, monkeypatch): """Parametrized fixture to test with different environment settings.""" from letta.settings import settings diff --git a/tests/managers/test_agent_manager.py b/tests/managers/test_agent_manager.py index 2584459a..733d7e76 100644 --- a/tests/managers/test_agent_manager.py +++ b/tests/managers/test_agent_manager.py @@ -256,7 +256,7 @@ async def test_calculate_multi_agent_tools(set_letta_environment): """Test that calculate_multi_agent_tools excludes local-only tools in production.""" result = calculate_multi_agent_tools() - if settings.environment == "PRODUCTION": + if settings.environment == "prod": # Production environment should exclude local-only tools expected_tools = set(MULTI_AGENT_TOOLS) - set(LOCAL_ONLY_MULTI_AGENT_TOOLS) assert result == expected_tools, "Production should exclude local-only multi-agent tools" @@ -283,7 +283,7 @@ async def test_upsert_base_tools_excludes_local_only_in_production(server: SyncS tools = await server.tool_manager.upsert_base_tools_async(actor=default_user) tool_names = {tool.name for tool in tools} - if settings.environment == "PRODUCTION": + if settings.environment == "prod": # Production environment should exclude local-only multi-agent tools for local_only_tool in LOCAL_ONLY_MULTI_AGENT_TOOLS: assert local_only_tool not in tool_names, f"Local-only tool '{local_only_tool}' should not be upserted in production" @@ -306,7 +306,7 @@ async def test_upsert_multi_agent_tools_only(server: SyncServer, default_user, s tools = await server.tool_manager.upsert_base_tools_async(actor=default_user, allowed_types={ToolType.LETTA_MULTI_AGENT_CORE}) tool_names = {tool.name for tool in tools} - if settings.environment == "PRODUCTION": + if settings.environment == "prod": # Should only have non-local multi-agent tools expected_tools = set(MULTI_AGENT_TOOLS) - set(LOCAL_ONLY_MULTI_AGENT_TOOLS) assert tool_names == expected_tools, "Production multi-agent upsert should exclude local-only tools" diff --git a/tests/managers/test_tool_manager.py b/tests/managers/test_tool_manager.py index 81e0c428..9861029e 100644 --- a/tests/managers/test_tool_manager.py +++ b/tests/managers/test_tool_manager.py @@ -1278,7 +1278,7 @@ async def test_upsert_base_tools(server: SyncServer, default_user): tools = await server.tool_manager.upsert_base_tools_async(actor=default_user) # Calculate expected tools accounting for production filtering - if settings.environment == "PRODUCTION": + if settings.environment == "prod": expected_tool_names = sorted(LETTA_TOOL_SET - set(LOCAL_ONLY_MULTI_AGENT_TOOLS)) else: expected_tool_names = sorted(LETTA_TOOL_SET) @@ -1330,7 +1330,7 @@ async def test_upsert_filtered_base_tools(server: SyncServer, default_user, tool tool_names = sorted([t.name for t in tools]) # Adjust expected names for multi-agent tools in production - if tool_type == ToolType.LETTA_MULTI_AGENT_CORE and settings.environment == "PRODUCTION": + if tool_type == ToolType.LETTA_MULTI_AGENT_CORE and settings.environment == "prod": expected_sorted = sorted(set(expected_names) - set(LOCAL_ONLY_MULTI_AGENT_TOOLS)) else: expected_sorted = sorted(expected_names)