Skip to main content

Feature toggles beat hard-coded agent IDs

· 6 min read
Sai Prudhvi Neelakantam
Senior Consultant, Data Engineering & AI at Evidi

Multi-agent shells rot when every new assistant becomes an if-else on agent ids. Microcopy forks. Export prefixes fork. Access checks fork. Soon the SPA is a customer-specific catalog pretending to be a product.

Default-open with overlays. Product feature flags gate shared UX. Per-agent overlay rows carry scope, starters, export prefixes, and access arrays. The SPA never parses JWTs to invent policy. White-label cores stay clean because domain agents are data, not code forks. Test matrices expand by flag, not by customer branch.

Feature flag configuration explorer in Azure App Configuration

Figure 1. Shared shell UX is a product feature. Agent differences belong in overlay flags the API already authorizes. Source: Microsoft Learn: manage feature flags.

Create a feature flag switch in Azure App Configuration

Figure 2. Feature flags gate surfaces. App roles still decide what the catalog may show. The SPA should not invent policy from JWTs. Source: Microsoft Learn: manage feature flags.

I learned this while watching agent catalogs grow faster than the shared UX could absorb. Each "quick" special case for one assistant taught the next engineer that hard-coding was normal. Feature flags plus overlay rows restored a single shell with many agents.

The core idea

Shared behavior is a product feature. Agent differences are overlay data under that feature.

If starters, export names, and access arrays live in code beside agent ids, every tenant wants a fork. If they live in overlay rows gated by flags, the core stays boring and the catalog stays honest. Authorization still belongs on the API; overlays describe what the API already allows the shell to show.

A model that stays explainable

1. Default-open shared UX behind flags

Chat layout, citation drawers, export affordances, and follow-up chips are product features. Gate them with flags so you can disable a surface without deleting an agent. Flags are for product posture, not for encoding tenant politics in React.

2. Overlay rows per agent, not per customer fork

Each agent row can carry scope labels, starter prompts, export prefixes, and access arrays. Customer variation should select which rows are loaded, not rewrite the shell. Overlays scale; forks multiply support.

3. Access arrays without JWT archaeology in the SPA

The catalog API returns what this caller may see. The SPA renders that list. Decoding roles in the browser to filter hard-coded ids duplicates policy and drifts. One access payload beats three copies of role strings.

4. Microcopy stays under parent toggles

Tone and helper text for a feature belong with the feature flag, not scattered beside agent ids. Otherwise you fix a typo in four branches and miss the fifth. Parent toggles keep copy reviewable.

5. White-label cores stay free of domain agents

Domain packs arrive as data and config. The core repo should not need a pull request every time a specialist agent is added for one tenant. If the core PR list is mostly agent ids, you inverted the architecture.

6. Expand tests by flag matrix

Test general-only, specialized-only, flag-off, and flag-on. Do not maintain a test suite per customer fork. When a flag changes default, CI should tell you before a demo does.

Failure modes I design against

If-else catalogs. Every agent id teaches a new special case.

JWT parsing in React. Policy drifts from the API.

Copy forks. Same feature, five wordings, no owner.

Tenant branches. White-label becomes many apps.

Flag soup without owners. Nobody knows what "true" means in Prod.

Tests per customer. Velocity dies; fear of merge rises.

How overlays and authZ stay friends

Overlays are not a second authorization system. They decorate an already authorized catalog. If an access array on a row disagrees with the API role check, the API wins and the row is wrong. Build a validator that fails CI when overlay access claims exceed what roles can grant. Configuration that over-promises is a security bug with a friendly JSON face.

Migration from hard-coded ids

Inventory every branch on agent id. Classify each as product feature, overlay field, or true one-off that should be a flag. Move fields into rows. Replace branches with flag checks. Delete dead id lists. Keep a short ADR so the next engineer does not reintroduce "just one if" for a VIP agent. VIP agents are still rows.

Operability for on-call

When a starter prompt is wrong, on-call should edit overlay data or a flagged config, not ship a shell hotfix. When a feature misbehaves for everyone, flip the parent flag. Separate those runbooks. Mixing "fix one agent" with "disable citations globally" in the same panic path is how you take down the wrong surface.

Trade-offs

Flags and overlays add configuration surface. Hard-coded ids feel faster for the first three agents and collapse at thirty. API-driven catalogs need contract tests; browser-side role parsing needs tribal knowledge. Flag ownership and naming discipline are mandatory; unnamed flags become landmines. A clean core with overlays takes packaging work up front and removes fork tax forever after.

What I would put on an ADR

  1. Shared shell UX is gated by product feature flags, not by agent id branches.
  2. Per-agent overlays carry scope, starters, export prefixes, and access arrays as data.
  3. SPA consumes authorized catalog payloads; no JWT role parsing for agent visibility.
  4. Domain agents ship as packs/config; core stays free of tenant agent hard-coding.
  5. CI expands by flag and role matrix, not by customer fork.
  6. Overlay access claims are validated against API authorization rules.

Primary references: Azure App Configuration feature flag guidance and your Foundry/agent catalog API contracts on Microsoft Learn where applicable. Pair product flag docs with the authorization ADR so toggles never become a backdoor.

Closing

Hard-coded agent ids are a short-term kindness and a long-term fork machine.

Gate shared UX with flags. Describe agents as overlays. Keep policy on the API. Test the matrix. The shell should feel like one product even when the catalog is many specialists.