AGENTS.md@meta/feature-flags · git:20260713.866aced · 2026-07-13 · sha256 e4618e34ba13cb17

AGENTS.md@meta/feature-flags git:20260713.866acedA

Immutable. This exact content is served forever at /api/v1/blob/e4618e34ba13cb17.

# Feature Flags — Agent Instructions

## Naming Convention

Feature flag keys are **simple kebab-case strings** with no prefix or suffix:

```
"browser"
"a2a-channel"
"voice-mode"
"conversation-starters"
```

The `id` and `key` fields in `feature-flag-registry.json` **must match** and both use kebab-case. client-scope flags follow the same convention:

```
"user-hosted-enabled"
"quick-input"
"expand-completed-steps"
```

**Do not** use a `feature_flags.` prefix, `.enabled` suffix, or snake_case. The old canonical format (`feature_flags.<id>.enabled` / `snake_case_key`) is being retired.

## Adding a New Flag

1. Add an entry to `meta/feature-flags/feature-flag-registry.json` with matching `id` and `key`:

   ```json
   {
     "id": "my-new-flag",
     "scope": "assistant",
     "key": "my-new-flag",
     "label": "My New Flag",
     "description": "What this flag controls",
     "defaultEnabled": false
   }
   ```

   Use `"defaultEnabled": false` for new gated features unless the feature is intentionally GA. Locally declared flags that are missing from a remote platform snapshot fall back to this registry default; undeclared flags fail closed.

2. Run the sync script to copy the registry into bundled locations:

   ```bash
   bun run meta/sync-bundled-copies.ts
   ```

3. **Create the flag via Terraform in `vellum-assistant-platform`** so it exists on the platform for remote sync.

## Creating a Feature Gate

Define a constant using the flag's `id` directly and a predicate function that delegates to the resolver:

```typescript
import { isAssistantFeatureFlagEnabled } from "../config/assistant-feature-flags.js";
import type { AssistantConfig } from "../config/schema.js";

const MY_FLAG = "my-flag" as const;

export function isMyFlagEnabled(config: AssistantConfig): boolean {
  return isAssistantFeatureFlagEnabled(MY_FLAG, config);
}
```

## Skill Feature-Flag Gating

A skill's SKILL.md frontmatter `featureFlag` field should reference the flag `id` directly:

```yaml
featureFlag: my-new-flag
```

Skills without a `featureFlag` field are always available. Skills that declare one are gated at six independent enforcement points — when the flag is OFF the skill is unavailable everywhere.

## Auth Scopes Are Unrelated

The OAuth/API scopes `feature_flags.read` and `feature_flags.write` control access to the feature-flag management API. They are **not** flag keys and should not be modified when adding or renaming flags.