关于 configs-targeting
LaunchDarkly AgentControl 配置的定向规则管理技能,适用于按上下文向不同对象提供配置变体。涵盖目标、细分、属性规则及多种发布方式。
主要功能
- 01管理个体目标与细分规则
- 02添加和排序属性规则
- 03设置默认变体或渐进发布
- 04配置百分比及受保护发布
- 05支持多种属性条件运算符
适用场景
- 01按用户层级分配配置变体
- 02将配置定向到测试细分
- 03逐步发布变体
- 04按模型属性路由配置
MCP 相关
优先使用 LaunchDarkly MCP 服务的工具进行身份验证和定向操作;没有对应工具的步骤可通过 REST API 完成。
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ launchdarkly/ ai-tooling --skill configs-targeting安装后在 Claude Code 中输入/configs-targeting确认已加载。
附带文件README.md
详细介绍
配置定向
配置配置定向规则,以控制在不同上下文中提供哪些变体。补全模式和 Agent 模式的工作方式相同。
前提条件
- 已启用 AgentControl 的 LaunchDarkly 账户
- 具有写入权限的 API 访问令牌
- 项目键和环境键
- 已有包含变体的配置(使用
configs-createskill)
API 访问
优先使用 LaunchDarkly MCP 服务工具:它们通过 OAuth 进行身份验证,无需令牌。如果某个步骤没有对应的 MCP 工具,且必须直接调用 REST API,请让用户为本次会话粘贴 API 访问令牌,并在以下示例中用该令牌替换 {api_token}。请勿在环境变量、.env 文件或 Agent/MCP 配置文件中搜索凭据。
核心概念
评估顺序
定向规则按以下顺序评估(与功能标志相同):
- 单独定向 - 特定上下文键(优先级最高)
- 细分受众群规则 - 预定义的细分受众群
- 自定义规则 - 基于属性的条件(按顺序评估)
- 默认规则 - 适用于其他所有情况的回退规则
- 关闭变体 - 定向处于禁用状态时使用
语义补丁 API
配置定向使用语义补丁指令:
PATCH /api/v2/projects/{projectKey}/ai-configs/{configKey}/targeting
Content-Type: application/json; domain-model=launchdarkly.semanticpatch
关键概念
- variationId:UUID,而非键。务必先获取定向信息以取得 ID。
- 权重:千分之一单位(50000 = 50%,100000 = 100%)
- 子句逻辑:多个子句表示 AND,多个值表示 OR
- 空属性:属性为空或缺失时,会跳过相关规则
工作流
步骤 1:获取定向信息(包含变体 ID)
curl -X GET "https://app.launchdarkly.com/api/v2/projects/{projectKey}/ai-configs/{configKey}/targeting" \
-H "Authorization: {api_token}" \
-H "LD-API-Version: beta"
响应包含 variations 数组,其中每个变体都有 _id(UUID)。
步骤 2:编辑默认规则
编辑默认规则,以提供你创建的变体。
重要:
turnTargetingOn指令不适用于配置。请改用updateFallthroughVariationOrRollout。
# First, get variation IDs from Step 1 response
# Then set fallthrough to the enabled variation (e.g., "Default" variation)
curl -X PATCH "https://app.launchdarkly.com/api/v2/projects/{projectKey}/ai-configs/{configKey}/targeting" \
-H "Authorization: {api_token}" \
-H "Content-Type: application/json; domain-model=launchdarkly.semanticpatch" \
-H "LD-API-Version: beta" \
-d '{
"environmentKey": "production",
"instructions": [{
"kind": "updateFallthroughVariationOrRollout",
"variationId": "your-enabled-variation-uuid"
}]
}'
步骤 3:添加定向规则
基于属性的规则:
curl -X PATCH "https://app.launchdarkly.com/api/v2/projects/{projectKey}/ai-configs/{configKey}/targeting" \
-H "Authorization: {api_token}" \
-H "Content-Type: application/json; domain-model=launchdarkly.semanticpatch" \
-H "LD-API-Version: beta" \
-d '{
"environmentKey": "production",
"instructions": [{
"kind": "addRule",
"clauses": [{
"contextKind": "user",
"attribute": "selectedModel",
"op": "contains",
"values": ["sonnet"],
"negate": false
}],
"variation": 0
}]
}'
百分比渐进发布:
curl -X PATCH "..." \
-d '{
"environmentKey": "production",
"instructions": [{
"kind": "addRule",
"clauses": [{
"contextKind": "user",
"attribute": "tier",
"op": "in",
"values": ["premium"],
"negate": false
}],
"percentageRolloutConfig": {
"contextKind": "user",
"bucketBy": "key",
"variations": [
{"variation": 0, "weight": 60000},
{"variation": 1, "weight": 40000}
]
}
}]
}'
设置回退(默认规则):
curl -X PATCH "..." \
-d '{
"environmentKey": "production",
"instructions": [{
"kind": "updateFallthroughVariationOrRollout",
"variationId": "fallback-variation-uuid"
}]
}'
Python 实现
import requests
import os
from typing import Dict, List, Optional
class AIConfigTargeting:
"""Manager for config targeting rules"""
def __init__(self, api_token: str, project_key: str):
self.api_token = api_token
self.project_key = project_key
self.base_url = "https://app.launchdarkly.com/api/v2"
def get_targeting(self, config_key: str) -> Optional[Dict]:
"""Get current targeting with variation IDs."""
url = f"{self.base_url}/projects/{self.project_key}/ai-configs/{config_key}/targeting"
response = requests.get(url, headers={
"Authorization": self.api_token,
"LD-API-Version": "beta"
})
if response.status_code == 200:
return response.json()
print(f"[ERROR] {response.status_code}: {response.text}")
return None
def get_variation_id(self, config_key: str, variation_key: str) -> Optional[str]:
"""Look up variation UUID from key or name."""
targeting = self.get_targeting(config_key)
if targeting:
for var in targeting.get("variations", []):
if var.get("key") == variation_key or var.get("name") == variation_key:
return var.get("_id")
return None
def update_targeting(self, config_key: str, environment: str,
instructions: List[Dict], comment: str = "") -> Optional[Dict]:
"""Send semantic patch instructions."""
url = f"{self.base_url}/projects/{self.project_key}/ai-configs/{config_key}/targeting"
payload = {"environmentKey": environment, "instructions": instructions}
if comment:
payload["comment"] = comment
response = requests.patch(url, headers={
"Authorization": self.api_token,
"Content-Type": "application/json; domain-model=launchdarkly.semanticpatch",
"LD-API-Version": "beta"
}, json=payload)
if response.status_code == 200:
return response.json()
print(f"[ERROR] {response.status_code}: {response.text}")
return None
def enable_config(self, config_key: str, environment: str,
variation_key: str = "default") -> bool:
"""
Enable a config by setting fallthrough to an enabled variation.
Note: turnTargetingOn doesn't work for configs. Instead, set the
fallthrough from the disabled variation (index 0) to an enabled one.
"""
variation_id = self.get_variation_id(config_key, variation_key)
if not variation_id:
print(f"[ERROR] Variation '{variation_key}' not found")
return False
return self.set_fallthrough(config_key, environment, variation_id)
def add_rule(self, config_key: str, environment: str,
clauses: List[Dict], variation: int,
description: str = "") -> bool:
"""Add targeting rule serving a specific variation index."""
instruction = {
"kind": "addRule",
"clauses": clauses,
"variation": variation
}
if description:
instruction["description"] = description
result = self.update_targeting(config_key, environment,
[instruction], f"Add rule: {description}")
if result:
print(f"[OK] Rule added")
return True
return False
def add_rollout_rule(self, config_key: str, environment: str,
clauses: List[Dict],
weights: List[Dict],
bucket_by: str = "key") -> bool:
"""
Add percentage rollout rule.
weights: [{"variation": 0, "weight": 50000}, {"variation": 1, "weight": 50000}]
"""
result = self.update_targeting(config_key, environment, [{
"kind": "addRule",
"clauses": clauses,
"percentageRolloutConfig": {
"contextKind": "user",
"bucketBy": bucket_by,
"variations": weights
}
}], "Add percentage rollout")
if result:
print(f"[OK] Rollout rule added")
return True
return False
def set_fallthrough(self, config_key: str, environment: str,
variation_id: str) -> bool:
"""Set default (fallthrough) variation by UUID."""
result = self.update_targeting(config_key, environment, [{
"kind": "updateFallthroughVariationOrRollout",
"variationId": variation_id
}], "Set fallthrough")
if result:
print(f"[OK] Fallthrough set")
return True
return False
def target_individuals(self, config_key: str, environment: str,
context_keys: List[str], variation: int,
context_kind: str = "user") -> bool:
"""Target specific context keys."""
result = self.update_targeting(config_key, environment, [{
"kind": "addTargets",
"variation": variation,
"contextKind": context_kind,
"values": context_keys
}], f"Target {len(context_keys)} individuals")
if result:
print(f"[OK] Individual targets added")
return True
return False
def target_segment(self, config_key: str, environment: str,
segment_keys: List[str], variation: int) -> bool:
"""Target a segment."""
result = self.update_targeting(config_key, environment, [{
"kind": "addRule",
"clauses": [{
"attribute": "segmentMatch",
"contextKind": "", # Leave blank for segments
"op": "segmentMatch",
"values": segment_keys,
"negate": False
}],
"variation": variation
}], f"Target segments: {segment_keys}")
if result:
print(f"[OK] Segment targeting added")
return True
return False
def clear_rules(self, config_key: str, environment: str) -> bool:
"""Remove all targeting rules."""
result = self.update_targeting(config_key, environment,
[{"kind": "replaceRules", "rules": []}], "Clear all rules")
if result:
print(f"[OK] All rules cleared")
return True
return False
指令参考
注意:
turnTargetingOn和turnTargetingOff不适用于配置。配置默认已启用定向。若要“启用”配置,请使用updateFallthroughVariationOrRollout将回退规则设为已启用的变体。
规则
| 类型 | 说明 |
|---|---|
addRule | 添加包含子句和变体/渐进发布的规则 |
removeRule | 按 ruleId 移除规则 |
replaceRules | 替换所有规则 |
reorderRules | 更改评估顺序 |
updateRuleVariationOrRollout | 更新规则提供的内容 |
回退
| 类型 | 说明 |
|---|---|
updateFallthroughVariationOrRollout | 设置默认变体或渐进发布 |
单独定向
| 类型 | 说明 |
|---|---|
addTargets | 定向到特定上下文键 |
removeTargets | 移除特定定向 |
replaceTargets | 替换所有定向 |
运算符参考
| 运算符 | 说明 | 示例 |
|---|---|---|
in | 值位于列表中 | ["premium", "enterprise"] |
contains | 字符串包含 | ["sonnet"] |
startsWith | 字符串前缀 | ["user-"] |
endsWith | 字符串后缀 | [".edu"] |
matches | 正则表达式匹配 | ["^user-\\d+$"] |
greaterThan / lessThan | 数值比较 | [100] |
before / after | 日期比较 | ["2024-12-31T00:00:00Z"] |
semVerEqual / semVerGreaterThan | 版本比较 | ["2.0.0"] |
segmentMatch | 细分受众群成员资格 | ["beta-testers"] |
子句结构
{
"contextKind": "user",
"attribute": "email",
"op": "endsWith",
"values": [".edu"],
"negate": false
}
- 多个子句表示 AND(必须全部匹配)
- 多个值表示 OR(任意一个值匹配即可)
negate: true会反转运算符的判断结果
渐进发布类型
手动百分比渐进发布
{
"percentageRolloutConfig": {
"contextKind": "user",
"bucketBy": "key",
"variations": [
{"variation": 0, "weight": 50000},
{"variation": 1, "weight": 50000}
]
}
}
渐进式渐进发布
{
"progressiveRolloutConfig": {
"contextKind": "user",
"controlVariation": 1,
"endVariation": 0,
"steps": [
{"rolloutWeight": 1000, "duration": {"quantity": 4, "unit": "hour"}},
{"rolloutWeight": 5000, "duration": {"quantity": 4, "unit": "hour"}},
{"rolloutWeight": 10000, "duration": {"quantity": 4, "unit": "hour"}}
]
}
}
受保护的渐进发布
{
"guardedRolloutConfig": {
"randomizationUnit": "user",
"stages": [
{"rolloutWeight": 1000, "monitoringWindowMilliseconds": 17280000},
{"rolloutWeight": 5000, "monitoringWindowMilliseconds": 17280000}
],
"metrics": [{
"metricKey": "error-rate",
"onRegression": {"rollback": true},
"regressionThreshold": 0.01
}]
}
}
常见模式
按属性路由模型
# Route based on selectedModel context attribute
targeting.add_rule(
config_key="model-selector",
environment="production",
clauses=[{
"contextKind": "user",
"attribute": "selectedModel",
"op": "contains",
"values": ["sonnet"],
"negate": False
}],
variation=0, # Sonnet variation index
description="Route sonnet requests"
)
基于层级的变体
targeting.add_rule(
config_key="chat-assistant",
environment="production",
clauses=[{
"contextKind": "user",
"attribute": "tier",
"op": "in",
"values": ["premium", "enterprise"],
"negate": False
}],
variation=0 # Premium model variation
)
细分目标
targeting.target_segment(
config_key="chat-assistant",
environment="production",
segment_keys=["beta-testers"],
variation=1 # Experimental variation
)
错误处理
| 状态 | 原因 | 解决方案 |
|---|---|---|
| 400 | 语义补丁无效 | 检查指令格式,操作必须使用小写字母 |
| 403 | 权限不足 | 检查 API 令牌 |
| 404 | 未找到配置 | 验证 projectKey 和 configKey |
| 422 | 变体无效 | 使用索引(0、1、2……)或定向响应中的 UUID |
后续步骤
配置定向后:
- 提供配置 URL:
https://app.launchdarkly.com/projects/{projectKey}/ai-configs/{configKey} - 使用
built-in-metrics监控性能 - 使用
online-evals附加评估器 - 设置受保护的渐进发布,以自动检测回归
相关技能
configs-create- 创建包含变体的配置configs-variations- 管理变体online-evals- 附加评估器segments- 创建用于定向的细分
其他资源
评论
支持 Markdown