Feature Flags
Feature flags allow you to control agent behavior, prompt versions, and experimental features at runtime without deploying new code. They are defined in services/backend/src/config/feature_flags.py.
Overview
The feature flag system uses a FeatureFlag enum with a simple boolean check function. Flags can be toggled through environment variables, the admin API, or the dashboard UI.
Using Feature Flags
from src.config.feature_flags import FeatureFlag, is_feature_enabled
# Check if a flag is enabled
if is_feature_enabled(FeatureFlag.USE_V3_STYLE):
prompt = load_prompt("style_v3")
else:
prompt = load_prompt("style_v2")Available Flags
Feature flags are defined as an enum in the configuration module:
class FeatureFlag(str, Enum):
USE_V3_STYLE = "use_v3_style"
ENABLE_TRY_ON = "enable_try_on"
ENABLE_SHOPPING_AGENT = "enable_shopping_agent"
USE_DEEPSEEK_CRITIC = "use_deepseek_critic"
ENABLE_MEMORY_V2 = "enable_memory_v2"
ENABLE_COST_ALERTS = "enable_cost_alerts"
ENABLE_APPROVAL_QUEUES = "enable_approval_queues"
AB_TEST_PERSONALIZATION = "ab_test_personalization"Controlling Agent Versions
Feature flags are commonly used to switch between agent prompt versions during rollouts:
from src.config.feature_flags import FeatureFlag, is_feature_enabled
class StyleAgent(BaseAgent):
async def execute(self, input_data: dict):
if is_feature_enabled(FeatureFlag.USE_V3_STYLE):
system_prompt = STYLE_V3_PROMPT
model = "gpt-5.1"
else:
system_prompt = STYLE_V2_PROMPT
model = "gpt-4o"
response = await self.llm.generate(
model=model,
system=system_prompt,
messages=[{"role": "user", "content": input_data["description"]}],
)
return responseA/B Testing with Feature Flags
Feature flags integrate with the personalization A/B testing system to run controlled experiments:
from src.config.feature_flags import FeatureFlag, is_feature_enabled
from src.services.personalization_ab_testing import get_user_variant
async def get_recommendations(user_id: str, input_data: dict):
if is_feature_enabled(FeatureFlag.AB_TEST_PERSONALIZATION):
variant = get_user_variant(user_id, "personalization_v2")
if variant == "treatment":
return await personalized_recommendations_v2(user_id, input_data)
else:
return await personalized_recommendations_v1(user_id, input_data)
return await personalized_recommendations_v1(user_id, input_data)Users are consistently assigned to the same variant for the duration of the experiment based on a hash of their user ID and the experiment name.
Gradual Rollout Patterns
Percentage-Based Rollout
Roll out a new feature to an increasing percentage of users:
from src.config.feature_flags import is_feature_enabled_for_user
async def analyze(user_id: str, input_data: dict):
# Enable for 25% of users based on user_id hash
if is_feature_enabled_for_user(
FeatureFlag.ENABLE_MEMORY_V2,
user_id,
rollout_percent=25,
):
memory = MemoryServiceV2()
else:
memory = MemoryServiceV1()
return await run_pipeline(input_data, memory=memory)Organization-Based Rollout
Enable features for specific organizations (B2B):
from src.config.feature_flags import is_feature_enabled_for_org
async def run_workflow(org_id: str, workflow_id: str):
if is_feature_enabled_for_org(
FeatureFlag.ENABLE_APPROVAL_QUEUES,
org_id,
):
# Run with approval gates
return await execute_with_approvals(workflow_id)
else:
return await execute_workflow(workflow_id)Configuration Sources
Feature flags are resolved from the following sources in priority order:
- Admin API / Dashboard UI — Highest priority. Set through the B2B admin endpoints.
- Environment variables — Set in the
.envfile. Use the flag name in uppercase with aFF_prefix:FF_USE_V3_STYLE=true FF_ENABLE_TRY_ON=false - Default values — Defined in
feature_flags.py. Used when no override is set.
Viewing Flag Status
Check the current state of all feature flags through the B2B admin API:
GET /api/v1/admin/feature-flags{
"flags": [
{ "name": "use_v3_style", "enabled": true, "source": "env" },
{ "name": "enable_try_on", "enabled": false, "source": "default" },
{ "name": "enable_analysis_agent", "enabled": true, "source": "admin" }
]
}