Skip to main content
Glama
canopy-labs

Featureflip

Official

Wrap a feature in a new flag

wrap_feature

Create a Boolean feature flag and get an SDK code snippet to guard a new code path. The flag starts disabled; enable it when ready.

Instructions

Create a Boolean feature flag and get back the SDK code snippet to guard the new code path with it. Returns the snippet only — apply the edit yourself. The flag starts DISABLED in every environment; enable it with toggle_flag when ready.

Input Schema

NameRequiredDescriptionDefault
keyYesFlag key, e.g. new-checkout
nameNoDisplay name; defaults to the key
tagsNoTags for filtering, e.g. team or area
projectYesProject key
languageYesSDK language of the codebase being edited
descriptionNoWhat this flag guards
idempotency_keyNoIdempotency-Key header for safe retries

Output Schema

NameRequiredDescriptionDefault
flagYes
next_stepsYes
integrationYes

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed3 schema fields changedv0.3.0
    • addedInput schema / properties / idempotency_key / description
      Added value: +"Idempotency-Key header for safe retries"
    • addedInput schema / properties / tags / description
      Added value: +"Tags for filtering, e.g. team or area"
    • changedOutput schema / (root)
      Previous value: -nullNew value: +{
      +  "$defs": {
      +    "ActionCapability": {
      +      "description": "One entry in a resource's `_actions` block: may the caller perform it, and if not, why.",
      +      "properties": {
      +        "allowed": {
      +          "type": [
      +            "boolean",
      +            "null"
      +          ]
      +        },
      +        "reason": {
      +          "type": [
      +            "string",
      +            "null"
      +          ]
      +        }
      +      },
      +      "type": [
      +        "object",
      +        "null"
      +      ]
      +    },
      +    "PublicFlagOwner": {
      +      "description": "A flag's owner as returned on flag reads. Null means the flag is unowned.",
      +      "properties": {
      +        "email": {
      +          "type": [
      +            "string",
      +            "null"
      +          ]
      +        },
      +        "id": {
      +          "type": [
      +            "string",
      +            "null"
      +          ]
      +        },
      +        "name": {
      +          "type": [
      +            "string",
      +            "null"
      +          ]
      +        }
      +      },
      +      "type": [
      +        "object",
      +        "null"
      +      ]
      +    },
      +    "PublicFlagResponse": {
      +      "description": "Public detail representation of a feature flag, returned by\n`GET .../flags/{flag}` and the body of a successful create. Drops internal/dashboard-only\nfields present on FeatureFlagDto — notably `ProjectId` (implicit in the\nroute) and `Staleness` (an internal analytics signal, not part of the public contract).\nEffectiveExpiresAtUtc is when the flag counts as past expiry, from its own ExpiresAtUtc\nor its project's default lifetime; ExpirySource says which (`explicit` / `project-default`),\nboth null when neither applies.",
      +      "properties": {
      +        "_actions": {
      +          "additionalProperties": {
      +            "anyOf": [
      +              {
      +                "$ref": "#/$defs/ActionCapability"
      +              },
      +              {
      +                "type": "null"
      +              }
      +            ]
      +          },
      +          "description": "Capability hints: which operations the authenticated caller may perform on this resource, each with allowed + optional reason. Computed from the caller's role and the resource's state. Injected at runtime; safe to ignore. Present only on top-level resource responses — nested occurrences (e.g. a rule inside a targeting-config response) do not carry it.",
      +          "type": [
      +            "object",
      +            "null"
      +          ]
      +        },
      +        "clientSideVisible": {
      +          "type": [
      +            "boolean",
      +            "null"
      +          ]
      +        },
      +        "createdAt": {
      +          "type": [
      +            "string",
      +            "null"
      +          ]
      +        },
      +        "description": {
      +          "type": [
      +            "string",
      +            "null"
      +          ]
      +        },
      +        "effectiveExpiresAtUtc": {
      +          "type": [
      +            "string",
      +            "null"
      +          ]
      +        },
      +        "expiresAtUtc": {
      +          "type": [
      +            "string",
      +            "null"
      +          ]
      +        },
      +        "expirySource": {
      +          "type": [
      +            "string",
      +            "null"
      +          ]
      +        },
      +        "id": {
      +          "type": [
      +            "string",
      +            "null"
      +          ]
      +        },
      +        "isArchived": {
      +          "type": [
      +            "boolean",
      +            "null"
      +          ]
      +        },
      +        "isPermanent": {
      +          "type": [
      +            "boolean",
      +            "null"
      +          ]
      +        },
      +        "key": {
      +          "type": [
      +            "string",
      +            "null"
      +          ]
      +        },
      +        "name": {
      +          "type": [
      +            "string",
      +            "null"
      +          ]
      +        },
      +        "owner": {
      +          "anyOf": [
      +            {
      +              "$ref": "#/$defs/PublicFlagOwner"
      +            },
      +            {
      +              "type": "null"
      +            }
      +          ]
      +        },
      +        "removalPrUrl": {
      +          "type": [
      +            "string",
      +            "null"
      +          ]
      +        },
      +        "tags": {
      +          "items": {
      +            "type": [
      +              "string",
      +              "null"
      +            ]
      +          },
      +          "type": [
      +            "array",
      +            "null"
      +          ]
      +        },
      +        "type": {
      +          "description": "Allowed values: Boolean, String, Number, Json.",
      +          "type": [
      +            "string",
      +            "null"
      +          ]
      +        },
      +        "updatedAt": {
      +          "type": [
      +            "string",
      +            "null"
      +          ]
      +        },
      +        "variations": {
      +          "items": {
      +            "anyOf": [
      +              {
      +                "$ref": "#/$defs/PublicVariationResponse"
      +              },
      +              {
      +                "type": "null"
      +              }
      +            ]
      +          },
      +          "type": [
      +            "array",
      +            "null"
      +          ]
      +        }
      +      },
      +      "type": [
      +        "object",
      +        "null"
      +      ]
      +    },
      +    "PublicVariationResponse": {
      +      "description": "A single variation on a flag, as returned in Variations.",
      +      "properties": {
      +        "_actions": {
      +          "additionalProperties": {
      +            "anyOf": [
      +              {
      +                "$ref": "#/$defs/ActionCapability"
      +              },
      +              {
      +                "type": "null"
      +              }
      +            ]
      +          },
      +          "description": "Capability hints: which operations the authenticated caller may perform on this resource, each with allowed + optional reason. Computed from the caller's role and the resource's state. Injected at runtime; safe to ignore. Present only on top-level resource responses — nested occurrences (e.g. a rule inside a targeting-config response) do not carry it.",
      +          "type": [
      +            "object",
      +            "null"
      +          ]
      +        },
      +        "description": {
      +          "type": [
      +            "string",
      +            "null"
      +          ]
      +        },
      +        "id": {
      +          "type": [
      +            "string",
      +            "null"
      +          ]
      +        },
      +        "key": {
      +          "type": [
      +            "string",
      +            "null"
      +          ]
      +        },
      +        "name": {
      +          "type": [
      +            "string",
      +            "null"
      +          ]
      +        },
      +        "value": {
      +          "type": [
      +            "string",
      +            "null"
      +          ]
      +        }
      +      },
      +      "type": [
      +        "object",
      +        "null"
      +      ]
      +    }
      +  },
      +  "properties": {
      +    "flag": {
      +      "$ref": "#/$defs/PublicFlagResponse"
      +    },
      +    "integration": {
      +      "properties": {
      +        "code": {
      +          "type": "string"
      +        },
      +        "install": {
      +          "type": "string"
      +        },
      +        "language": {
      +          "type": "string"
      +        },
      +        "notes": {
      +          "type": "string"
      +        }
      +      },
      +      "type": "object"
      +    },
      +    "next_steps": {
      +      "items": {
      +        "type": "string"
      +      },
      +      "type": "array"
      +    }
      +  },
      +  "required": [
      +    "flag",
      +    "integration",
      +    "next_steps"
      +  ],
      +  "type": "object"
      +}
  2. First observedv0.1.6

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only supply destructiveHint=false, so the description carries most of the burden and does well: it discloses that the tool does not edit code ('apply the edit yourself') and that the new flag defaults to DISABLED in every environment. It omits retry/auth behavior and the significance of the idempotency_key parameter, but the state and scope disclosures are genuinely useful.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences, front-loaded with the primary action and result, followed by the non-obvious constraint (snippet only) and the lifecycle default. Every sentence adds distinct information with no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so the snippet return value needn't be described. Combined with full schema coverage, the description's coverage of scope (no code edit), default state (disabled everywhere), and next step (toggle_flag) makes it complete for this tool's complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% with 7 well-documented parameters, so the schema does the heavy lifting. The description adds no parameter-level meaning such as expected key format or language implications, making 3 the correct baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb+resource pair (create a Boolean feature flag) plus the distinctive side effect (return an SDK snippet for guarding a code path). It implicitly differentiates itself from the plain create_flag sibling by noting the snippet return, but never names that sibling or contrasts the two explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives clear context for when this tool fits — wrapping a new code path — and names the natural follow-up tool (toggle_flag) with the condition 'when ready.' It stops short of stating when to prefer the sibling create_flag instead, so the routing guidance is incomplete rather than explicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.