diff --git a/skills.json b/skills.json index 6bf3b2f..16a8f37 100644 --- a/skills.json +++ b/skills.json @@ -2,10 +2,11 @@ "skills": [ { "name": "aiconfig-create", - "description": "Guide for setting up AI configuration in your application. Helps you choose between agent vs completion mode, select the right approach for your stack, and create AI Configs that make sense for your use case.", + "description": "Create and configure AI Configs in LaunchDarkly. Helps you choose between agent vs completion mode, create the config, add variations with models and prompts, and verify the setup.", "path": "skills/ai-configs/aiconfig-create", - "version": "0.2.0", - "compatibility": "Requires LaunchDarkly API access token with ai-configs:write permission or LaunchDarkly MCP server." + "version": "1.0.0-experimental", + "license": "Apache-2.0", + "compatibility": "Requires the remotely hosted LaunchDarkly MCP server" }, { "name": "aiconfig-online-evals", @@ -30,24 +31,27 @@ }, { "name": "aiconfig-tools", - "description": "Guide for giving your AI agents capabilities through tools. Helps you identify what your AI needs to do, create tool definitions, and attach them in a way that makes sense for your framework.", + "description": "Give your AI agents capabilities through tools (function calling). Helps you identify what your AI needs to do, create tool definitions, and attach them to AI Config variations.", "path": "skills/ai-configs/aiconfig-tools", - "version": "0.2.0", - "compatibility": "Requires LaunchDarkly API token with ai-tool permissions." + "version": "1.0.0-experimental", + "license": "Apache-2.0", + "compatibility": "Requires the remotely hosted LaunchDarkly MCP server" }, { "name": "aiconfig-update", "description": "Update, archive, and delete LaunchDarkly AI Configs and their variations. Use when you need to modify config properties, change model parameters, update instructions or messages, archive unused configs, or permanently remove them.", "path": "skills/ai-configs/aiconfig-update", - "version": "0.2.0", - "compatibility": "Requires LaunchDarkly project with AI Configs enabled and API access token." + "version": "1.0.0-experimental", + "license": "Apache-2.0", + "compatibility": "Requires the remotely hosted LaunchDarkly MCP server" }, { "name": "aiconfig-variations", - "description": "Guide for experimenting with AI configurations. Helps you test different models, prompts, and parameters to find what works best through systematic experimentation.", + "description": "Experiment with AI configurations by creating and managing variations. Helps you test different models, prompts, and parameters to find what works best through systematic experimentation.", "path": "skills/ai-configs/aiconfig-variations", - "version": "0.2.0", - "compatibility": "Requires LaunchDarkly API access token with ai-configs:write permission." + "version": "1.0.0-experimental", + "license": "Apache-2.0", + "compatibility": "Requires the remotely hosted LaunchDarkly MCP server" }, { "name": "launchdarkly-flag-cleanup", diff --git a/skills/ai-configs/aiconfig-create/README.md b/skills/ai-configs/aiconfig-create/README.md index 29ca8d6..0a46092 100644 --- a/skills/ai-configs/aiconfig-create/README.md +++ b/skills/ai-configs/aiconfig-create/README.md @@ -6,9 +6,9 @@ An Agent Skill for creating AI Configs in LaunchDarkly. Guides choosing agent vs This skill teaches agents how to: - Understand the use case and choose agent vs completion mode -- Create AI Configs via the two-step API process (config then variations) -- Set up model configuration with the correct modelConfigKey -- Verify creation via API fetch +- Create AI Configs using MCP tools (`setup-ai-config` for one-step, or `create-ai-config` + `create-ai-config-variation` for more control) +- Set up model configuration with the correct `modelConfigKey` format +- Verify creation via the tool response or `get-ai-config` ## Installation (Local) @@ -16,8 +16,7 @@ Copy `skills/ai-configs/aiconfig-create/` into your agent client's skills path. ## Prerequisites -- LaunchDarkly API access token with `ai-configs:write` permission or MCP server -- LaunchDarkly project (use `aiconfig-projects` skill if needed) +This skill requires the remotely hosted LaunchDarkly MCP server to be configured in your environment. ## Usage @@ -34,16 +33,14 @@ Set up an AI config for content generation using Claude ``` aiconfig-create/ ├── SKILL.md -├── README.md -└── references/ - └── api-quickstart.md +└── README.md ``` ## Related -- [AI Config Projects](../aiconfig-projects/) — Create projects first -- [AI Config Tools](../aiconfig-tools/) — Add tools after creating config -- [AI Config Variations](../aiconfig-variations/) — Add more variations for experimentation +- [AI Config Projects](../aiconfig-projects/): Create projects first +- [AI Config Tools](../aiconfig-tools/): Add tools after creating config +- [AI Config Variations](../aiconfig-variations/): Add more variations for experimentation - [LaunchDarkly AI Configs Docs](https://docs.launchdarkly.com/home/ai-configs) ## License diff --git a/skills/ai-configs/aiconfig-create/SKILL.md b/skills/ai-configs/aiconfig-create/SKILL.md index 845f491..87e1abb 100644 --- a/skills/ai-configs/aiconfig-create/SKILL.md +++ b/skills/ai-configs/aiconfig-create/SKILL.md @@ -1,114 +1,164 @@ --- name: aiconfig-create -description: Guide for setting up AI configuration in your application. Helps you choose between agent vs completion mode, select the right approach for your stack, and create AI Configs that make sense for your use case. -compatibility: Requires LaunchDarkly API access token with ai-configs:write permission or LaunchDarkly MCP server. +description: "Create and configure AI Configs in LaunchDarkly. Helps you choose between agent vs completion mode, create the config, add variations with models and prompts, and verify the setup." +license: Apache-2.0 +compatibility: Requires the remotely hosted LaunchDarkly MCP server metadata: author: launchdarkly - version: "0.2.0" + version: "1.0.0-experimental" --- # Create AI Config -You're using a skill that will guide you through setting up AI configuration in your application. Your job is to explore the codebase to understand the use case and stack, choose agent vs completion mode, create the config following the right path, and verify it works. +You're using a skill that will guide you through creating an AI Config in LaunchDarkly. Your job is to understand the use case, choose the right mode, create the config and its variations, and verify everything is set up correctly. ## Prerequisites -- LaunchDarkly API access token with `ai-configs:write` permission or MCP server -- LaunchDarkly project (use `aiconfig-projects` skill if needed) +This skill requires the remotely hosted LaunchDarkly MCP server to be configured in your environment. -## Core Principles +**Primary MCP tool:** +- `setup-ai-config` -- create a config with its first variation in one step (recommended) -1. **Understand the Use Case First**: Know what you're building before choosing a mode -2. **Choose the Right Mode**: Agent mode vs completion mode depends on your framework and needs -3. **Two-Step Creation**: Create config first, then create variations (model, prompts, parameters) -4. **Verify via API**: The agent fetches the config to confirm it was created correctly +**Alternative MCP tools (for more control):** +- `create-ai-config` -- create just the config shell (key, name, mode) +- `create-ai-config-variation` -- add a variation with model, prompts, and parameters +- `get-ai-config` -- verify the config was created correctly -## API Key Detection +**Optional MCP tools (enhance workflow):** +- `list-ai-configs` -- browse existing configs to understand naming conventions +- `create-project` -- create a project if one doesn't exist yet -1. **Check environment variables** — `LAUNCHDARKLY_API_KEY`, `LAUNCHDARKLY_API_TOKEN`, `LD_API_KEY` -2. **Check MCP config** — Claude: `~/.claude/config.json` → `mcpServers.launchdarkly.env.LAUNCHDARKLY_API_KEY` -3. **Prompt user** — Only if detection fails +## Important: Bias Towards Action + +When the user provides enough context (use case, model, mode), proceed through the entire workflow without stopping to ask for details you can infer. Use reasonable defaults for unspecified fields: `default` for variation key, the use case as the basis for instructions/messages, kebab-case for config keys. Complete all steps (create + verify) in one pass. ## Workflow -### Step 1: Understand Your Use Case +### Step 1: Understand the Use Case Before creating, identify what you're building: - **What framework?** LangGraph, LangChain, CrewAI, OpenAI SDK, Anthropic SDK, custom -- **What does the AI need?** Just text, or tools/function calling? -- **Agent or completion?** See decision below +- **What does the AI need?** Just text generation, or tools/function calling? +- **Agent or completion?** See the decision matrix below ### Step 2: Choose Agent vs Completion Mode -| Your Need | Mode | -|-----------|------| -| Persistent instructions across interactions | **Agent** | -| LangGraph, CrewAI, AutoGen | **Agent** | -| Direct OpenAI/Anthropic API calls | **Completion** | -| Full control of message structure | **Completion** | -| One-off text generation | **Completion** | +This choice is about **input schema and framework compatibility**, not execution behavior. Agent mode returns an `instructions` string; completion mode returns a `messages` array. Both provide provider abstraction, A/B testing, and metrics tracking. -**Both modes support tools.** Agent mode: single `instructions` string. Completion mode: full `messages` array. +| Your Need | Mode | Why | +|-----------|------|-----| +| LangGraph, CrewAI, AutoGen frameworks | **Agent** | Frameworks expect goal/instruction input | +| Persistent instructions across interactions | **Agent** | Single instructions string, SDK method: `aiclient.agent()` | +| Direct OpenAI/Anthropic API calls | **Completion** | Messages array maps directly to provider APIs | +| Full control of message structure | **Completion** | System/user/assistant role-based messages | +| One-off text generation | **Completion** | Standard chat format | +| Need online evaluations (LLM-as-judge) | **Completion** | Online evals are only available in completion mode | -### Step 3: Create the Config +**Both modes support tools.** Not all models support agent mode -- check model compatibility if using agent mode. If unsure, start with completion mode (it's the API default and more flexible). -Follow [API Quick Start](references/api-quickstart.md) for curl examples: +### Step 3: Create the Config (Recommended: One Step) -1. **Create config** — `POST /projects/{projectKey}/ai-configs` (key, name, mode) -2. **Create variation** — `POST /projects/{projectKey}/ai-configs/{configKey}/variations` (instructions or messages, modelConfigKey, model.parameters) -3. **Attach tools** — After creation, PATCH variation to add tools (see `aiconfig-tools` skill) +Use `setup-ai-config` to create the config and its first variation in one call. This is the recommended approach: it handles creation, variation setup, and verification automatically. + +**Config fields:** +- `key` -- unique identifier (lowercase, hyphens) +- `name` -- human-readable name +- `mode` -- `"agent"` or `"completion"` +- Optional: `description`, `tags` + +**Variation fields:** +- `variationKey`, `variationName` -- identifiers for the first variation +- `modelConfigKey` -- must be `Provider.model-id` format (e.g., `OpenAI.gpt-4o`, `Anthropic.claude-sonnet-4-5`) +- `modelName` -- the model identifier (e.g., `gpt-4o`) + +**For agent mode**, provide: +- `instructions` -- a string with the agent's system instructions + +Example agent-mode call: +```json +{ + "projectKey": "my-project", "key": "support-agent", "name": "Support Agent", + "mode": "agent", "variationKey": "default", "variationName": "Default", + "modelConfigKey": "OpenAI.gpt-4o", "modelName": "gpt-4o", + "instructions": "You are a customer support agent. Help users resolve their issues." +} +``` + +**For completion mode**, provide: +- `messages` -- an array of `{role, content}` objects (system, user, assistant) + +Example completion-mode call: +```json +{ + "projectKey": "my-project", "key": "product-descriptions", "name": "Product Descriptions", + "mode": "completion", "variationKey": "default", "variationName": "Default", + "modelConfigKey": "Anthropic.claude-sonnet-4-5", "modelName": "claude-sonnet-4-5", + "messages": [ + {"role": "system", "content": "You are a product copywriter. Write compelling descriptions."}, + {"role": "user", "content": "Write a description for: {{product_name}}"} + ] +} +``` + +**Optional:** +- `parameters` -- model parameters like `{temperature: 0.7, maxTokens: 2000}` + +The tool returns the full verified config detail with the variation attached. + +### Step 3 (Alternative): Two-Step Creation + +If the user asks for more control or a step-by-step approach, use the individual tools: + +1. `create-ai-config` -- create the config shell +2. `create-ai-config-variation` -- add the variation with model, prompts, and parameters +3. `get-ai-config` -- verify the result + +**Execute all three steps without stopping to ask for details.** Infer the variation key (`default`), name (`Default`), instructions/messages, and model from the user's request context. If the user asked for GPT-4o agent mode, you have enough to complete the entire flow. Only ask clarifying questions if the mode or model is truly ambiguous. ### Step 4: Verify -After creation, verify the config: +If you used `setup-ai-config`, verification is automatic: the response includes the full config with variations. Check: -1. **Fetch via API:** - ```bash - curl -X GET "https://app.launchdarkly.com/api/v2/projects/{projectKey}/ai-configs/{configKey}" \ - -H "Authorization: {api_token}" -H "LD-API-Version: beta" - ``` +1. Config exists with the correct mode +2. Variation has a model assigned (not "NO MODEL") +3. Instructions or messages are present +4. Parameters are set -2. **Confirm:** - - Config exists with correct mode - - Variations have model names (not "NO MODEL") - - modelConfigKey is set - - Parameters are present +**Report results:** +- Config created with correct structure +- Variation has model assigned +- Flag any missing model or parameters +- Provide config URL: `https://app.launchdarkly.com/projects/{projectKey}/ai-configs/{configKey}` -3. **Report results:** - - ✓ Config created with correct structure - - ✓ Variations have models assigned - - ⚠️ Flag any missing model or parameters - - Provide config URL: `https://app.launchdarkly.com/projects/{projectKey}/ai-configs/{configKey}` +## modelConfigKey Format -## Important Notes +Required for models to display in the UI. Format: `{Provider}.{model-id}` -- **modelConfigKey** must be `{Provider}.{model-id}` (e.g., `OpenAI.gpt-4o`) for models to show in UI -- **Tools** must be created first (`aiconfig-tools` skill), then attached via PATCH -- **Tools endpoint** is `/ai-tools`, NOT `/ai-configs/tools` +- `OpenAI.gpt-4o` +- `OpenAI.gpt-4o-mini` +- `Anthropic.claude-sonnet-4-5` +- `Anthropic.claude-3-5-sonnet` + +The `create-ai-config-variation` tool validates this format and rejects invalid values. ## Edge Cases | Situation | Action | |-----------|--------| | Config already exists | Ask if user wants to update instead | -| Variation shows "NO MODEL" | PATCH variation with modelConfigKey and model | -| Invalid modelConfigKey | Use values from model-configs API | +| Variation shows "NO MODEL" | Use `update-ai-config-variation` to set modelConfigKey | +| Need to attach tools | Create tools first (`aiconfig-tools` skill), then update the variation | ## What NOT to Do - Don't create configs without understanding the use case - Don't skip the two-step process (config then variation) -- Don't try to attach tools during initial creation -- Don't forget modelConfigKey (models won't show) +- Don't try to attach tools during initial creation -- update the variation afterward +- Don't forget modelConfigKey (models won't show in the UI) ## Related Skills -- `aiconfig-tools` — Create tools before attaching -- `aiconfig-variations` — Add more variations for experimentation -- `aiconfig-update` — Modify configs based on learnings - -## References - -- [API Quick Start](references/api-quickstart.md) -- [LaunchDarkly AI Configs Docs](https://docs.launchdarkly.com/home/ai-configs) +- `aiconfig-tools` -- Create tools before attaching +- `aiconfig-variations` -- Add more variations for experimentation +- `aiconfig-update` -- Modify configs based on learnings diff --git a/skills/ai-configs/aiconfig-create/references/api-quickstart.md b/skills/ai-configs/aiconfig-create/references/api-quickstart.md deleted file mode 100644 index 85290fb..0000000 --- a/skills/ai-configs/aiconfig-create/references/api-quickstart.md +++ /dev/null @@ -1,121 +0,0 @@ -# API Quick Start - -Create AI Configs using the LaunchDarkly API. - -## Two-Step Process - -LaunchDarkly requires creating the config first, then adding variations. This ensures model configuration (`modelConfigKey`) is properly set and variations display correctly in the UI. Creating everything in one call can result in variations showing "NO MODEL" or missing parameters. - -1. **Create the config** — Basic metadata (key, name, mode) -2. **Create variations** — Model, prompts/instructions, parameters for each variation - -## Create Config - -```bash -curl -X POST \ - https://app.launchdarkly.com/api/v2/projects/{projectKey}/ai-configs \ - -H "Authorization: api-xxxxx" \ - -H "Content-Type: application/json" \ - -H "LD-API-Version: beta" \ - -d '{ - "key": "support-agent", - "name": "Customer Support Agent", - "mode": "agent" - }' -``` - -## Create Variation (Agent Mode) - -```bash -curl -X POST \ - https://app.launchdarkly.com/api/v2/projects/{projectKey}/ai-configs/{configKey}/variations \ - -H "Authorization: api-xxxxx" \ - -H "Content-Type: application/json" \ - -H "LD-API-Version: beta" \ - -d '{ - "key": "default", - "name": "Default Configuration", - "instructions": "You are a helpful customer support agent.", - "modelConfigKey": "OpenAI.gpt-4o", - "model": { - "modelName": "gpt-4o", - "parameters": { - "temperature": 0.7, - "maxTokens": 2000 - } - } - }' -``` - -## Create Variation (Completion Mode) - -```bash -curl -X POST \ - https://app.launchdarkly.com/api/v2/projects/{projectKey}/ai-configs/{configKey}/variations \ - -H "Authorization: api-xxxxx" \ - -H "Content-Type: application/json" \ - -H "LD-API-Version: beta" \ - -d '{ - "key": "default", - "name": "Default Configuration", - "messages": [ - {"role": "system", "content": "You are a helpful assistant."}, - {"role": "user", "content": "{{user_prompt}}"} - ], - "modelConfigKey": "Anthropic.claude-sonnet-4-5", - "model": { - "modelName": "claude-sonnet-4-5", - "parameters": { - "temperature": 0.8, - "maxTokens": 4000 - } - } - }' -``` - -## modelConfigKey Format - -Required for models to show in UI: `{Provider}.{model-id}` - -- `OpenAI.gpt-4o` -- `OpenAI.gpt-4o-mini` -- `Anthropic.claude-sonnet-4-5` -- `Anthropic.claude-3-5-sonnet` - -## Attach Tools (After Creation) - -Tools cannot be attached during config creation. PATCH the variation: - -```bash -curl -X PATCH \ - https://app.launchdarkly.com/api/v2/projects/{projectKey}/ai-configs/{configKey}/variations/{variationKey} \ - -H "Authorization: api-xxxxx" \ - -H "Content-Type: application/json" \ - -H "LD-API-Version: beta" \ - -d '{ - "model": { - "parameters": { - "tools": [ - {"key": "search-database", "version": 1} - ] - } - } - }' -``` - -## Verify Config - -```bash -curl -X GET \ - https://app.launchdarkly.com/api/v2/projects/{projectKey}/ai-configs/{configKey} \ - -H "Authorization: api-xxxxx" \ - -H "LD-API-Version: beta" -``` - -## List Models - -```bash -curl -X GET \ - https://app.launchdarkly.com/api/v2/projects/{projectKey}/ai-configs/model-configs \ - -H "Authorization: api-xxxxx" -``` diff --git a/skills/ai-configs/aiconfig-projects/README.md b/skills/ai-configs/aiconfig-projects/README.md index 2c65b01..e48531f 100644 --- a/skills/ai-configs/aiconfig-projects/README.md +++ b/skills/ai-configs/aiconfig-projects/README.md @@ -61,7 +61,7 @@ aiconfig-projects/ ## Related -- [LaunchDarkly AI Configs](https://docs.launchdarkly.com/home/ai-configs) — Create AI Configs after setting up projects +- [LaunchDarkly AI Configs](https://docs.launchdarkly.com/home/ai-configs): Create AI Configs after setting up projects - [LaunchDarkly Docs](https://docs.launchdarkly.com) - [Agent Skills Specification](https://agentskills.io/specification) diff --git a/skills/ai-configs/aiconfig-projects/SKILL.md b/skills/ai-configs/aiconfig-projects/SKILL.md index 7c9ffd1..623873a 100644 --- a/skills/ai-configs/aiconfig-projects/SKILL.md +++ b/skills/ai-configs/aiconfig-projects/SKILL.md @@ -22,15 +22,15 @@ You're using a skill that will guide you through setting up LaunchDarkly project 1. **Understand First**: Explore the codebase to understand the stack and patterns. 2. **Choose the Right Fit**: Select an approach that matches your architecture. 3. **Follow Conventions**: Respect existing code style and structure. -4. **Verify Integration**: Confirm the setup works — the agent performs checks and reports results. +4. **Verify Integration**: Confirm the setup works: the agent performs checks and reports results. ## API Key Detection Before prompting the user for an API key, try to detect it automatically: -1. **Check environment variables** — Look for `LAUNCHDARKLY_API_KEY`, `LAUNCHDARKLY_API_TOKEN`, or `LD_API_KEY` -2. **Check MCP config** — If using Claude, read `~/.claude/config.json` for `mcpServers.launchdarkly.env.LAUNCHDARKLY_API_KEY` -3. **Prompt user** — Only if detection fails, ask the user for their API key +1. **Check environment variables**: Look for `LAUNCHDARKLY_API_KEY`, `LAUNCHDARKLY_API_TOKEN`, or `LD_API_KEY` +2. **Check MCP config**: If using Claude, read `~/.claude/config.json` for `mcpServers.launchdarkly.env.LAUNCHDARKLY_API_KEY` +3. **Prompt user**: Only if detection fails, ask the user for their API key See [Quick Start](references/quick-start.md) for API usage patterns. diff --git a/skills/ai-configs/aiconfig-tools/README.md b/skills/ai-configs/aiconfig-tools/README.md index 671c2bb..7b573ba 100644 --- a/skills/ai-configs/aiconfig-tools/README.md +++ b/skills/ai-configs/aiconfig-tools/README.md @@ -6,9 +6,9 @@ An Agent Skill for creating tools (function calling) and attaching them to AI Co This skill teaches agents how to: - Identify what capabilities the AI needs -- Create tool definitions with JSON schemas via the API -- Attach tools to AI Config variations -- Verify tools are properly connected +- Create tool definitions using the `create-ai-tool` MCP tool +- Attach tools to AI Config variations via `update-ai-config-variation` +- Verify tools are properly connected via `get-ai-config` ## Installation (Local) @@ -16,8 +16,7 @@ Copy `skills/ai-configs/aiconfig-tools/` into your agent client's skills path. ## Prerequisites -- LaunchDarkly API token with `/*:ai-tool/*` permission -- Existing AI Config (use `aiconfig-create` skill first) +This skill requires the remotely hosted LaunchDarkly MCP server to be configured in your environment. ## Usage @@ -34,15 +33,13 @@ Create tools for the content assistant to call our API ``` aiconfig-tools/ ├── SKILL.md -├── README.md -└── references/ - └── api-quickstart.md +└── README.md ``` ## Related -- [AI Config Create](../aiconfig-create/) — Create the config before adding tools -- [AI Config Variations](../aiconfig-variations/) — Manage variations that tools attach to +- [AI Config Create](../aiconfig-create/): Create the config before adding tools +- [AI Config Variations](../aiconfig-variations/): Manage variations that tools attach to - [LaunchDarkly AI Configs Docs](https://docs.launchdarkly.com/home/ai-configs) ## License diff --git a/skills/ai-configs/aiconfig-tools/SKILL.md b/skills/ai-configs/aiconfig-tools/SKILL.md index a8ff757..6cb723e 100644 --- a/skills/ai-configs/aiconfig-tools/SKILL.md +++ b/skills/ai-configs/aiconfig-tools/SKILL.md @@ -1,10 +1,11 @@ --- name: aiconfig-tools -description: Guide for giving your AI agents capabilities through tools. Helps you identify what your AI needs to do, create tool definitions, and attach them in a way that makes sense for your framework. -compatibility: Requires LaunchDarkly API token with ai-tool permissions. +description: "Give your AI agents capabilities through tools (function calling). Helps you identify what your AI needs to do, create tool definitions, and attach them to AI Config variations." +license: Apache-2.0 +compatibility: Requires the remotely hosted LaunchDarkly MCP server metadata: author: launchdarkly - version: "0.2.0" + version: "1.0.0-experimental" --- # AI Config Tools @@ -13,94 +14,104 @@ You're using a skill that will guide you through adding capabilities to your AI ## Prerequisites -- LaunchDarkly API token with `/*:ai-tool/*` permission -- Existing AI Config (use `aiconfig-create` skill first) -- Tools endpoint: `/ai-tools` (NOT `/ai-configs/tools`) +This skill requires the remotely hosted LaunchDarkly MCP server to be configured in your environment. + +**Required MCP tools:** +- `create-ai-tool` -- create a new tool definition with a schema +- `update-ai-config-variation` -- attach tools to an AI Config variation +- `get-ai-config` -- verify tools are attached to the variation + +**Optional MCP tools:** +- `list-ai-tools` -- browse existing tools in the project +- `get-ai-tool` -- inspect a specific tool's schema ## Core Principles 1. **Start with Capabilities**: Think about what your AI needs to do before creating tools 2. **Framework Matters**: LangGraph/CrewAI often auto-generate schemas; OpenAI SDK needs manual schemas 3. **Create Before Attach**: Tools must exist before you can attach them to variations -4. **Verify**: The agent fetches tools and config to confirm attachment - -## API Key Detection - -1. **Check environment variables** — `LAUNCHDARKLY_API_KEY`, `LAUNCHDARKLY_API_TOKEN`, `LD_API_KEY` -2. **Check MCP config** — Claude config if applicable -3. **Prompt user** — Only if detection fails +4. **Verify**: The agent fetches the config to confirm attachment +5. **Complete the Full Workflow**: Listing existing tools is a discovery step, not the end goal. After listing, always proceed to create the requested tool, attach it, and verify. Do not stop after exploration. ## Workflow ### Step 1: Identify Needed Capabilities What should the AI be able to do? - - Query databases, call APIs, perform calculations, send notifications - Check what exists in the codebase (API clients, functions) - Consider framework: LangGraph/LangChain auto-generate schemas; direct SDK needs manual schemas +If the user asks to check existing tools first, or you have no codebase context about what tools exist, follow this exact order: +1. `list-ai-tools` -- explore what exists +2. `create-ai-tool` -- create the new tool (with a key different from existing ones) +3. `update-ai-config-variation` -- attach it +4. `get-ai-config` -- verify + +Call `list-ai-tools` as your **first** tool call before any creation. Never stop after listing alone -- always proceed through all four steps. + ### Step 2: Create Tools -Follow [API Quick Start](references/api-quickstart.md): +Use `create-ai-tool` with: +- `key` -- unique identifier for the tool +- `description` -- clear description (the LLM uses this to decide when to call the tool) +- `schema` -- raw JSON Schema (do NOT use the OpenAI function calling wrapper): -1. **Create tool** — `POST /projects/{projectKey}/ai-tools` with key, description, schema -2. **Schema format** — Use OpenAI function calling format (type, function.name, function.parameters) -3. **Clear descriptions** — The LLM uses the description to decide when to call +```json +{ + "type": "object", + "properties": { + "query": {"type": "string", "description": "Search query"}, + "limit": {"type": "integer", "default": 10} + }, + "required": ["query"] +} +``` ### Step 3: Attach to Variation -Tools cannot be attached during config creation. PATCH the variation: +Use `update-ai-config-variation` to attach tools. Pass the tool references in the `tools` field: -```bash -PATCH /projects/{projectKey}/ai-configs/{configKey}/variations/{variationKey} +```json +{ + "projectKey": "my-project", + "configKey": "support-chatbot", + "variationKey": "default", + "tools": [ + {"key": "search-knowledge-base", "version": 1} + ] +} ``` -Body: `{"model": {"parameters": {"tools": [{"key": "tool-name", "version": 1}]}}}` - -See [API Quick Start](references/api-quickstart.md) for full curl example. - ### Step 4: Verify -1. **Verify tool exists:** - ```bash - GET /projects/{projectKey}/ai-tools/{toolKey} - ``` +1. Use `get-ai-tool` to confirm the tool exists with a valid schema +2. Use `get-ai-config` to confirm the tool is attached to the variation (check `tools` in the variation's output) -2. **Verify attached to variation:** - ```bash - GET /projects/{projectKey}/ai-configs/{configKey}/variations/{variationKey} - ``` - Check `model.parameters.tools` includes your tool key. - -3. **Report results:** - - ✓ Tool created with valid schema - - ✓ Tool attached to variation - - ⚠️ Flag any issues +**Report results:** +- Tool created with valid schema +- Tool attached to variation +- Flag any issues ## Orchestrator Note -LangGraph, CrewAI, AutoGen often generate schemas from function definitions. You still need to create tools in LaunchDarkly and attach keys to variations so the SDK knows what's available. +LangGraph, CrewAI, and AutoGen often generate schemas from function definitions. You still need to create tools in LaunchDarkly and attach keys to variations so the SDK knows what's available. ## Edge Cases | Situation | Action | |-----------|--------| | Tool already exists (409) | Use existing or create with different key | -| Wrong endpoint | Use `/ai-tools`, not `/ai-configs/tools` | -| Schema invalid | Use OpenAI function format | +| Schema invalid | Use raw JSON Schema format (type: object, properties, required) | +| Wrong endpoint assumed | The tools use `/ai-tools`, not `/ai-configs/tools` | ## What NOT to Do -- Don't use `/ai-configs/tools` — it doesn't exist -- Don't try to attach tools during config creation -- Don't skip clear tool descriptions (LLM needs them) +- Don't try to attach tools during config creation -- update the variation afterward +- Don't skip clear tool descriptions (LLM needs them to decide when to call) +- Don't forget to verify attachment after updating the variation ## Related Skills -- `aiconfig-create` — Create config before attaching tools -- `aiconfig-variations` — Manage variations - -## References - -- [API Quick Start](references/api-quickstart.md) +- `aiconfig-create` -- Create config before attaching tools +- `aiconfig-variations` -- Manage variations with different tool sets diff --git a/skills/ai-configs/aiconfig-tools/references/api-quickstart.md b/skills/ai-configs/aiconfig-tools/references/api-quickstart.md deleted file mode 100644 index 9549dc4..0000000 --- a/skills/ai-configs/aiconfig-tools/references/api-quickstart.md +++ /dev/null @@ -1,88 +0,0 @@ -# Tools API Quick Start - -Create and manage tools using the LaunchDarkly API. - -**Endpoint:** `https://app.launchdarkly.com/api/v2/projects/{projectKey}/ai-tools` -Do NOT use `/ai-configs/tools` — that endpoint does not exist. - -## Create a Tool - -```bash -curl -X POST \ - https://app.launchdarkly.com/api/v2/projects/{projectKey}/ai-tools \ - -H "Authorization: api-xxxxx" \ - -H "Content-Type: application/json" \ - -d '{ - "key": "search-database", - "description": "Search the customer database", - "schema": { - "type": "function", - "function": { - "name": "search_database", - "description": "Search for records", - "parameters": { - "type": "object", - "properties": { - "query": {"type": "string", "description": "Search query"}, - "limit": {"type": "integer", "default": 10} - }, - "required": ["query"] - } - } - } - }' -``` - -## Attach to Variation - -```bash -curl -X PATCH \ - https://app.launchdarkly.com/api/v2/projects/{projectKey}/ai-configs/{configKey}/variations/{variationKey} \ - -H "Authorization: api-xxxxx" \ - -H "Content-Type: application/json" \ - -H "LD-API-Version: beta" \ - -d '{ - "model": { - "parameters": { - "tools": [ - {"key": "search-database", "version": 1} - ] - } - } - }' -``` - -## List Tools - -```bash -curl -X GET \ - https://app.launchdarkly.com/api/v2/projects/{projectKey}/ai-tools \ - -H "Authorization: api-xxxxx" -``` - -## Get Tool - -```bash -curl -X GET \ - https://app.launchdarkly.com/api/v2/projects/{projectKey}/ai-tools/{toolKey} \ - -H "Authorization: api-xxxxx" -``` - -## Schema Format - -Use OpenAI function calling format: - -```json -{ - "type": "function", - "function": { - "name": "function_name", - "description": "What the LLM uses to decide when to call", - "parameters": { - "type": "object", - "properties": { ... }, - "required": [ ... ] - } - } -} -``` diff --git a/skills/ai-configs/aiconfig-update/README.md b/skills/ai-configs/aiconfig-update/README.md index 9f1e00b..7754356 100644 --- a/skills/ai-configs/aiconfig-update/README.md +++ b/skills/ai-configs/aiconfig-update/README.md @@ -5,10 +5,11 @@ An Agent Skill for updating, archiving, and deleting AI Configs and their variat ## Overview This skill teaches agents how to: -- Update config metadata (name, description) -- Modify variation instructions, messages, models, and parameters -- Archive configs (reversible) or delete them (permanent) -- Verify changes via API fetch +- Assess config health using `get-ai-config-health` before making changes +- Update config metadata (name, description, tags) via `update-ai-config` +- Modify variation instructions, messages, models, and parameters via `update-ai-config-variation` +- Archive configs (reversible) or delete them (permanent, irreversible) +- Verify changes via `get-ai-config` ## Installation (Local) @@ -16,8 +17,7 @@ Copy `skills/ai-configs/aiconfig-update/` into your agent client's skills path. ## Prerequisites -- LaunchDarkly API access token with write permissions -- Existing AI Config to modify +This skill requires the remotely hosted LaunchDarkly MCP server to be configured in your environment. ## Usage @@ -38,15 +38,13 @@ Archive the old chatbot config ``` aiconfig-update/ ├── SKILL.md -├── README.md -└── references/ - └── api-quickstart.md +└── README.md ``` ## Related -- [AI Config Create](../aiconfig-create/) — Create configs -- [AI Config Variations](../aiconfig-variations/) — Add or test variations +- [AI Config Create](../aiconfig-create/): Create configs +- [AI Config Variations](../aiconfig-variations/): Add or test variations - [LaunchDarkly AI Configs Docs](https://docs.launchdarkly.com/home/ai-configs) ## License diff --git a/skills/ai-configs/aiconfig-update/SKILL.md b/skills/ai-configs/aiconfig-update/SKILL.md index f5b1329..d3d9c49 100644 --- a/skills/ai-configs/aiconfig-update/SKILL.md +++ b/skills/ai-configs/aiconfig-update/SKILL.md @@ -1,10 +1,11 @@ --- name: aiconfig-update -description: Update, archive, and delete LaunchDarkly AI Configs and their variations. Use when you need to modify config properties, change model parameters, update instructions or messages, archive unused configs, or permanently remove them. -compatibility: Requires LaunchDarkly project with AI Configs enabled and API access token. +description: "Update, archive, and delete LaunchDarkly AI Configs and their variations. Use when you need to modify config properties, change model parameters, update instructions or messages, archive unused configs, or permanently remove them." +license: Apache-2.0 +compatibility: Requires the remotely hosted LaunchDarkly MCP server metadata: author: launchdarkly - version: "0.2.0" + version: "1.0.0-experimental" --- # AI Config Update & Lifecycle @@ -13,8 +14,17 @@ You're using a skill that will guide you through updating, archiving, and deleti ## Prerequisites -- Existing AI Config to modify -- LaunchDarkly API access token or MCP server +This skill requires the remotely hosted LaunchDarkly MCP server to be configured in your environment. + +**Required MCP tools:** +- `get-ai-config-health` -- assess config health before making changes (detects missing models, orphaned tools, empty configs) +- `get-ai-config` -- understand current state before making changes +- `update-ai-config` -- update config metadata (name, description, tags, archive) +- `update-ai-config-variation` -- update variation model, prompts, or parameters + +**Optional MCP tools:** +- `delete-ai-config` -- permanently delete a config (irreversible) +- `delete-ai-config-variation` -- permanently delete a variation (irreversible) ## Core Principles @@ -22,57 +32,63 @@ You're using a skill that will guide you through updating, archiving, and deleti 2. **Verify After Changing**: Fetch the config again to confirm updates were applied 3. **Archive Before Deleting**: Archival is reversible; deletion is not -## API Key Detection - -1. **Check environment variables** — `LAUNCHDARKLY_API_KEY`, `LAUNCHDARKLY_API_TOKEN`, `LD_API_KEY` -2. **Check MCP config** — If applicable -3. **Prompt user** — Only if detection fails - ## Workflow -### Step 1: Understand Current State +### Step 1: Assess Health and Understand Current State -Fetch the config to see what exists before changing anything: -```bash -GET /projects/{projectKey}/ai-configs/{configKey} -``` +Start with `get-ai-config-health` to get a structured health assessment. This detects: +- Variations with no model (show as "NO MODEL" in the UI) +- Variations with neither instructions nor messages +- Orphaned tool references (tools attached that don't exist in the project) +- Configs with no variations at all + +The health verdict (`healthy`, `warning`, `unhealthy`) helps you prioritize what to fix. + +Then use `get-ai-config` to review the full detail: +- Current mode (agent or completion) +- Existing variations and their models +- Current instructions or messages +- Attached tools and parameters ### Step 2: Make the Update -Follow [API Quick Start](references/api-quickstart.md): +**Update config metadata** -- Use `update-ai-config`: +- Change name or description +- Add or replace tags +- Archive with `archived: true` (reversible) -- **Update instructions/messages** — PATCH variation -- **Switch model** — PATCH variation with modelConfigKey and model -- **Tune parameters** — PATCH variation with model.parameters -- **Archive config** — PATCH config with `{"archived": true}` -- **Delete** — DELETE config or variation (irreversible) +**Update a variation** -- Use `update-ai-config-variation`: +- Switch model (provide new `modelConfigKey` and `modelName`) +- Change instructions or messages +- Tune parameters (temperature, maxTokens, etc.) +- Attach or detach tools via the parameters object -### Step 4: Verify +**Archive a config** -- Use `update-ai-config` with `archived: true`. Archiving is the **preferred** way to retire a config: +- It is reversible (unarchive with `archived: false`) +- The config is hidden from active lists but preserved +- After calling the archive, treat a successful response as confirmation and proceed to verification +- When a user says "remove", "retire", "decommission", or "no longer need", default to archiving unless they explicitly say "delete permanently" -1. **Fetch updated config:** - ```bash - GET /projects/{projectKey}/ai-configs/{configKey}/variations/{variationKey} - ``` +**Delete** -- Use `delete-ai-config` or `delete-ai-config-variation` (irreversible, requires `confirm: true`). **Always suggest archiving first.** Only proceed with deletion if the user explicitly confirms they want permanent, irreversible removal. -2. **Confirm the response shows your updated values** +### Step 3: Verify -3. **Report results:** - - ✓ Update applied successfully - - ✓ Config reflects changes - - ⚠️ Flag any issues or rollback if needed +Use `get-ai-config` to confirm the response shows your updated values. + +**Report results:** +- Update applied successfully +- Config reflects changes +- Flag any issues or rollback if needed ## What NOT to Do -- Don't update production directly without testing -- Don't change multiple things at once +- Don't update production configs without testing in another variation first +- Don't change multiple things at once -- make incremental changes - Don't skip verification -- Don't delete without user confirmation +- Don't delete without explicit user confirmation -- always suggest archiving first +- Don't retry an update because the API response doesn't echo back the exact values you sent -- verify with `get-ai-config` instead ## Related Skills -- `aiconfig-variations` — Create variations to test changes -- `aiconfig-tools` — Update tools - -## References - -- [API Quick Start](references/api-quickstart.md) +- `aiconfig-variations` -- Create variations to test changes side-by-side +- `aiconfig-tools` -- Update tool attachments diff --git a/skills/ai-configs/aiconfig-update/references/api-quickstart.md b/skills/ai-configs/aiconfig-update/references/api-quickstart.md deleted file mode 100644 index ffaea8c..0000000 --- a/skills/ai-configs/aiconfig-update/references/api-quickstart.md +++ /dev/null @@ -1,74 +0,0 @@ -# Update API Quick Start - -Update and delete AI Configs using the LaunchDarkly API. - -## Update Config Metadata - -```bash -curl -X PATCH \ - https://app.launchdarkly.com/api/v2/projects/{projectKey}/ai-configs/{configKey} \ - -H "Authorization: api-xxxxx" \ - -H "Content-Type: application/json" \ - -H "LD-API-Version: beta" \ - -d '{ - "name": "Updated Name", - "description": "Updated description" - }' -``` - -## Update Variation - -```bash -curl -X PATCH \ - https://app.launchdarkly.com/api/v2/projects/{projectKey}/ai-configs/{configKey}/variations/{variationKey} \ - -H "Authorization: api-xxxxx" \ - -H "Content-Type: application/json" \ - -H "LD-API-Version: beta" \ - -d '{ - "instructions": "Updated instructions...", - "model": { - "parameters": { - "temperature": 0.5, - "maxTokens": 1500 - } - } - }' -``` - -## Archive Config - -```bash -curl -X PATCH \ - https://app.launchdarkly.com/api/v2/projects/{projectKey}/ai-configs/{configKey} \ - -H "Authorization: api-xxxxx" \ - -H "Content-Type: application/json" \ - -H "LD-API-Version: beta" \ - -d '{"archived": true}' -``` - -## Delete Config - -```bash -curl -X DELETE \ - https://app.launchdarkly.com/api/v2/projects/{projectKey}/ai-configs/{configKey} \ - -H "Authorization: api-xxxxx" \ - -H "LD-API-Version: beta" -``` - -## Delete Variation - -```bash -curl -X DELETE \ - https://app.launchdarkly.com/api/v2/projects/{projectKey}/ai-configs/{configKey}/variations/{variationKey} \ - -H "Authorization: api-xxxxx" \ - -H "LD-API-Version: beta" -``` - -## Verify Update - -```bash -curl -X GET \ - https://app.launchdarkly.com/api/v2/projects/{projectKey}/ai-configs/{configKey}/variations/{variationKey} \ - -H "Authorization: api-xxxxx" \ - -H "LD-API-Version: beta" -``` diff --git a/skills/ai-configs/aiconfig-variations/README.md b/skills/ai-configs/aiconfig-variations/README.md index 5bb9f69..fe91011 100644 --- a/skills/ai-configs/aiconfig-variations/README.md +++ b/skills/ai-configs/aiconfig-variations/README.md @@ -6,9 +6,8 @@ An Agent Skill for creating and managing AI Config variations to experiment with This skill teaches agents how to: - Design experiments (model comparison, prompt optimization, parameter tuning) -- Create variations via the API -- Attach tools to variations -- Verify variations exist with correct configuration +- Create variations using `clone-ai-config-variation` (recommended) or `create-ai-config-variation` +- Verify variations exist with correct configuration via `get-ai-config` ## Installation (Local) @@ -16,8 +15,7 @@ Copy `skills/ai-configs/aiconfig-variations/` into your agent client's skills pa ## Prerequisites -- LaunchDarkly API access token with `ai-configs:write` permission -- Existing AI Config (use `aiconfig-create` skill first) +This skill requires the remotely hosted LaunchDarkly MCP server to be configured in your environment. ## Usage @@ -34,16 +32,14 @@ Create variations to compare Claude vs GPT-4 for our agent ``` aiconfig-variations/ ├── SKILL.md -├── README.md -└── references/ - └── api-quickstart.md +└── README.md ``` ## Related -- [AI Config Create](../aiconfig-create/) — Create the config first -- [AI Config Update](../aiconfig-update/) — Modify existing variations -- [AI Config Tools](../aiconfig-tools/) — Attach tools to variations +- [AI Config Create](../aiconfig-create/): Create the config first +- [AI Config Update](../aiconfig-update/): Modify existing variations +- [AI Config Tools](../aiconfig-tools/): Attach tools to variations - [LaunchDarkly AI Configs Docs](https://docs.launchdarkly.com/home/ai-configs) ## License diff --git a/skills/ai-configs/aiconfig-variations/SKILL.md b/skills/ai-configs/aiconfig-variations/SKILL.md index 17627bb..34b5957 100644 --- a/skills/ai-configs/aiconfig-variations/SKILL.md +++ b/skills/ai-configs/aiconfig-variations/SKILL.md @@ -1,10 +1,11 @@ --- name: aiconfig-variations -description: Guide for experimenting with AI configurations. Helps you test different models, prompts, and parameters to find what works best through systematic experimentation. -compatibility: Requires LaunchDarkly API access token with ai-configs:write permission. +description: "Experiment with AI configurations by creating and managing variations. Helps you test different models, prompts, and parameters to find what works best through systematic experimentation." +license: Apache-2.0 +compatibility: Requires the remotely hosted LaunchDarkly MCP server metadata: author: launchdarkly - version: "0.2.0" + version: "1.0.0-experimental" --- # AI Config Variations @@ -13,22 +14,25 @@ You're using a skill that will guide you through testing and optimizing AI confi ## Prerequisites -- Existing AI Config (use `aiconfig-create` first) -- LaunchDarkly API access token or MCP server -- Clear hypothesis about what to test +This skill requires the remotely hosted LaunchDarkly MCP server to be configured in your environment. + +**Primary MCP tool:** +- `clone-ai-config-variation` -- clone a baseline variation with selective overrides (recommended for experimentation) + +**Alternative MCP tools (for more control):** +- `get-ai-config` -- review existing variations before adding new ones +- `create-ai-config-variation` -- create new variations from scratch + +**Optional MCP tools:** +- `update-ai-config-variation` -- refine a variation after creation +- `delete-ai-config-variation` -- remove variations that didn't work out ## Core Principles 1. **Test One Thing at a Time**: Change model OR prompt OR parameters, not all at once 2. **Have a Hypothesis**: Know what you're trying to improve 3. **Measure Results**: Use metrics to compare variations -4. **Verify via API**: The agent fetches the config to confirm variations exist - -## API Key Detection - -1. **Check environment variables** — `LAUNCHDARKLY_API_KEY`, `LAUNCHDARKLY_API_TOKEN`, `LD_API_KEY` -2. **Check MCP config** — If applicable -3. **Prompt user** — Only if detection fails +4. **Verify via Tool**: The agent fetches the config to confirm variations exist ## Workflow @@ -40,53 +44,67 @@ What's the problem? Cost, quality, speed, accuracy? How will you measure success | Goal | What to Vary | |------|--------------| -| Reduce cost | Cheaper model (e.g., gpt-4o-mini) | -| Improve quality | Better model or prompt | -| Reduce latency | Faster model, lower max_tokens | -| Increase accuracy | Different model (Claude vs GPT-4) | +| Reduce cost | Cheaper model (e.g., `gpt-4o-mini`) | +| Improve quality | Better model or more detailed prompt | +| Reduce latency | Faster model, lower `maxTokens` | +| Increase accuracy | Different model family (Claude vs GPT-4) | -### Step 3: Create Variations +### Step 3: Create Variations (Recommended: Clone with Overrides) -Follow [API Quick Start](references/api-quickstart.md): +Use `clone-ai-config-variation` to duplicate the baseline and override only what you're testing. The tool reads the source variation, merges your overrides, and creates the new variation. Everything you **don't** pass is inherited from the source automatically. -- `POST /projects/{projectKey}/ai-configs/{configKey}/variations` -- Include modelConfigKey (required for UI) -- Keep everything else constant except what you're testing +**Required fields:** +- `sourceVariationKey` -- the baseline to clone from +- `key` and `name` -- identifiers for the new variation (e.g., `gpt4o-mini-cost-test`) -### Step 4: Set Up Targeting +**Override ONLY the fields you are testing.** Leave all other fields unset -- do not pass them even if you know their current values. The clone tool inherits them from the source. This enforces the one-variable-at-a-time principle: -Use `aiconfig-targeting` skill to control distribution (e.g., 50/50 split for A/B test). +- Testing a cheaper model? Pass only `modelConfigKey` and `modelName`. Do NOT pass `instructions`, `messages`, or `parameters`. +- Testing different instructions? Pass only `instructions`. Do NOT pass `modelConfigKey` or `modelName`. +- Testing a parameter? Pass only `parameters`. Do NOT pass model or prompt fields. -### Step 5: Verify +The response returns both the source and created variation, so you can immediately verify the diff. -1. **Fetch config:** - ```bash - GET /projects/{projectKey}/ai-configs/{configKey} - ``` +### Step 3 (Alternative): Create from Scratch -2. **Confirm variations exist with correct model and parameters** +If you need full control, use `get-ai-config` first to review the current state, then `create-ai-config-variation` with all fields specified manually. Always fetch before creating so you understand the existing config's mode, model, and parameters. -3. **Report results:** - - ✓ Variations created - - ✓ Models and parameters correct - - ⚠️ Flag any issues +### Step 4: Verify -## modelConfigKey +If you used `clone-ai-config-variation`, the response includes both source and created variations for immediate comparison. Otherwise, use `get-ai-config` to confirm. -Required for models to show in UI. Format: `{Provider}.{model-id}` — e.g., `OpenAI.gpt-4o`, `Anthropic.claude-sonnet-4-5`. +**Report results:** +- Variations created with correct models and parameters +- Only the intended variable differs between variations +- Flag any issues + +**Note on API responses:** After calling a creation or clone tool, treat a successful response as confirmation that the operation succeeded. The API response may not echo back every field you sent (e.g., model fields may show defaults). Do not retry or assume failure based on response field values alone -- verify with `get-ai-config` if needed. + +## modelConfigKey Format + +Required for models to display in the UI. Format: `{Provider}.{model-id}`: +- `OpenAI.gpt-4o`, `OpenAI.gpt-4o-mini` +- `Anthropic.claude-sonnet-4-5`, `Anthropic.claude-3-5-sonnet` + +## Safety: Protect the Baseline + +When the user wants to try a different model, prompt, or parameters, **always create a new variation alongside the baseline**. Never modify or delete the existing baseline variation. This applies even if the user says "replace" or "switch" -- the correct action is to create a new variation and let targeting/rollouts control traffic, not to edit the original. + +- Use `clone-ai-config-variation` or `create-ai-config-variation` to add the new variation +- Do NOT use `update-ai-config-variation` on the baseline to change its model or instructions +- Do NOT use `delete-ai-config-variation` on the baseline +- Explain to the user that keeping the baseline enables comparison and safe rollback ## What NOT to Do -- Don't test too many things at once -- Don't forget modelConfigKey +- Don't test too many things at once -- change one variable per variation +- Don't pass unchanged fields when cloning -- let the tool inherit them from the source +- Don't forget modelConfigKey (variations without it show as "NO MODEL" in the UI) - Don't make decisions on small sample sizes +- Don't modify or remove the baseline variation -- create new variations alongside it +- Don't use `update-ai-config-variation` to "replace" a baseline -- create a new variation instead ## Related Skills -- `aiconfig-create` — Create the initial config -- `aiconfig-targeting` — Control who gets which variation -- `aiconfig-update` — Refine based on learnings - -## References - -- [API Quick Start](references/api-quickstart.md) +- `aiconfig-create` -- Create the initial config +- `aiconfig-update` -- Refine based on learnings diff --git a/skills/ai-configs/aiconfig-variations/references/api-quickstart.md b/skills/ai-configs/aiconfig-variations/references/api-quickstart.md deleted file mode 100644 index 526d553..0000000 --- a/skills/ai-configs/aiconfig-variations/references/api-quickstart.md +++ /dev/null @@ -1,112 +0,0 @@ -# Variations API Quick Start - -Create, update, and manage variations using the LaunchDarkly API. - -## Create Variation (Agent Mode) - -```bash -curl -X POST \ - https://app.launchdarkly.com/api/v2/projects/{projectKey}/ai-configs/{configKey}/variations \ - -H "Authorization: api-xxxxx" \ - -H "Content-Type: application/json" \ - -H "LD-API-Version: beta" \ - -d '{ - "key": "gpt4o-variant", - "name": "GPT-4o Variant", - "instructions": "You are a helpful assistant.", - "modelConfigKey": "OpenAI.gpt-4o", - "model": { - "modelName": "gpt-4o", - "parameters": { - "temperature": 0.7, - "maxTokens": 1500 - } - } - }' -``` - -## Create Variation (Completion Mode) - -```bash -curl -X POST \ - https://app.launchdarkly.com/api/v2/projects/{projectKey}/ai-configs/{configKey}/variations \ - -H "Authorization: api-xxxxx" \ - -H "Content-Type: application/json" \ - -H "LD-API-Version: beta" \ - -d '{ - "key": "claude-variant", - "name": "Claude Variant", - "messages": [ - {"role": "system", "content": "You are helpful."}, - {"role": "user", "content": "{{user_input}}"} - ], - "modelConfigKey": "Anthropic.claude-sonnet-4-5", - "model": { - "modelName": "claude-sonnet-4-5", - "parameters": { - "temperature": 0.8, - "maxTokens": 2000 - } - } - }' -``` - -## Update Variation - -```bash -curl -X PATCH \ - https://app.launchdarkly.com/api/v2/projects/{projectKey}/ai-configs/{configKey}/variations/{variationKey} \ - -H "Authorization: api-xxxxx" \ - -H "Content-Type: application/json" \ - -H "LD-API-Version: beta" \ - -d '{ - "instructions": "Updated instructions...", - "model": { - "parameters": { - "temperature": 0.5, - "maxTokens": 1000 - } - } - }' -``` - -## List Variations - -```bash -curl -X GET \ - https://app.launchdarkly.com/api/v2/projects/{projectKey}/ai-configs/{configKey} \ - -H "Authorization: api-xxxxx" \ - -H "LD-API-Version: beta" -``` - -## Delete Variation - -```bash -curl -X DELETE \ - https://app.launchdarkly.com/api/v2/projects/{projectKey}/ai-configs/{configKey}/variations/{variationKey} \ - -H "Authorization: api-xxxxx" \ - -H "LD-API-Version: beta" -``` - -## modelConfigKey Format - -`{Provider}.{model-id}` — e.g., `OpenAI.gpt-4o`, `Anthropic.claude-sonnet-4-5` - -## Attach Tools - -```bash -curl -X PATCH \ - https://app.launchdarkly.com/api/v2/projects/{projectKey}/ai-configs/{configKey}/variations/{variationKey} \ - -H "Authorization: api-xxxxx" \ - -H "Content-Type: application/json" \ - -H "LD-API-Version: beta" \ - -d '{ - "model": { - "parameters": { - "tools": [ - {"key": "search-database", "version": 1} - ] - } - } - }' -``` diff --git a/skills/feature-flags/launchdarkly-flag-cleanup/SKILL.md b/skills/feature-flags/launchdarkly-flag-cleanup/SKILL.md index 02fa36c..933b51b 100644 --- a/skills/feature-flags/launchdarkly-flag-cleanup/SKILL.md +++ b/skills/feature-flags/launchdarkly-flag-cleanup/SKILL.md @@ -19,12 +19,12 @@ If you haven't already identified which flag to clean up, use the [flag discover This skill requires the remotely hosted LaunchDarkly MCP server to be configured in your environment. **Required MCP tools:** -- `check-removal-readiness` — detailed safety check (orchestrates flag config, cross-env status, dependencies, code references, and expiring targets in parallel) -- `get-flag` — fetch flag configuration for a specific environment +- `check-removal-readiness`: detailed safety check (orchestrates flag config, cross-env status, dependencies, code references, and expiring targets in parallel) +- `get-flag`: fetch flag configuration for a specific environment **Optional MCP tools:** -- `archive-flag` — archive the flag in LaunchDarkly after code removal -- `delete-flag` — permanently delete the flag (irreversible, prefer archive) +- `archive-flag`: archive the flag in LaunchDarkly after code removal +- `delete-flag`: permanently delete the flag (irreversible, prefer archive) ## Core Principles @@ -64,11 +64,11 @@ Use `check-removal-readiness` to get a detailed safety assessment. This single t The tool returns a readiness verdict: -**`safe`** — No blockers or warnings. Proceed with removal. +**`safe`**: No blockers or warnings. Proceed with removal. -**`caution`** — No hard blockers but warnings exist (e.g., code references in other repos, expiring targets scheduled, flag marked as permanent). Present warnings and let the user decide. +**`caution`**: No hard blockers but warnings exist (e.g., code references in other repos, expiring targets scheduled, flag marked as permanent). Present warnings and let the user decide. -**`blocked`** — Hard blockers prevent safe removal (e.g., dependent flags, actively receiving requests, targeting is on with active rules). Present blockers — the user must resolve them first. +**`blocked`**: Hard blockers prevent safe removal (e.g., dependent flags, actively receiving requests, targeting is on with active rules). Present blockers: the user must resolve them first. ### Step 3: Determine the Forward Value @@ -78,8 +78,8 @@ Use `get-flag` to fetch the flag configuration in each critical environment. The |----------|---------------| | All critical envs ON, same fallthrough, no rules/targets | Use `fallthrough.variation` | | All critical envs OFF, same offVariation | Use `offVariation` | -| Critical envs differ in ON/OFF state | **NOT SAFE** — stop and inform the user | -| Critical envs serve different variations | **NOT SAFE** — stop and inform the user | +| Critical envs differ in ON/OFF state | **NOT SAFE**: stop and inform the user | +| Critical envs serve different variations | **NOT SAFE**: stop and inform the user | ### Step 4: Present the Cleanup Plan @@ -153,7 +153,7 @@ Before considering the job done: | Flag not found in LaunchDarkly | Inform user, check for typos in the key | | Flag already archived | Ask if code cleanup is still needed (flag is gone from LD but code may still reference it) | | Multiple SDK patterns in codebase | Search all patterns: `variation()`, `boolVariation()`, `variationDetail()`, `allFlags()`, `useFlags()`, plus any wrappers | -| Dynamic flag keys (`flag-${id}`) | Warn that automated removal may be incomplete — manual review required | +| Dynamic flag keys (`flag-${id}`) | Warn that automated removal may be incomplete: manual review required | | Different default values in code vs LD | Flag as inconsistency in the PR description | | Orphaned exports/files remain after removal | Run unused-export checks and remove dead files | @@ -162,18 +162,18 @@ Before considering the job done: - Don't change code unrelated to flag cleanup. - Don't refactor or optimize beyond flag removal. - Don't remove flags still being actively rolled out. -- Don't guess the forward value — always query LaunchDarkly. +- Don't guess the forward value: always query LaunchDarkly. ## After Cleanup Once the PR is merged and deployed: 1. **Archive the flag in LaunchDarkly** using `archive-flag`. Archival is reversible; deletion is not. Always archive first. 2. **Notify other teams** if `check-removal-readiness` reported code references in other repositories. -3. **If the flag had targeting changes pending,** they can be ignored — the flag is being removed. +3. **If the flag had targeting changes pending,** they can be ignored: the flag is being removed. ## References -- [PR Template](references/pr-template.md) — Structured PR description for flag removal -- [SDK Patterns](references/sdk-patterns.md) — Flag evaluation patterns by language/framework -- [Flag Discovery](../launchdarkly-flag-discovery/SKILL.md) — Find cleanup candidates before using this skill -- [Flag Targeting](../launchdarkly-flag-targeting/SKILL.md) — If you need to change targeting instead of removing +- [PR Template](references/pr-template.md): Structured PR description for flag removal +- [SDK Patterns](references/sdk-patterns.md): Flag evaluation patterns by language/framework +- [Flag Discovery](../launchdarkly-flag-discovery/SKILL.md): Find cleanup candidates before using this skill +- [Flag Targeting](../launchdarkly-flag-targeting/SKILL.md): If you need to change targeting instead of removing diff --git a/skills/feature-flags/launchdarkly-flag-create/README.md b/skills/feature-flags/launchdarkly-flag-create/README.md index 2e096d8..709bbc1 100644 --- a/skills/feature-flags/launchdarkly-flag-create/README.md +++ b/skills/feature-flags/launchdarkly-flag-create/README.md @@ -53,8 +53,8 @@ launchdarkly-flag-create/ ## Related -- [LaunchDarkly Flag Targeting](../launchdarkly-flag-targeting/) — Control targeting after creating a flag -- [LaunchDarkly Flag Cleanup](../launchdarkly-flag-cleanup/) — Remove flags when they're no longer needed +- [LaunchDarkly Flag Targeting](../launchdarkly-flag-targeting/): Control targeting after creating a flag +- [LaunchDarkly Flag Cleanup](../launchdarkly-flag-cleanup/): Remove flags when they're no longer needed - [LaunchDarkly MCP Server](https://github.com/launchdarkly/mcp-server) - [LaunchDarkly Docs](https://docs.launchdarkly.com) diff --git a/skills/feature-flags/launchdarkly-flag-create/SKILL.md b/skills/feature-flags/launchdarkly-flag-create/SKILL.md index f4a089f..d78c0a5 100644 --- a/skills/feature-flags/launchdarkly-flag-create/SKILL.md +++ b/skills/feature-flags/launchdarkly-flag-create/SKILL.md @@ -17,12 +17,12 @@ You're using a skill that will guide you through introducing a new feature flag This skill requires the remotely hosted LaunchDarkly MCP server to be configured in your environment. **Required MCP tools:** -- `create-flag` — create a new feature flag in a project -- `get-flag` — verify the flag was created correctly +- `create-flag`: create a new feature flag in a project +- `get-flag`: verify the flag was created correctly **Optional MCP tools (enhance workflow):** -- `list-flags` — browse existing flags to understand naming conventions and tags -- `update-flag-settings` — update flag metadata (name, description, tags, temporary/permanent status) +- `list-flags`: browse existing flags to understand naming conventions and tags +- `update-flag-settings`: update flag metadata (name, description, tags, temporary/permanent status) ## Workflow @@ -68,7 +68,7 @@ Based on what the user needs, choose the appropriate flag configuration. See [Fl **Defaults to apply:** - Set `temporary: true` unless the user explicitly says this is a permanent/long-lived flag. Most flags are release flags that should eventually be cleaned up. -- Generate a `key` from the name if not provided (e.g., "New Checkout Flow" → `new-checkout-flow`), but match the codebase's naming convention if one exists. +- Generate a `key` from the name if not provided (e.g., "New Checkout Flow" -> `new-checkout-flow`), but match the codebase's naming convention if one exists. - Suggest relevant tags based on the feature area, team, or context the user mentions. ### Step 3: Create the Flag in LaunchDarkly @@ -85,7 +85,7 @@ After creation: Now add the code to evaluate the flag, **matching the patterns you found in Step 1**. 1. **Use the same SDK patterns** the codebase already uses. If there's a wrapper, use the wrapper. If there are constants, add the new key to the constants file. -2. **Use an appropriate default value.** The default (fallback) value in code should be the "safe" behavior — typically the existing behavior before the flag. This ensures the feature stays off if the SDK can't reach LaunchDarkly. +2. **Use an appropriate default value.** The default (fallback) value in code should be the "safe" behavior: typically the existing behavior before the flag. This ensures the feature stays off if the SDK can't reach LaunchDarkly. 3. **Add the conditional logic.** Wrap the new behavior in a flag check. 4. **Handle both branches.** Make sure the code path for each variation is clear and complete. @@ -98,7 +98,7 @@ Confirm the flag is properly set up: 1. **Code compiles/passes linting.** Run the project's build or lint step. 2. **Flag exists in LaunchDarkly.** Use `get-flag` to confirm it was created with the right configuration. 3. **Both code paths work.** The flag-off path preserves existing behavior; the flag-on path enables the new feature. -4. **Default value is safe.** If LaunchDarkly is unreachable, the code falls back to the default — make sure that's the existing/safe behavior. +4. **Default value is safe.** If LaunchDarkly is unreachable, the code falls back to the default: make sure that's the existing/safe behavior. ## Updating Flag Settings @@ -126,5 +126,5 @@ Multiple instructions can be batched in a single call. These changes are project ## References -- [Flag Types and Patterns](references/flag-types.md) — Boolean vs multivariate, naming conventions, configuration best practices -- [SDK Evaluation Patterns](references/sdk-evaluation-patterns.md) — How to evaluate flags in each SDK, including common wrapper patterns +- [Flag Types and Patterns](references/flag-types.md): Boolean vs multivariate, naming conventions, configuration best practices +- [SDK Evaluation Patterns](references/sdk-evaluation-patterns.md): How to evaluate flags in each SDK, including common wrapper patterns diff --git a/skills/feature-flags/launchdarkly-flag-create/references/flag-types.md b/skills/feature-flags/launchdarkly-flag-create/references/flag-types.md index 69bb719..2d0c132 100644 --- a/skills/feature-flags/launchdarkly-flag-create/references/flag-types.md +++ b/skills/feature-flags/launchdarkly-flag-create/references/flag-types.md @@ -146,13 +146,13 @@ Tags help organize flags in LaunchDarkly. Suggest tags based on: ## Best Practices for Variations ### Boolean Flags -- Name variations: `true` → "Enabled" / "New behavior", `false` → "Disabled" / "Old behavior" +- Name variations: `true` -> "Enabled" / "New behavior", `false` -> "Disabled" / "Old behavior" - Set `offVariation` to `false` (index 1) ### Multivariate Flags - Always include a "control" or "default" variation - Give every variation a descriptive `name` -- Consider what the `offVariation` should be — typically the control/default +- Consider what the `offVariation` should be: typically the control/default - Order variations with the default/control first ### Default Values in Code diff --git a/skills/feature-flags/launchdarkly-flag-create/references/sdk-evaluation-patterns.md b/skills/feature-flags/launchdarkly-flag-create/references/sdk-evaluation-patterns.md index da17e93..8a574f2 100644 --- a/skills/feature-flags/launchdarkly-flag-create/references/sdk-evaluation-patterns.md +++ b/skills/feature-flags/launchdarkly-flag-create/references/sdk-evaluation-patterns.md @@ -192,7 +192,7 @@ When adding flag evaluation code, follow this pattern: 1. **Import/access the client** the same way existing code does 2. **Define the flag key** following the project's convention (constants file, inline, etc.) 3. **Choose the right evaluation method** based on the flag type -4. **Set a safe default value** — the behavior when LaunchDarkly is unreachable +4. **Set a safe default value**: the behavior when LaunchDarkly is unreachable 5. **Add the conditional logic** for each variation ### Example: Adding a boolean flag (Node.js) diff --git a/skills/feature-flags/launchdarkly-flag-discovery/README.md b/skills/feature-flags/launchdarkly-flag-discovery/README.md index c15c5d1..2720fc8 100644 --- a/skills/feature-flags/launchdarkly-flag-discovery/README.md +++ b/skills/feature-flags/launchdarkly-flag-discovery/README.md @@ -54,7 +54,7 @@ launchdarkly-flag-discovery/ ## Related -- [LaunchDarkly Flag Cleanup](../launchdarkly-flag-cleanup/) — Remove flags from code after discovery identifies candidates +- [LaunchDarkly Flag Cleanup](../launchdarkly-flag-cleanup/): Remove flags from code after discovery identifies candidates - [LaunchDarkly MCP Server](https://github.com/launchdarkly/mcp-server) - [LaunchDarkly Docs](https://docs.launchdarkly.com) diff --git a/skills/feature-flags/launchdarkly-flag-discovery/SKILL.md b/skills/feature-flags/launchdarkly-flag-discovery/SKILL.md index 2e75560..a30164c 100644 --- a/skills/feature-flags/launchdarkly-flag-discovery/SKILL.md +++ b/skills/feature-flags/launchdarkly-flag-discovery/SKILL.md @@ -17,14 +17,14 @@ You're using a skill that will guide you through auditing and understanding the This skill requires the remotely hosted LaunchDarkly MCP server to be configured in your environment. **Required MCP tools:** -- `list-flags` — search and browse flags with filtering by state, type, tags -- `get-flag` — get full configuration for a single flag in a specific environment -- `get-flag-status-across-envs` — check a flag's lifecycle status across all environments +- `list-flags`: search and browse flags with filtering by state, type, tags +- `get-flag`: get full configuration for a single flag in a specific environment +- `get-flag-status-across-envs`: check a flag's lifecycle status across all environments **Optional MCP tools (enhance depth):** -- `find-stale-flags` — find flags that are candidates for cleanup, sorted by staleness -- `get-flag-health` — get combined health view for a single flag (merges status + config) -- `check-removal-readiness` — detailed safety check for a specific flag +- `find-stale-flags`: find flags that are candidates for cleanup, sorted by staleness +- `get-flag-health`: get combined health view for a single flag (merges status + config) +- `check-removal-readiness`: detailed safety check for a specific flag ## Workflow @@ -44,15 +44,15 @@ Adapt your approach to the user's goal: **For a broad audit:** - Use `list-flags` scoped to a critical environment (default to `production`). -- Note the total count — this tells you the scale of the flag surface area. +- Note the total count: this tells you the scale of the flag surface area. - Filter by `state` (active, inactive, launched, new) to segment the landscape. -- Filter by `type` (temporary vs permanent) — temporary flags are the primary cleanup targets. +- Filter by `type` (temporary vs permanent): temporary flags are the primary cleanup targets. **For cleanup planning:** -- Use `find-stale-flags` — this is the most efficient entry point. It returns a prioritized list of cleanup candidates sorted by staleness, categorized as: - - `never_requested` — created but never evaluated (possibly abandoned) - - `inactive_30d` — no SDK evaluations in the specified period - - `launched_no_changes` — fully rolled out, no recent changes +- Use `find-stale-flags`: this is the most efficient entry point. It returns a prioritized list of cleanup candidates sorted by staleness, categorized as: + - `never_requested`: created but never evaluated (possibly abandoned) + - `inactive_30d`: no SDK evaluations in the specified period + - `launched_no_changes`: fully rolled out, no recent changes - Default `inactiveDays` is 30. Increase for conservative cleanup (60, 90) or decrease for aggressive cleanup (7, 14). - Default `includeOnly` is `temporary`. Set to `all` to include permanent flags. @@ -68,9 +68,9 @@ Key signals to evaluate: | Signal | What it tells you | |--------|-------------------| -| **Lifecycle state** | Where the flag is in its journey (new → active → launched → inactive) | -| **Last requested** | When an SDK last evaluated this flag — staleness indicator | -| **Targeting complexity** | Number of rules and targets — removal complexity indicator | +| **Lifecycle state** | Where the flag is in its journey (new -> active -> launched -> inactive) | +| **Last requested** | When an SDK last evaluated this flag: staleness indicator | +| **Targeting complexity** | Number of rules and targets: removal complexity indicator | | **Cross-environment consistency** | Whether the flag behaves the same everywhere | | **Flag age + temporary status** | Old temporary flags are strong cleanup candidates | @@ -80,18 +80,18 @@ Use `get-flag-status-across-envs` to check if a flag is consistent across enviro Group flags into actionable categories: -1. **Ready to remove** — Inactive everywhere, temporary, no dependencies. Direct the user to the [flag cleanup skill](../launchdarkly-flag-cleanup/SKILL.md) for code removal. -2. **Likely safe, needs verification** — Launched (fully rolled out), no rule changes recently. The user should confirm the rollout is intentionally complete. -3. **Needs investigation** — Active in some environments but not others, or has complex targeting. Don't recommend action without more context. -4. **Leave alone** — Active flags doing their job, or permanent flags that are intentionally long-lived. +1. **Ready to remove**: Inactive everywhere, temporary, no dependencies. Direct the user to the [flag cleanup skill](../launchdarkly-flag-cleanup/SKILL.md) for code removal. +2. **Likely safe, needs verification**: Launched (fully rolled out), no rule changes recently. The user should confirm the rollout is intentionally complete. +3. **Needs investigation**: Active in some environments but not others, or has complex targeting. Don't recommend action without more context. +4. **Leave alone**: Active flags doing their job, or permanent flags that are intentionally long-lived. ### Step 5: Assess Removal Readiness (When Applicable) If the user wants to know whether a specific flag can be removed, use `check-removal-readiness`. This tool orchestrates multiple API calls in parallel and returns a structured verdict: -- **`safe`** — No blockers or warnings. Proceed with cleanup. -- **`caution`** — Warnings exist (code references, expiring targets, permanent flag type). Present and let the user decide. -- **`blocked`** — Hard blockers (dependent flags, active requests, targeting rules). Must resolve first. +- **`safe`**: No blockers or warnings. Proceed with cleanup. +- **`caution`**: Warnings exist (code references, expiring targets, permanent flag type). Present and let the user decide. +- **`blocked`**: Hard blockers (dependent flags, active requests, targeting rules). Must resolve first. See [Removal Readiness Checklist](references/removal-readiness-checklist.md) for the full details on interpreting each signal. @@ -107,7 +107,7 @@ Structure your response based on what the user asked for: ## Important Context -- **"Launched" means fully rolled out** — targeting is on, a single variation is served to everyone, and no changes have been made recently. It doesn't mean "recently deployed." +- **"Launched" means fully rolled out**: targeting is on, a single variation is served to everyone, and no changes have been made recently. It doesn't mean "recently deployed." - **"Inactive" doesn't always mean safe to remove.** The flag might be used in code that hasn't shipped yet, or referenced as a prerequisite by another flag. - **Permanent flags can be inactive on purpose.** Some flags are designed to be dormant until needed (kill switches, emergency toggles). Don't automatically flag these for cleanup. - **Weights are scaled by 1000 in the API.** A weight of `60000` means 60%. Always convert to human-readable percentages. @@ -115,5 +115,5 @@ Structure your response based on what the user asked for: ## References -- [Flag Health Signals](references/flag-health-signals.md) — How to interpret lifecycle states, staleness, and health data -- [Removal Readiness Checklist](references/removal-readiness-checklist.md) — Full safety assessment before recommending flag removal +- [Flag Health Signals](references/flag-health-signals.md): How to interpret lifecycle states, staleness, and health data +- [Removal Readiness Checklist](references/removal-readiness-checklist.md): Full safety assessment before recommending flag removal diff --git a/skills/feature-flags/launchdarkly-flag-discovery/references/flag-health-signals.md b/skills/feature-flags/launchdarkly-flag-discovery/references/flag-health-signals.md index fedb6a9..bab85d5 100644 --- a/skills/feature-flags/launchdarkly-flag-discovery/references/flag-health-signals.md +++ b/skills/feature-flags/launchdarkly-flag-discovery/references/flag-health-signals.md @@ -8,9 +8,9 @@ Every flag in every environment has a lifecycle state. Here's what each one mean | State | Meaning | Action | |-------|---------|--------| -| `new` | Flag was recently created, hasn't received meaningful traffic | Leave alone — still being set up | +| `new` | Flag was recently created, hasn't received meaningful traffic | Leave alone: still being set up | | `active` | Flag is receiving SDK evaluations and serving variations | Healthy, doing its job | -| `launched` | Flag is on, serving a single variation to everyone, no recent changes | Candidate for cleanup — rollout is complete | +| `launched` | Flag is on, serving a single variation to everyone, no recent changes | Candidate for cleanup: rollout is complete | | `inactive` | Flag hasn't received SDK evaluations in a while | Strong candidate for cleanup | ## Staleness Signals @@ -29,9 +29,9 @@ The more complex a flag's targeting, the more carefully you need to assess it: | Indicator | What to check | Implications | |-----------|--------------|--------------| | **Rules count** | Number of targeting rules | More rules = more contexts depending on this flag = higher removal risk | -| **Individual targets** | Users/contexts individually targeted | Someone specifically configured these — check before removing | -| **Prerequisites** | Other flags that depend on this flag | **Hard blocker** — cannot remove without updating dependent flags | -| **Percentage rollout** | Fallthrough uses weighted variations | Flag is mid-rollout — not ready for removal | +| **Individual targets** | Users/contexts individually targeted | Someone specifically configured these: check before removing | +| **Prerequisites** | Other flags that depend on this flag | **Hard blocker**: cannot remove without updating dependent flags | +| **Percentage rollout** | Fallthrough uses weighted variations | Flag is mid-rollout: not ready for removal | ## Cross-Environment Signals @@ -40,10 +40,10 @@ Use `get-flag-status-across-envs` to build a complete picture: | Pattern | Interpretation | |---------|---------------| | Inactive everywhere | Safe to consider for removal | -| Launched everywhere | Rollout complete — candidate for code cleanup | -| Active in production, inactive in staging | Normal — production is the source of truth | -| Inactive in production, active in staging | Unusual — might be pre-release, or staging is stale | -| Mixed states across environments | Needs investigation — don't recommend action without understanding why | +| Launched everywhere | Rollout complete: candidate for code cleanup | +| Active in production, inactive in staging | Normal: production is the source of truth | +| Inactive in production, active in staging | Unusual: might be pre-release, or staging is stale | +| Mixed states across environments | Needs investigation: don't recommend action without understanding why | ## Decision Matrix @@ -53,9 +53,9 @@ Combine signals to reach a recommendation: |-----------|-------|-----|-------------|----------------| | Yes | Inactive 30+ days | Any | None | **Strong cleanup candidate** | | Yes | Launched | Any | None | **Ready to hardcode and remove** | -| Yes | Never requested, 7+ days old | Any | None | **Likely abandoned — verify and remove** | -| Yes | Active | Any | Any | **Leave alone — actively used** | -| No | Inactive 30+ days | Any | None | **Ask the user** — permanent flags may be intentionally dormant | -| No | Launched | Any | None | **Ask the user** — may want to keep as permanent config | -| Any | Any | Any | Has dependents | **Cannot remove** — update dependents first | -| Any | Active in some envs | Any | Any | **Needs investigation** — understand why states differ | +| Yes | Never requested, 7+ days old | Any | None | **Likely abandoned: verify and remove** | +| Yes | Active | Any | Any | **Leave alone: actively used** | +| No | Inactive 30+ days | Any | None | **Ask the user**: permanent flags may be intentionally dormant | +| No | Launched | Any | None | **Ask the user**: may want to keep as permanent config | +| Any | Any | Any | Has dependents | **Cannot remove**: update dependents first | +| Any | Active in some envs | Any | Any | **Needs investigation**: understand why states differ | diff --git a/skills/feature-flags/launchdarkly-flag-discovery/references/removal-readiness-checklist.md b/skills/feature-flags/launchdarkly-flag-discovery/references/removal-readiness-checklist.md index 31e6005..e00ab54 100644 --- a/skills/feature-flags/launchdarkly-flag-discovery/references/removal-readiness-checklist.md +++ b/skills/feature-flags/launchdarkly-flag-discovery/references/removal-readiness-checklist.md @@ -43,7 +43,7 @@ A systematic safety check to determine whether a feature flag can be safely remo - This flag has no prerequisites of its own (simpler removal) **Fail criteria (hard blocker):** -- Other flags depend on this flag as a prerequisite — removing it would break their targeting logic +- Other flags depend on this flag as a prerequisite: removing it would break their targeting logic ### 4. Code References @@ -53,7 +53,7 @@ A systematic safety check to determine whether a feature flag can be safely remo - No code references found, or references only exist in the current repository (about to be cleaned up) **Caution criteria:** -- Code references exist in multiple repositories — flag removal in code needs to be coordinated +- Code references exist in multiple repositories: flag removal in code needs to be coordinated **Note:** Code reference scanning has limitations. It tracks static string matches and may miss dynamic flag key construction (`flag-${name}`) or have false positives from comments/documentation. @@ -65,17 +65,17 @@ A systematic safety check to determine whether a feature flag can be safely remo - No expiring targets scheduled **Caution criteria:** -- Expiring targets exist — someone actively set a future removal date. Coordinate with them. +- Expiring targets exist: someone actively set a future removal date. Coordinate with them. ### 6. Flag Type **Check:** The `temporary` field on the flag. **Pass criteria:** -- Flag is marked as `temporary` — it was intended to be removed +- Flag is marked as `temporary`: it was intended to be removed **Caution criteria:** -- Flag is marked as `permanent` — it may be intentionally long-lived. Confirm with the user before recommending removal. +- Flag is marked as `permanent`: it may be intentionally long-lived. Confirm with the user before recommending removal. ## Readiness Levels @@ -97,14 +97,14 @@ Hard blockers prevent safe removal. - Present each blocker with specifics - For prerequisite dependencies: user must update dependent flags first - For active targeting: user should toggle off and wait for a cool-down period -- For active status: flag is still being used — don't remove +- For active status: flag is still being used: don't remove ## Presenting Results Structure the assessment as: -1. **Verdict** — Lead with safe / caution / blocked -2. **Blockers** (if any) — Each with type and actionable detail -3. **Warnings** (if any) — Each with type and context -4. **Forward value** — What variation should replace the flag in code (only if safe or caution) -5. **Next steps** — What to do now (proceed with cleanup, address warnings, resolve blockers) +1. **Verdict**: Lead with safe / caution / blocked +2. **Blockers** (if any): Each with type and actionable detail +3. **Warnings** (if any): Each with type and context +4. **Forward value**: What variation should replace the flag in code (only if safe or caution) +5. **Next steps**: What to do now (proceed with cleanup, address warnings, resolve blockers) diff --git a/skills/feature-flags/launchdarkly-flag-targeting/README.md b/skills/feature-flags/launchdarkly-flag-targeting/README.md index 6fd3ff8..84048c4 100644 --- a/skills/feature-flags/launchdarkly-flag-targeting/README.md +++ b/skills/feature-flags/launchdarkly-flag-targeting/README.md @@ -61,8 +61,8 @@ launchdarkly-flag-targeting/ ## Related -- [LaunchDarkly Flag Create](../launchdarkly-flag-create/) — Create flags before targeting them -- [LaunchDarkly Flag Discovery](../launchdarkly-flag-discovery/) — Audit flags and understand the landscape +- [LaunchDarkly Flag Create](../launchdarkly-flag-create/): Create flags before targeting them +- [LaunchDarkly Flag Discovery](../launchdarkly-flag-discovery/): Audit flags and understand the landscape - [LaunchDarkly MCP Server](https://github.com/launchdarkly/mcp-server) - [LaunchDarkly Docs](https://docs.launchdarkly.com) diff --git a/skills/feature-flags/launchdarkly-flag-targeting/SKILL.md b/skills/feature-flags/launchdarkly-flag-targeting/SKILL.md index 07f3c9d..2eec9eb 100644 --- a/skills/feature-flags/launchdarkly-flag-targeting/SKILL.md +++ b/skills/feature-flags/launchdarkly-flag-targeting/SKILL.md @@ -17,23 +17,26 @@ You're using a skill that will guide you through changing who sees what for a fe This skill requires the remotely hosted LaunchDarkly MCP server to be configured in your environment. **Required MCP tools:** -- `get-flag` — understand current state before making changes -- `toggle-flag` — turn targeting on or off for a flag in an environment -- `update-rollout` — change the default rule (fallthrough) variation or percentage rollout -- `update-targeting-rules` — add, remove, or modify custom targeting rules -- `update-individual-targets` — add or remove specific users/contexts from individual targeting +- `get-flag`: understand current state before making changes +- `toggle-flag`: turn targeting on or off for a flag in an environment +- `update-rollout`: change the default rule (fallthrough) variation or percentage rollout +- `update-targeting-rules`: add, remove, or modify custom targeting rules +- `update-individual-targets`: add or remove specific users/contexts from individual targeting **Optional MCP tools:** -- `copy-flag-config` — copy targeting configuration from one environment to another +- `copy-flag-config`: copy targeting configuration from one environment to another +- `create-approval-request`: create an approval request when direct changes are blocked +- `list-approval-requests`: check on pending approval requests for a flag +- `apply-approval-request`: apply an already-approved approval request ## Core Concept: Evaluation Order Before making any targeting changes, understand how LaunchDarkly evaluates flags. This determines what your changes actually do: -1. **Flag is OFF** → Serve the `offVariation` to everyone. Nothing else matters. -2. **Individual targets** → If the context matches a specific target list, serve that variation. Highest priority. -3. **Custom rules** → Evaluate rules top-to-bottom. First matching rule wins. -4. **Default rule (fallthrough)** → If nothing else matched, serve this variation or rollout. +1. **Flag is OFF** -> Serve the `offVariation` to everyone. Nothing else matters. +2. **Individual targets** -> If the context matches a specific target list, serve that variation. Highest priority. +3. **Custom rules** -> Evaluate rules top-to-bottom. First matching rule wins. +4. **Default rule (fallthrough)** -> If nothing else matched, serve this variation or rollout. This means: if you add a targeting rule but the flag is OFF, nobody sees the change. If you set a percentage rollout on the default rule but there's an individual target, that targeted user bypasses the rollout. @@ -45,12 +48,12 @@ Before changing anything, check what's already configured. 1. **Confirm the environment.** "Turn it on" without specifying an environment is ambiguous. Always confirm which environment the user means. Default to asking rather than assuming. 2. **Fetch the flag.** Use `get-flag` with the target environment to see: - - `on` — Is targeting currently enabled? - - `fallthrough` — What's the default rule? (variation or percentage rollout) - - `offVariation` — What serves when the flag is off? - - `rules` — Any custom targeting rules? - - `targets` — Any individually targeted users/contexts? - - `prerequisites` — Any flags this depends on? + - `on`: Is targeting currently enabled? + - `fallthrough`: What's the default rule? (variation or percentage rollout) + - `offVariation`: What serves when the flag is off? + - `rules`: Any custom targeting rules? + - `targets`: Any individually targeted users/contexts? + - `prerequisites`: Any flags this depends on? 3. **Assess complexity.** A flag with no rules and no individual targets is simple. A flag with multiple rules, targets, and prerequisites needs more care. ### Step 2: Determine the Right Approach @@ -64,7 +67,7 @@ Based on what the user wants and what you found, choose the right tool and strat | "Turn it on" | `toggle-flag` with `on: true` | Simplest change | | "Turn it off" | `toggle-flag` with `on: false` | Serves offVariation to everyone | | "Roll out to X%" | `update-rollout` with `rolloutType: "percentage"` | Weights must sum to 100 | -| "Enable for beta users" | `update-targeting-rules` — add a rule with clause | Rules are ANDed within, ORed between | +| "Enable for beta users" | `update-targeting-rules`: add a rule with clause | Rules are ANDed within, ORed between | | "Add specific users" | `update-individual-targets` | Highest priority, overrides all rules | | "Full rollout" | `update-rollout` with `rolloutType: "variation"` | Serve one variation to everyone | | "Copy from staging" | `copy-flag-config` | Promote tested config to production | @@ -74,7 +77,12 @@ Based on what the user wants and what you found, choose the right tool and strat Before applying changes, especially in production, run through the [Safety Checklist](references/safety-checklist.md). The key checks: 1. **Right environment?** Double-check you're targeting the intended environment. -2. **Approval required?** Some environments require approval workflows. If `toggle-flag` or other tools return `requiresApproval: true`, surface this to the user with the approval URL. +2. **Approval required?** Some environments require approval workflows. If any mutation tool returns `requiresApproval: true`: + - Inform the user that this environment requires approvals. + - Share the `approvalUrl` if provided. + - Offer to create an approval request using `create-approval-request` with the same instructions (returned in the `instructions` field of the response). + - Do NOT attempt to bypass approval or auto-approve. + - See [Approval Workflows](references/approval-workflows.md) for the full process. 3. **Prerequisite flags?** If this flag has prerequisites, they must be met before targeting works as expected. 4. **Rule ordering impact?** If adding rules, consider where they fall in evaluation order. Rules evaluate top-to-bottom, first match wins. 5. **Include a comment.** Always add an audit trail comment, especially for production changes. @@ -100,6 +108,16 @@ After applying changes, confirm the result: - "Beta users now see variation A. Everyone else gets the default (variation B)." 3. **Check for side effects.** If there are rules or individual targets, make sure the change interacts correctly with them. +### Handling Approval-Required Environments + +When any mutation tool returns `requiresApproval: true`, the direct change was blocked because the environment requires approvals. Follow the [Approval Workflows](references/approval-workflows.md) reference to: + +1. **Create an approval request** with `create-approval-request` using the `instructions` from the blocked response +2. **Inform the user** about the pending approval and share the approval request details +3. **Check on approval status** later with `list-approval-requests` if requested +4. **Apply the request** with `apply-approval-request` once a reviewer has approved it (reviewStatus is "approved") +5. **Verify the result** with `get-flag` after applying + ## Important Context - **`update-rollout` uses human-friendly percentages.** Pass 80 for 80%, not 80000. The tool handles the internal weight conversion. @@ -110,5 +128,6 @@ After applying changes, confirm the result: ## References -- [Targeting Patterns](references/targeting-patterns.md) — Rollout strategies, rule construction, individual targeting, and cross-environment copying -- [Safety Checklist](references/safety-checklist.md) — Pre-change verification, approval workflows, environment awareness +- [Targeting Patterns](references/targeting-patterns.md): Rollout strategies, rule construction, individual targeting, and cross-environment copying +- [Safety Checklist](references/safety-checklist.md): Pre-change verification, approval workflows, environment awareness +- [Approval Workflows](references/approval-workflows.md): Creating, checking, and applying approval requests diff --git a/skills/feature-flags/launchdarkly-flag-targeting/marketplace.json b/skills/feature-flags/launchdarkly-flag-targeting/marketplace.json index 39d46cf..1b123a6 100644 --- a/skills/feature-flags/launchdarkly-flag-targeting/marketplace.json +++ b/skills/feature-flags/launchdarkly-flag-targeting/marketplace.json @@ -1,6 +1,6 @@ { "name": "launchdarkly-flag-targeting", - "description": "Control LaunchDarkly feature flag targeting including toggling, rollouts, rules, individual targets, and cross-environment copying", + "description": "Control LaunchDarkly feature flag targeting including toggling, rollouts, rules, individual targets, cross-environment copying, and approval workflows", "version": "1.0.0-experimental", "author": "LaunchDarkly", "repository": "https://github.com/launchdarkly/agent-skills", diff --git a/skills/feature-flags/launchdarkly-flag-targeting/references/approval-workflows.md b/skills/feature-flags/launchdarkly-flag-targeting/references/approval-workflows.md new file mode 100644 index 0000000..ca88f03 --- /dev/null +++ b/skills/feature-flags/launchdarkly-flag-targeting/references/approval-workflows.md @@ -0,0 +1,116 @@ +# Approval Workflows + +Some LaunchDarkly environments require approval before changes take effect. This is an Enterprise feature configured per environment. When this happens, mutation tools like `toggle-flag`, `update-rollout`, `update-targeting-rules`, `update-individual-targets`, and `copy-flag-config` return `requiresApproval: true` instead of making the change directly. + +## Detecting Approval Requirements + +Any mutation tool response may include these fields when a change is blocked: + +- `requiresApproval: true`: the change was blocked and needs approval +- `approvalUrl`: a URL where the approval can be reviewed (if available) +- `message`: a human-readable explanation +- `instructions`: the semantic patch instructions that were attempted (use these to create an approval request) + +## Creating an Approval Request + +When a change is blocked, use `create-approval-request` to submit the change for review: + +1. Use the **same instructions** returned in the blocked response's `instructions` field +2. Provide a clear `description` explaining what the change does and why +3. Optionally notify specific team members (`notifyMemberIds`) or teams (`notifyTeamKeys`) + +### Example: Toggle flag with approval + +If `toggle-flag` returns `requiresApproval: true`: + +``` +Tool: create-approval-request +Input: + projectKey: "my-project" + flagKey: "new-checkout" + env: "production" + instructions: [{"kind": "turnFlagOn"}] + description: "Enable new checkout flow in production after successful staging test" +``` + +### Example: Rollout with approval + +If `update-rollout` returns `requiresApproval: true` with instructions: + +``` +Tool: create-approval-request +Input: + projectKey: "my-project" + flagKey: "new-checkout" + env: "production" + instructions: [{"kind": "updateFallthroughVariationOrRollout", "rolloutWeights": {"var-id-1": 25000, "var-id-2": 75000}}] + description: "Roll out new checkout to 25% of users in production" +``` + +### Example: Targeting rule with approval + +If `update-targeting-rules` returns `requiresApproval: true`: + +``` +Tool: create-approval-request +Input: + projectKey: "my-project" + flagKey: "new-checkout" + env: "production" + instructions: [{"kind": "addRule", "clauses": [{"contextKind": "user", "attribute": "email", "op": "endsWith", "values": ["@company.com"]}], "variationId": "", "description": "Internal users"}] + description: "Add targeting rule for internal users in production" +``` + +## Checking Approval Status + +Use `list-approval-requests` to see pending requests for a flag: + +``` +Tool: list-approval-requests +Input: + projectKey: "my-project" + flagKey: "new-checkout" + env: "production" +``` + +The response shows: +- `status`: pending, completed, or failed +- `reviewStatus`: pending, approved, or declined +- `reviews`: list of reviewer actions with status and comments +- `description`: what the change does +- `instructionCount`: number of instructions in the request + +## Applying Approved Requests + +Once a reviewer approves the request (`reviewStatus` is `"approved"`), use `apply-approval-request`: + +``` +Tool: apply-approval-request +Input: + projectKey: "my-project" + id: "" + comment: "Applying approved production rollout" +``` + +After applying, verify the change with `get-flag`. + +**Important:** The agent can apply already-approved requests but must NEVER approve requests itself. Approval is a human decision. + +## What the Agent Should NOT Do + +- **Do NOT auto-approve**: The purpose of approvals is human oversight. Never try to approve a request. +- **Do NOT retry the direct change**: If a change was blocked, retrying the same mutation will also be blocked. Use the approval workflow. +- **Do NOT skip informing the user**: Always tell the user that approval is required and what the next steps are. +- **Do NOT bypass approval**: Never use workarounds or alternative API calls to skip the approval process. + +## Typical Flow + +1. User asks for a targeting change (e.g., "turn on the flag in production") +2. Agent attempts the change using the mutation tool +3. Tool returns `requiresApproval: true` with `instructions` +4. Agent informs the user and offers to create an approval request +5. If the user agrees, agent creates the request with `create-approval-request` +6. Agent shares the approval request details (ID, approval URL if available) +7. A human reviewer approves or declines the request (outside the agent) +8. If approved, the user or agent can apply it with `apply-approval-request` +9. Agent verifies the change with `get-flag` diff --git a/skills/feature-flags/launchdarkly-flag-targeting/references/safety-checklist.md b/skills/feature-flags/launchdarkly-flag-targeting/references/safety-checklist.md index 3c768c6..138f8fd 100644 --- a/skills/feature-flags/launchdarkly-flag-targeting/references/safety-checklist.md +++ b/skills/feature-flags/launchdarkly-flag-targeting/references/safety-checklist.md @@ -24,9 +24,15 @@ Run through this checklist before applying any targeting changes, especially in Some environments require approval for changes. -- [ ] If the API returns `requiresApproval: true`, inform the user -- [ ] Provide the approval URL so they can follow the workflow -- [ ] Do NOT attempt to bypass approval +- [ ] If any mutation tool returns `requiresApproval: true`, inform the user +- [ ] Provide the approval URL if one was returned +- [ ] Offer to create an approval request with `create-approval-request` using the returned `instructions` +- [ ] Include a clear description of the intended change in the approval request +- [ ] Do NOT attempt to bypass approval or auto-approve +- [ ] If checking on a previous request, use `list-approval-requests` +- [ ] Only apply a request (`apply-approval-request`) if reviewStatus is "approved" + +See [Approval Workflows](approval-workflows.md) for the complete reference. ### 5. Audit Trail @@ -52,7 +58,7 @@ Some environments require approval for changes. - [ ] The values match exactly what the SDK sends as the user/context key - [ ] Individual targets are intended to override rules (they always win) -- [ ] Using `replaceTargets` intentionally — it replaces ALL targets, not just adds +- [ ] Using `replaceTargets` intentionally: it replaces ALL targets, not just adds ## For Cross-Environment Copies diff --git a/skills/feature-flags/launchdarkly-flag-targeting/references/targeting-patterns.md b/skills/feature-flags/launchdarkly-flag-targeting/references/targeting-patterns.md index 78e3a83..1213e03 100644 --- a/skills/feature-flags/launchdarkly-flag-targeting/references/targeting-patterns.md +++ b/skills/feature-flags/launchdarkly-flag-targeting/references/targeting-patterns.md @@ -16,7 +16,7 @@ The simplest targeting change. **Notes:** - Turning a flag OFF makes it serve the `offVariation` to everyone, regardless of rules or targets. -- Turning a flag ON activates the full targeting evaluation (individual targets → rules → default rule). +- Turning a flag ON activates the full targeting evaluation (individual targets -> rules -> default rule). ## Percentage Rollouts (Default Rule) @@ -178,7 +178,7 @@ The `ruleId` (also shown as `_id`) can be found in the flag's current configurat } ``` -Rule order matters — rules evaluate top to bottom, first match wins. +Rule order matters: rules evaluate top to bottom, first match wins. ### Update a rule's variation @@ -217,7 +217,7 @@ Rule order matters — rules evaluate top to bottom, first match wins. ## Individual Targets -Individual targets are the highest priority — they override all rules. +Individual targets are the highest priority: they override all rules. ### Add users to a variation @@ -316,4 +316,4 @@ Multiple instructions can be batched. For example, turning on and setting a roll } ``` -This is preferred over multiple separate calls — it's atomic (all changes apply together or none do). +This is preferred over multiple separate calls: it's atomic (all changes apply together or none do). diff --git a/template/SKILL.md.template b/template/SKILL.md.template index 52aadbd..81635d9 100644 --- a/template/SKILL.md.template +++ b/template/SKILL.md.template @@ -74,5 +74,5 @@ Confirm the job was done correctly: ## References -- [Reference 1](references/reference-1.md) — Description -- [Reference 2](references/reference-2.md) — Description +- [Reference 1](references/reference-1.md): Description +- [Reference 2](references/reference-2.md): Description