| name | aiconfig-context-advanced |
| description | Build safe, scalable contexts for LaunchDarkly AI Configs with cardinality controls, multi-context patterns, and agent graph attributes. |
| compatibility | Python 3.9+, launchdarkly-server-sdk |
| metadata | {"author":"launchdarkly","version":"0.2.0"} |
Advanced Context Patterns for AI Config
Advanced patterns for context enrichment, multi-context scenarios, performance optimization, and comprehensive attribute reference for partner integrations.
Prerequisites
- Understanding of basic context patterns (see
aiconfig-context-basic)
- LaunchDarkly SDK key (retrieve via API:
GET /api/v2/projects/{projectKey}/environments)
- Python 3.9+ (required by SDK)
- launchdarkly-server-sdk and launchdarkly-server-sdk-ai packages
Note: The AI SDK (launchdarkly-server-sdk-ai) is currently in alpha and under active development. APIs and behavior may change.
Important Constraints
- Attribute names cannot contain dots (
.) but nested objects are supported
- Reference nested values in templates using:
{{ ldctx.user.name }}
- The
key and kind attributes are always sent and cannot be private
- Private attributes are still sent to LaunchDarkly but not stored in the dashboard
Context Patterns by Use Case
1. Experimentation & Testing
Build contexts optimized for A/B testing and experimentation:
from ldclient import Context
import hashlib
from datetime import datetime
def build_experiment_context(user_id: str, user_data: dict):
"""Build context with experiment-relevant attributes"""
builder = Context.builder(user_id)
builder.set("tier", user_data.get("subscription_tier", "free"))
builder.set("accountAgeDays", calculate_age_days(user_data.get("created_at")))
builder.set("usageLevel", categorize_usage(user_data.get("api_calls_monthly", 0)))
builder.set("experimentCohort", user_data.get("cohort", "default"))
bucket = int(hashlib.md5(user_id.encode()).hexdigest()[:8], 16) % 100
builder.set("experimentBucket", bucket)
week_number = datetime.now().isocalendar()[1]
builder.set("cohortWeek", week_number)
return builder.build()
def categorize_usage(api_calls: int) -> str:
"""Categorize usage levels for segmentation"""
if api_calls > 100000:
return "power_user"
elif api_calls > 10000:
return "active"
elif api_calls > 1000:
return "regular"
else:
return "light"
Why these attributes matter:
tier - Segment results by subscription level
accountAgeDays - Compare new vs established users
usageLevel - Analyze power users separately
experimentBucket - Stable random assignment
cohortWeek - Time-based analysis
→ Set up targeting: See aiconfig-targeting
→ Analyze results: See aiconfig-ai-metrics
2. Targeted Deployments & Canary Testing
Context patterns for targeted deployments and canary testing:
def build_deployment_context(user_id: str, user_data: dict, org_data: dict = None):
"""Context for targeted deployments and canary testing"""
builder = Context.builder(user_id)
builder.set("betaTester", user_data.get("opted_into_beta", False))
from datetime import datetime
signup_date = datetime.fromisoformat(user_data.get("signup_date", "2024-01-01"))
builder.set("earlyAdopter", signup_date < datetime(2023, 1, 1))
if org_data:
builder.set("orgRiskTolerance", org_data.get("risk_profile", "conservative"))
builder.set("orgSize", org_data.get("employee_count", 0))
builder.set("region", user_data.get("region", "us-east"))
builder.set("dataCenter", map_to_datacenter(user_data.get("region")))
builder.set("performanceTier", calculate_performance_tier(user_data))
return builder.build()
def calculate_performance_tier(user_data: dict) -> str:
"""Determine performance tier for capacity planning"""
if user_data.get("plan") == "enterprise" and user_data.get("sla") == "premium":
return "high_priority"
elif user_data.get("plan") in ["business", "enterprise"]:
return "standard"
else:
return "best_effort"
→ Configure targeting: See aiconfig-targeting
→ Set up percentage splits: Use targeting rules for A/B testing
3. Multi-Context for B2B Applications
Sophisticated multi-context patterns for enterprise applications:
def build_b2b_contexts(user_data: dict, org_data: dict, workspace_data: dict = None):
"""Build comprehensive B2B multi-context"""
user_context = Context.builder(user_data["id"]).kind("user")
user_context.set("role", user_data.get("role"))
user_context.set("department", user_data.get("department"))
user_context.set("permissions", user_data.get("permission_level"))
user_context.set("lastActive", user_data.get("last_activity"))
org_context = Context.builder(org_data["id"]).kind("organization")
org_context.set("tier", org_data.get("plan"))
org_context.set("industry", org_data.get("industry"))
org_context.set("size", categorize_org_size(org_data.get("employee_count")))
org_context.set("mrr", org_data.get("monthly_revenue"))
org_context.set("features", org_data.get("enabled_features", []))
multi_builder = Context.multi_builder()
multi_builder.add(user_context.build())
multi_builder.add(org_context.build())
if workspace_data:
workspace_context = Context.builder(workspace_data["id"]).kind("workspace")
workspace_context.set("name", workspace_data.get("name"))
workspace_context.set("type", workspace_data.get("type"))
workspace_context.set("memberCount", workspace_data.get("member_count"))
multi_builder.add(workspace_context.build())
return multi_builder.build()
def categorize_org_size(employee_count: int) -> str:
"""Categorize organization size"""
if employee_count > 1000:
return "enterprise"
elif employee_count > 100:
return "mid_market"
elif employee_count > 10:
return "small_business"
else:
return "startup"
→ Target by organization: See aiconfig-targeting for multi-context rules
→ B2B experiments: Consider organization-level randomization
4. Context Enrichment Pipeline
Pattern for enriching contexts with external data:
class ContextEnrichmentPipeline:
"""Pipeline for enriching contexts with external data"""
def __init__(self):
self.enrichers = []
def add_enricher(self, enricher):
"""Add an enrichment step"""
self.enrichers.append(enricher)
return self
def enrich(self, base_context_data: dict) -> Context:
"""Build enriched context"""
user_id = base_context_data["user_id"]
builder = Context.builder(user_id)
enriched_data = base_context_data.copy()
for enricher in self.enrichers:
enriched_data = enricher(enriched_data)
for key, value in enriched_data.items():
if key != "user_id" and value is not None:
builder.set(key, value)
return builder.build()
def enrich_from_crm(data: dict) -> dict:
"""Enrich with CRM data"""
data["accountValue"] = get_account_value(data.get("user_id"))
data["industrySegment"] = get_industry_segment(data.get("company"))
return data
def enrich_from_usage_metrics(data: dict) -> dict:
"""Enrich with usage analytics"""
data["dailyActiveUse"] = get_daily_active_use(data.get("user_id"))
data["featureAdoption"] = calculate_feature_adoption(data.get("user_id"))
return data
def enrich_with_computed_fields(data: dict) -> dict:
"""Add computed attributes"""
if data.get("accountValue") and data.get("dailyActiveUse"):
data["engagementScore"] = calculate_engagement_score(
data["accountValue"],
data["dailyActiveUse"]
)
return data
pipeline = ContextEnrichmentPipeline()
pipeline.add_enricher(enrich_from_crm) \
.add_enricher(enrich_from_usage_metrics) \
.add_enricher(enrich_with_computed_fields)
context = pipeline.enrich({"user_id": "user-123", "company": "TechCorp"})
5. JWT Claims Integration
Advanced JWT integration with custom claims:
def context_from_jwt_with_custom_claims(jwt_claims: dict, claim_mappings: dict = None):
"""Build context from JWT with custom claim mappings"""
user_id = jwt_claims.get("sub") or jwt_claims.get("user_id")
if not user_id:
raise ValueError("No user identifier in JWT")
builder = Context.builder(user_id)
default_mappings = {
"email": "email",
"name": "name",
"given_name": "firstName",
"family_name": "lastName",
"preferred_username": "username",
"locale": "locale",
"zoneinfo": "timezone",
"org_id": "organizationId",
"team_id": "teamId",
"subscription_tier": "tier",
"permissions": "permissions"
}
if claim_mappings:
default_mappings.update(claim_mappings)
for claim_key, context_key in default_mappings.items():
if claim_key in jwt_claims:
builder.set(context_key, jwt_claims[claim_key])
if "custom" in jwt_claims:
for key, value in jwt_claims["custom"].items():
if isinstance(value, dict):
for nested_key, nested_value in value.items():
builder.set(f"{key}_{nested_key}", nested_value)
else:
builder.set(key, value)
builder.set("jwtIssuer", jwt_claims.get("iss"))
builder.set("jwtAudience", jwt_claims.get("aud"))
return builder.build()
6. Performance Optimization
Patterns for high-volume context operations:
from functools import lru_cache
from typing import Dict, Optional
import time
class OptimizedContextBuilder:
"""Optimized context building for high-volume scenarios"""
def __init__(self, cache_size: int = 1000):
self.cache_size = cache_size
self._compute_cache = {}
self._cache_timestamps = {}
self._cache_ttl = 300
@lru_cache(maxsize=1000)
def _get_cached_computation(self, key: str, value: any) -> any:
"""Cache expensive computations"""
return expensive_computation(key, value)
def build_context_optimized(self, user_id: str, raw_data: dict) -> Context:
"""Build context with caching and optimization"""
builder = Context.builder(user_id)
attributes = {}
import json
import hashlib
cache_key = f"{user_id}:{hashlib.md5(json.dumps(raw_data, sort_keys=True).encode()).hexdigest()}"
now = time.time()
if cache_key in self._compute_cache:
cached_time = self._cache_timestamps.get(cache_key, 0)
if now - cached_time < self._cache_ttl:
attributes.update(self._compute_cache[cache_key])
else:
computed = self._compute_attributes(raw_data)
self._compute_cache[cache_key] = computed
self._cache_timestamps[cache_key] = now
attributes.update(computed)
else:
computed = self._compute_attributes(raw_data)
self._compute_cache[cache_key] = computed
self._cache_timestamps[cache_key] = now
attributes.update(computed)
for key, value in raw_data.items():
if key not in attributes and value is not None:
attributes[key] = value
for key, value in attributes.items():
builder.set(key, value)
if len(self._compute_cache) > self.cache_size:
self._clean_cache()
return builder.build()
def _compute_attributes(self, raw_data: dict) -> dict:
"""Compute expensive derived attributes"""
computed = {}
if "created_at" in raw_data:
computed["accountAge"] = calculate_account_age(raw_data["created_at"])
computed["isNewUser"] = computed["accountAge"] < 30
if "total_spend" in raw_data:
computed["valueSegment"] = calculate_value_segment(raw_data["total_spend"])
return computed
def _clean_cache(self):
"""Clean expired cache entries"""
now = time.time()
expired_keys = [
key for key, timestamp in self._cache_timestamps.items()
if now - timestamp > self._cache_ttl
]
for key in expired_keys:
del self._compute_cache[key]
del self._cache_timestamps[key]
optimizer = OptimizedContextBuilder()
for user_data in large_user_dataset:
context = optimizer.build_context_optimized(
user_data["id"],
user_data
)
Cardinality Budget & Safety Rules
CRITICAL: Prevent "oops we created 10M contexts" incidents with these rules:
Never Use as Context Keys
These should NEVER be context keys (use as private attributes instead):
- ❌ Request IDs, trace IDs, conversation IDs
- ❌ Session IDs (use stable user/employee ID as key)
- ❌ Timestamps or dates
- ❌ Raw numeric values (revenue, scores, counts)
- ❌ Dynamic lists or arrays
Always Bucket Numeric Fields
Transform continuous values into ranges:
builder.set("monthlyRevenue", 15234.56)
def bucket_revenue(revenue: float) -> str:
if revenue < 1000: return "0-1k"
elif revenue < 10000: return "1k-10k"
elif revenue < 100000: return "10k-100k"
else: return "100k+"
builder.set("revenueRange", bucket_revenue(15234.56))
Handle Lists Safely
For arrays/lists, use one of these patterns:
builder.set("enabledFeatures", ["feat1", "feat2", "feat3"])
feature_profile = get_feature_profile(features)
builder.set("featureProfile", feature_profile)
builder.set("hasAdvancedReporting", "reporting" in features)
builder.set("hasAPIAccess", "api" in features)
Context Key Guidelines
| Context Kind | Recommended Key Pattern | Cardinality Target |
|---|
| user | Employee/user ID | < 100K |
| organization | Company ID | < 10K |
| agentGraph | Graph name (not version) | < 100 |
| orchestrator | Type + region | < 20 |
| toolchain | Predefined profile | < 10 |
| session | Use user ID + session as attribute | Same as user |
Geographic Context Patterns
Advanced geographic targeting:
def build_geographic_context_advanced(user_id: str, ip_data: dict, preferences: dict = None):
"""Build context with advanced geographic attributes"""
builder = Context.builder(user_id)
builder.set("country", ip_data.get("country_code"))
builder.set("region", ip_data.get("region"))
builder.set("city", ip_data.get("city"))
builder.set("timezone", ip_data.get("timezone"))
builder.set("continent", map_to_continent(ip_data.get("country_code")))
builder.set("marketRegion", map_to_market_region(ip_data.get("country_code")))
builder.set("dataPrivacyRegion", get_privacy_region(ip_data.get("country_code")))
if preferences:
builder.set("preferredLanguage", preferences.get("language"))
builder.set("preferredCurrency", preferences.get("currency"))
else:
builder.set("inferredLanguage", infer_language(ip_data.get("country_code")))
builder.set("inferredCurrency", infer_currency(ip_data.get("country_code")))
builder.set("gdprApplies", is_gdpr_country(ip_data.get("country_code")))
builder.set("ccpaApplies", ip_data.get("region") == "CA" and ip_data.get("country_code") == "US")
return builder.build()
def get_privacy_region(country_code: str) -> str:
"""Determine data privacy region"""
eu_countries = ["DE", "FR", "IT", "ES", "NL", "BE", "PL", "SE", "DK", "FI"]
if country_code in eu_countries:
return "eu"
elif country_code == "US":
return "us"
elif country_code in ["JP", "KR"]:
return "apac_strict"
else:
return "standard"
Agent Graph Context Patterns
Build contexts for AI agent graphs and workflows:
def build_agent_graph_context(
graph_id: str,
node_id: str,
graph_data: dict,
node_data: dict
) -> dict:
"""Build context for agent graph execution"""
graph_context = Context.builder(graph_id).kind("agentGraph")
graph_context.set("graphVersion", graph_data.get("version", "1.0"))
graph_context.set("graphStage", graph_data.get("stage", "prod"))
graph_context.set("graphOwnerTeam", graph_data.get("owner_team"))
graph_context.set("graphPolicyProfile", graph_data.get("policy", "standard"))
graph_context.set("graphDomain", graph_data.get("domain"))
node_context = Context.builder(node_id).kind("agentNode")
node_context.set("nodeType", node_data.get("type"))
node_context.set("nodeDepth", node_data.get("depth", 0))
node_context.set("parentNodeId", node_data.get("parent_id"))
node_context.set("nodeCriticality", node_data.get("criticality", "medium"))
return {
"graph": graph_context.build(),
"node": node_context.build()
}
contexts = build_agent_graph_context(
graph_id="claims-triage-v3",
node_id="node-retriever-01",
graph_data={"version": "3.2", "stage": "canary"},
node_data={"type": "retriever", "depth": 1}
)
Orchestrator & Runtime Context
Capture orchestration engine and runtime characteristics:
def build_orchestrator_context(
orchestrator_type: str,
runtime_data: dict
) -> Context:
"""Build context for orchestration runtime"""
orchestrator_id = f"{orchestrator_type}-{runtime_data.get('region', 'default')}"
builder = Context.builder(orchestrator_id).kind("orchestrator")
builder.set("orchestratorType", orchestrator_type)
builder.set("orchestratorVersion", runtime_data.get("version"))
builder.set("executionMode", runtime_data.get("mode", "async"))
builder.set("retryPolicy", runtime_data.get("retry_policy", "standard"))
builder.set("parallelismEnabled", runtime_data.get("parallel", False))
builder.set("checkpointing", runtime_data.get("checkpointing", True))
builder.set("stateBackend", runtime_data.get("state_backend", "memory"))
builder.set("timeoutBudgetMs", runtime_data.get("timeout_ms", 30000))
builder.set("maxRetries", runtime_data.get("max_retries", 3))
return builder.build()
MCP & Toolchain Context
Model Context Protocol (MCP) is an open protocol that enables AI systems to interact with external tools and data sources through natural language. In an agent ecosystem, you may have:
- Multiple MCP servers providing different capabilities (database access, APIs, file systems)
- LaunchDarkly's own MCP server for feature flag management
- Third-party MCP servers from various vendors
Important: These context patterns apply to ANY MCP servers attached to your agent system, not just LaunchDarkly's MCP server. Since agents can have many MCP servers, we collapse them into targetable attributes to avoid cardinality explosion.
Handle MCP servers and tool capabilities safely:
def build_mcp_context(
toolchain_profile: str,
mcp_servers: list,
tool_policy: str = "standard"
) -> Context:
"""
Build context for MCP servers and toolchain.
IMPORTANT: Use a predefined profile as key (not a hash of servers)
to maintain low cardinality. Store server details as private attributes.
"""
builder = Context.builder(toolchain_profile).kind("toolchain")
builder.set("mcpEnabled", len(mcp_servers) > 0)
builder.set("mcpServerCount", categorize_count(len(mcp_servers)))
builder.set("toolPolicy", tool_policy)
max_risk = "low"
write_capable = False
third_party_present = False
server_ids = []
for server in mcp_servers:
server_ids.append(server.get("id"))
risk = server.get("riskTier", "low")
if risk_priority(risk) > risk_priority(max_risk):
max_risk = risk
if server.get("permissions", "read") in ["write", "admin"]:
write_capable = True
if server.get("vendor") not in ["internal", "first_party"]:
third_party_present = True
builder.set("maxRiskTier", max_risk)
builder.set("writeCapable", write_capable)
builder.set("thirdPartyPresent", third_party_present)
builder.set("mcpServerList", server_ids)
builder.private("mcpServerList")
return builder.build()
def categorize_count(count: int) -> str:
"""Bucket counts to avoid high cardinality"""
if count == 0:
return "none"
elif count <= 2:
return "1-2"
elif count <= 5:
return "3-5"
else:
return "6+"
def risk_priority(risk: str) -> int:
"""Convert risk tier to priority for comparison"""
return {"low": 1, "medium": 2, "high": 3, "critical": 4}.get(risk, 0)
Builder Context (Insurance Employees)
Context for insurance employees building and operating agents:
def build_builder_context(
employee_id: str,
employee_data: dict,
compliance_data: dict = None
) -> Context:
"""Build context for insurance employee builders"""
builder = Context.builder(employee_id).kind("builder")
builder.set("builderRole", employee_data.get("role"))
builder.set("department", employee_data.get("department"))
builder.set("seniority", employee_data.get("seniority", "mid"))
builder.set("trainingStatus", employee_data.get("training", "trained"))
builder.set("permissionTier", employee_data.get("permissions", "editor"))
builder.set("environmentAccess", employee_data.get("env_access", ["dev"]))
if compliance_data:
builder.set("licenseStates", compliance_data.get("licensed_states", []))
builder.set("certificationLevel", compliance_data.get("certification"))
builder.set("complianceTraining", compliance_data.get("compliance_complete"))
builder.set("canPublishGraphs", employee_data.get("can_publish", False))
builder.set("canModifyTools", employee_data.get("can_modify_tools", False))
builder.set("canAccessPii", employee_data.get("pii_access", False))
return builder.build()
Session & Execution Context
Handle high-cardinality session data carefully:
def build_session_context(
user_id: str,
execution_data: dict,
anonymous: bool = False
) -> Context:
"""
Build session/execution context.
IMPORTANT: Use a stable key (user/employee ID), NOT session ID.
Session IDs should be attributes, not keys, to avoid cardinality explosion.
"""
builder = Context.builder(user_id).kind("session")
if anonymous:
builder.anonymous(True)
builder.set("invocationReason", execution_data.get("reason"))
builder.set("attemptNumber", min(execution_data.get("attempt", 1), 3))
builder.set("isReplay", execution_data.get("is_replay", False))
builder.set("debugMode", execution_data.get("debug", False))
if execution_data.get("session_id"):
builder.set("sessionId", execution_data.get("session_id"))
builder.private("sessionId")
if execution_data.get("conversation_id"):
builder.set("conversationId", execution_data.get("conversation_id"))
builder.private("conversationId")
if execution_data.get("request_id"):
builder.set("requestId", execution_data.get("request_id"))
builder.private("requestId")
if execution_data.get("trace_id"):
builder.set("traceId", execution_data.get("trace_id"))
builder.private("traceId")
return builder.build()
Complete Multi-Context Example
Bringing it all together for agent graph execution:
def build_complete_agent_context(
user_id: str,
org_id: str,
graph_id: str,
node_id: str,
mcp_servers: list,
session_id: str
) -> Context:
"""Build complete multi-context for agent evaluation"""
multi_builder = Context.multi_builder()
user_context = Context.builder(user_id).kind("user")
user_context.set("role", "claims_adjuster")
user_context.set("department", "claims")
user_context.set("tier", "professional")
multi_builder.add(user_context.build())
org_context = Context.builder(org_id).kind("organization")
org_context.set("industry", "insurance")
org_context.set("complianceTier", "high")
org_context.set("dataResidency", "us-west")
multi_builder.add(org_context.build())
graph_context = Context.builder(graph_id).kind("agentGraph")
graph_context.set("graphVersion", "2.1")
graph_context.set("nodeId", node_id)
graph_context.set("nodeType", "retriever")
multi_builder.add(graph_context.build())
orch_context = Context.builder("orch-prod-west").kind("orchestrator")
orch_context.set("orchestratorType", "langgraph")
orch_context.set("executionMode", "async")
multi_builder.add(orch_context.build())
toolchain_profile = "claims-standard"
toolchain_context = build_mcp_context(toolchain_profile, mcp_servers, "strict")
multi_builder.add(toolchain_context)
session_context = Context.builder(user_id).kind("session")
session_context.set("sessionId", session_id)
session_context.private("sessionId")
session_context.set("invocationReason", "user_action")
multi_builder.add(session_context.build())
return multi_builder.build()
context = build_complete_agent_context(
user_id="emp-123",
org_id="carrier-456",
graph_id="claims-triage",
node_id="node-01",
mcp_servers=[
{"id": "mcp-claims-db", "vendor": "internal", "riskTier": "medium"},
{"id": "mcp-docs", "vendor": "internal", "riskTier": "low"}
],
session_id="sess-789"
)
config = ai_client.completion_config(
"claims-assistant",
context,
default_config
)
Context Factory Patterns
Reusable context factories for common scenarios:
class ContextFactory:
"""Factory for creating standardized contexts"""
@staticmethod
def create_retail_customer(customer_data: dict) -> Context:
"""Create context for retail/e-commerce"""
builder = Context.builder(customer_data["id"])
builder.set("customerType", customer_data.get("type", "regular"))
builder.set("lifetimeValue", customer_data.get("ltv", 0))
builder.set("purchaseFrequency", customer_data.get("purchase_frequency"))
builder.set("cartAbandonment", customer_data.get("cart_abandonment_rate"))
builder.set("preferredCategories", customer_data.get("categories", []))
builder.set("loyaltyTier", customer_data.get("loyalty_tier", "bronze"))
builder.set("lastPurchaseDays", customer_data.get("days_since_purchase"))
builder.set("avgOrderValue", customer_data.get("aov"))
builder.set("returnRate", customer_data.get("return_rate"))
return builder.build()
@staticmethod
def create_saas_user(user_data: dict, account_data: dict) -> Context:
"""Create context for SaaS applications"""
builder = Context.builder(user_data["id"])
builder.set("role", user_data.get("role"))
builder.set("onboardingCompleted", user_data.get("onboarding_complete"))
builder.set("lastLogin", user_data.get("last_login"))
builder.set("accountId", account_data.get("id"))
builder.set("plan", account_data.get("plan"))
builder.set("mrr", account_data.get("monthly_revenue"))
builder.set("churnRisk", account_data.get("churn_risk_score"))
builder.set("healthScore", account_data.get("health_score"))
builder.set("contractEndDate", account_data.get("contract_end"))
builder.set("activeUsers", account_data.get("active_user_count"))
builder.set("storageUsed", account_data.get("storage_gb"))
builder.set("apiCalls", account_data.get("api_calls_month"))
return builder.build()
retail_context = ContextFactory.create_retail_customer({
"id": "customer-123",
"type": "vip",
"ltv": 5000,
"loyalty_tier": "platinum"
})
saas_context = ContextFactory.create_saas_user(
{"id": "user-456", "role": "admin"},
{"id": "account-789", "plan": "enterprise", "mrr": 10000}
)
Comprehensive Attribute Reference
📚 Comprehensive Attribute Reference (Partner Integration Guide)
This exhaustive list is provided for partners building integrations. Most implementations only need 5-10 attributes.
Quick Jump:
User Attributes
| Attribute | Type | Common Use |
|---|
email | string | User identification |
name | string | Personalization in prompts |
firstName | string | Personalization |
lastName | string | Personalization |
username | string | Display purposes |
tier | string | Model selection, feature gating |
role | string | Role-based prompts |
department | string | Department-specific AI behavior |
cohort | string | User grouping and segmentation |
accountAge | number | Experience-based targeting |
language | string | Localization |
timezone | string | Time-aware responses |
Behavioral Attributes
| Attribute | Type | Common Use |
|---|
usageLevel | string | Resource allocation |
lastActivity | string/number | Engagement targeting |
sessionCount | number | Experience level detection |
featureUsage | array | Feature-specific targeting |
apiCalls | number | Rate limiting, tier enforcement |
dailyActiveUse | boolean | Engagement metrics |
churnRisk | number | Retention targeting |
engagementScore | number | User value assessment |
Business Attributes
| Attribute | Type | Common Use |
|---|
companyName | string | B2B personalization |
companySize | string | Enterprise features |
industry | string | Industry-specific prompts |
plan | string | Feature gating |
mrr | number | Value-based targeting |
contractValue | number | Priority support |
seats | number | License enforcement |
accountId | string | Account-level targeting |
Technical Attributes
| Attribute | Type | Common Use |
|---|
deviceType | string | Device-specific UI |
browser | string | Compatibility checks |
os | string | Platform-specific features |
appVersion | string | Version-specific behavior |
sdkVersion | string | SDK compatibility |
ip | string | Geographic inference |
Geographic Attributes
| Attribute | Type | Common Use |
|---|
country | string | Localization, compliance |
region | string | Regional features |
city | string | Local personalization |
marketRegion | string | Market-specific features |
dataCenter | string | Latency optimization |
gdprApplies | boolean | Privacy compliance |
Temporal Attributes
| Attribute | Type | Common Use |
|---|
signupDate | string/number | Cohort analysis |
lastLoginDate | string/number | Engagement tracking |
trialEndDate | string/number | Conversion targeting |
renewalDate | string/number | Retention campaigns |
hourOfDay | number | Time-based behavior |
dayOfWeek | string | Usage patterns |
Experimental Attributes
| Attribute | Type | Common Use |
|---|
experimentBucket | number | Random assignment |
testGroup | string | A/B test assignment |
cohortWeek | number | Time-based cohorts |
betaTester | boolean | Early access |
featureFlags | object | Feature toggles |
Agent Graph Attributes
Context for agent workflows and graph execution:
| Attribute | Type | Required | Common Use | Notes |
|---|
key* | string | Yes | Graph identifier | Unique ID like "claims-triage-v3" |
graphVersion | string | | Version control | Semantic version (1.0, 2.1) |
graphStage | string | | Deployment stage | draft/test/canary/prod |
graphOwnerTeam | string | | Ownership tracking | Team responsible for graph |
graphPolicyProfile | string | | Risk management | standard/restricted/elevated |
graphDomain | string | | Business domain | claims/underwriting/billing |
nodeId | string | | Current node | For node-level targeting |
nodeType | string | | Node capability | planner/retriever/executor/validator |
nodeDepth | number | | Graph traversal depth | 0-based depth in execution |
parentNodeId | string | | Node hierarchy | Parent in execution tree |
nodeCriticality | string | | Impact assessment | low/medium/high/critical |
graphComplexity | string | | Resource planning | simple/moderate/complex |
graphTags | array | | Categorization | ["financial", "pii", "regulated"] |
Orchestrator Attributes
Runtime engine and execution environment:
| Attribute | Type | Required | Common Use | Notes |
|---|
key* | string | Yes | Orchestrator ID | Like "langgraph-prod-west" |
orchestratorType | string | | Engine type | langgraph/temporal/custom/stepfunctions |
orchestratorVersion | string | | Version tracking | Engine version number |
executionMode | string | | Processing mode | sync/async/streaming/batch |
retryPolicy | string | | Error handling | none/standard/aggressive/custom |
parallelismEnabled | boolean | | Concurrency | Whether parallel execution allowed |
checkpointing | boolean | | State management | Whether state is persisted |
stateBackend | string | | Storage type | memory/redis/dynamodb/postgres |
timeoutBudgetMs | number | | Time constraints | Max execution time in ms |
maxRetries | number | | Resilience | Maximum retry attempts |
region | string | | Geographic location | Deployment region |
environment | string | | Deployment env | dev/staging/prod |
resourceTier | string | | Resource allocation | basic/standard/premium |
MCP/Toolchain Attributes
Tool capabilities and boundaries (collapsed from server list):
| Attribute | Type | Required | Common Use | Notes |
|---|
key* | string | Yes | Toolchain Profile | Predefined profile (e.g., "claims-standard") |
mcpEnabled | boolean | | MCP presence | Whether any MCP servers attached |
mcpServerCount | string | | Server quantity | none/1-2/3-5/6+ (bucketed) |
toolPolicy | string | | Access policy | standard/strict/permissive |
maxRiskTier | string | | Highest risk | low/medium/high/critical |
writeCapable | boolean | | Write permissions | Can modify external systems |
thirdPartyPresent | boolean | | Vendor risk | Non-internal servers present |
toolCategories | array | | Capability types | ["database", "api", "filesystem"] |
dataSourceTypes | array | | Data access | ["sql", "nosql", "files", "apis"] |
complianceLevel | string | | Regulatory | none/basic/sox/hipaa/pci |
auditingEnabled | boolean | | Tracking | Whether actions are logged |
mcpServerList | array | Private | Debug info | Actual server IDs (high cardinality) |
Builder Attributes
Insurance employee building agents:
| Attribute | Type | Required | Common Use | Notes |
|---|
key* | string | Yes | Employee ID | Unique identifier |
builderRole | string | | Job function | underwriter/claims_adjuster/actuarial |
department | string | | Org structure | claims/underwriting/risk/operations |
seniority | string | | Experience level | junior/mid/senior/principal |
trainingStatus | string | | Qualification | untrained/in_progress/trained/certified |
permissionTier | string | | Access level | viewer/editor/publisher/admin |
environmentAccess | array | | Allowed envs | ["dev", "test", "staging"] |
licenseStates | array | | Geographic auth | ["CA", "TX", "NY"] for US |
certificationLevel | string | | Professional cert | none/basic/advanced/expert |
complianceTraining | boolean | | Regulatory | Completed required training |
canPublishGraphs | boolean | | Publishing rights | Can push to production |
canModifyTools | boolean | | Tool management | Can add/remove MCP servers |
canAccessPii | boolean | | Data access | PII handling permission |
teamSize | number | | Team scope | Number of direct reports |
yearsExperience | number | | Tenure | Years in role/industry |
Session Attributes
Execution and request context:
| Attribute | Type | Required | Common Use | Notes |
|---|
key* | string | Yes | User/Employee ID | Use stable ID, NOT session ID |
sessionId | string | Private | Session tracking | High cardinality, mark private |
invocationReason | string | | Trigger type | user/scheduled/retry/webhook |
attemptNumber | number | | Retry count | Capped at 3 to avoid cardinality |
isReplay | boolean | | Execution type | Whether replaying previous |
debugMode | boolean | | Logging level | Enhanced logging enabled |
priority | string | | Queue priority | low/normal/high/critical |
workflowId | string | Private | Workflow tracking | High cardinality ID |
conversationId | string | Private | Chat thread | High cardinality ID |
requestId | string | Private | Request tracking | Unique per request |
traceId | string | Private | Distributed trace | Cross-service correlation |
parentSpanId | string | Private | Trace hierarchy | Parent in trace tree |
batchId | string | | Batch processing | Group of related requests |
userAction | string | | User intent | click/submit/refresh/navigate |
Using Attributes Effectively
For Targeting (aiconfig-targeting):
- Use
tier, plan, role, region for rule-based targeting
- Combine multiple attributes for complex rules
- Use numeric attributes with comparison operators
- Target by
graphStage for canary deployments
- Use
maxRiskTier to limit high-risk operations
- Filter by
builderRole for role-based access
For Segmentation (aiconfig-segments):
- Use
cohort, testGroup for grouping users
- Include
experimentBucket for random assignment
- Track
signupDate, accountAge for cohort analysis
- Group by
orchestratorType for runtime comparisons
- Segment by
graphDomain for business unit analysis
For Personalization (aiconfig-variations):
- Use in messages:
{{ ldctx.name }}, {{ ldctx.company }}
- Combine attributes:
{{ ldctx.firstName }} from {{ ldctx.companyName }}
- Conditional content based on attributes
- Adjust prompts by
builderRole and department
- Modify instructions based on
complianceLevel
For Metrics (aiconfig-ai-metrics):
- Segment by
tier, plan, usageLevel
- Track performance by
region, deviceType
- Analyze by
cohort, experimentBucket
- Compare
orchestratorType performance
- Monitor costs by
graphComplexity
- Track errors by
nodeType and nodeCriticality
For Experiments (A/B Testing):
- Randomize on stable IDs (
user.key, organization.key)
- Use
graphVersion for version testing
- Compare
orchestratorType variations
- Test different
retryPolicy settings
- Experiment with
parallelismEnabled toggles
For Risk Management:
- Restrict by
maxRiskTier and writeCapable
- Gate features by
certificationLevel
- Limit
canAccessPii for sensitive data
- Control
canPublishGraphs for production access
- Monitor
thirdPartyPresent for vendor risk
Private Attributes (High Cardinality):
- Mark session IDs, request IDs, trace IDs as private
- Keep
mcpServerList private to avoid cardinality explosion
- Private attributes can still be used for targeting but won't appear in UI
- Use bucketed/categorized versions for public attributes
Best Practices
-
Context Enrichment Strategy
- Enrich progressively, not all at once
- Cache expensive computations
- Use async enrichment for external data
-
Multi-Context Guidelines
- Keep context kinds focused (user, org, workspace)
- Don't duplicate attributes across contexts
- Use for true multi-entity scenarios
-
Performance Optimization
- Minimize attribute count
- Use caching for repeated builds
- Batch operations when possible
-
Data Privacy
- Never use PII as context keys
- Hash sensitive data
- Respect regional privacy laws
Related Skills
Prerequisites
aiconfig-context-basic - Master basic contexts first
aiconfig-sdk - SDK context implementation
aiconfig-targeting - Targeting with contexts
Framework Integration
aiconfig-frameworks - Use contexts with orchestrators
aiconfig-experiments - Multi-context experiments
aiconfig-segments - Create segments from contexts
Monitoring
aiconfig-ai-metrics - Track by context attributes
aiconfig-custom-metrics - Custom metrics by context
aiconfig-online-evals - Quality by context
References