# How Experimental Features Are Gated Behind Flags in Kimi-Code: Architecture and Implementation Guide

> Discover how Kimi-Code gates experimental features using a hierarchical flag system. Learn about its architecture and implementation for runtime feature availability.

- Repository: [Moonshot AI/kimi-code](https://github.com/MoonshotAI/kimi-code)
- Tags: architecture
- Published: 2026-07-25

---

**Kimi-code gates experimental features behind a hierarchical flag system located in `packages/agent-core/src/flags` that evaluates environment variables, config files, and registry defaults to determine runtime feature availability.**

Kimi-code implements a self-contained flag system to safely roll out experimental functionality without impacting production users. Understanding how experimental features are gated behind flags in kimi-code helps developers enable cutting-edge capabilities while maintaining stability. The system relies on three core components housed in the `packages/agent-core/src/flags` directory: a registry of definitions, TypeScript type safety, and a synchronous resolver.

## Architecture of the Experimental Flag System

### Flag Definitions in the Registry

The `FLAG_DEFINITIONS` constant in [`packages/agent-core/src/flags/registry.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core/src/flags/registry.ts) serves as the single source of truth for all experimental features. Each entry includes an `id`, `title`, `description`, `env` variable name, `default` boolean state, and `surface` designation indicating UI visibility. The `as const satisfies` assertion automatically derives the literal `FlagId` union, giving compile-time safety when referencing flags throughout the codebase.

### Type Safety with Flag Types

The [`packages/agent-core/src/flags/types.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core/src/flags/types.ts) file defines TypeScript interfaces for flag metadata and resolved states. It exports the `FlagId` union type derived from registry keys, providing compile-time autocomplete and preventing invalid flag references. This ensures that only defined experimental features can be queried via the resolver API.

### The Flag Resolver Logic

[`packages/agent-core/src/flags/resolver.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core/src/flags/resolver.ts) implements the `FlagResolver` class, a pure synchronous evaluator that determines feature availability. The resolver exposes three key methods:

- **`enabled(id)`**: Returns boolean state for a given flag ID (lines 39-41)
- **`explain(id)`**: Details the resolution path and precedence (lines 47-53)
- **`snapshot()`**: Captures current state of all flags for debugging

## Flag Resolution Precedence and Priority

The resolver evaluates experimental feature flags in strict precedence order according to the logic in `FlagResolver.explain`:

1. **Master switch** (`KIMI_CODE_EXPERIMENTAL_FLAG`): When truthy, forces all experimental flags to the enabled state (highest precedence)
2. **Per-feature environment variables**: Individual flag env vars like `KIMI_CODE_EXPERIMENTAL_TOOL_SELECT` override defaults and the master switch
3. **Config file overrides**: Boolean values in the `[experimental]` section of [`config.toml`](https://github.com/MoonshotAI/kimi-code/blob/main/config.toml)
4. **Registry defaults**: The `default` field from `FLAG_DEFINITIONS` when no override exists

## Accessing the Flag Resolver in Code

### Scoped Resolver Instances

Every `KimiCore`, `Session`, and `Agent` instance exposes a scoped resolver through the `flags` property. Access features within these contexts using:

```typescript
if (this.flags.enabled('tool-select')) {
  // Execute experimental tool selection logic
  await this.experimentalToolSelection();
} else {
  // Maintain stable behavior
  await this.standardToolSelection();
}

```

### Global Singleton Access

For code outside scoped instances, [`packages/agent-core/src/flags/resolver.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core/src/flags/resolver.ts) exports a global singleton as `flags` (re-exported via [`packages/agent-core/src/flags/index.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core/src/flags/index.ts)). Import using:

```typescript
import { flags } from '#/flags';

if (flags.enabled('my-feature')) {
  // Handle experimental path
}

```

## Adding a New Experimental Flag

To gate a new capability behind the flag system, follow these steps:

First, define the flag in [`packages/agent-core/src/flags/registry.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core/src/flags/registry.ts):

```typescript
{
  id: 'my_new_feature',
  title: 'My New Feature',
  description: 'A brief description of the experimental capability.',
  env: 'KIMI_CODE_EXPERIMENTAL_MY_NEW_FEATURE',
  default: false,
  surface: 'both',
},

```

Then check the flag at runtime within an Agent, Session, or KimiCore:

```typescript
if (this.flags.enabled('my_new_feature')) {
  await this.performNewFeatureLogic();
} else {
  await this.performLegacyLogic();
}

```

Optionally enable via [`config.toml`](https://github.com/MoonshotAI/kimi-code/blob/main/config.toml):

```toml
[experimental]
my_new_feature = true

```

Or force-enable all experimental features via environment variable:

```bash
export KIMI_CODE_EXPERIMENTAL_FLAG=1

```

## Key Files in the Flag System

- **[`packages/agent-core/src/flags/registry.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core/src/flags/registry.ts)**: Catalog of all experimental flags and metadata; the single source of truth
- **[`packages/agent-core/src/flags/resolver.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core/src/flags/resolver.ts)**: Resolution algorithm and public API (`enabled`, `explain`, `snapshot`)
- **[`packages/agent-core/src/flags/types.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core/src/flags/types.ts)**: TypeScript interfaces and `FlagId` union type definitions
- **[`packages/agent-core/src/flags/index.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core/src/flags/index.ts)**: Public entry point exporting the global resolver singleton

## Summary

- Kimi-code gates experimental features through a centralized system in `packages/agent-core/src/flags` with three core components: registry, types, and resolver
- The `FlagResolver` class evaluates flags using strict precedence: master env switch → per-feature env vars → [`config.toml`](https://github.com/MoonshotAI/kimi-code/blob/main/config.toml) overrides → registry defaults
- Type safety is enforced through the `FlagId` union type generated from `FLAG_DEFINITIONS` using `as const satisfies`
- Both scoped instances (on `Agent`, `Session`, `KimiCore`) and a global singleton provide access to `flags.enabled()` for checking experimental status
- New features require only a registry entry and runtime check to implement safe, reversible rollouts

## Frequently Asked Questions

### What is the fastest way to enable all experimental features in kimi-code?

Set the `KIMI_CODE_EXPERIMENTAL_FLAG` environment variable to any truthy value before starting the application. This master switch overrides all individual flag defaults and forces every experimental feature to the enabled state, regardless of their registry defaults or config file settings.

### Can individual experimental flags be disabled after enabling the master switch?

Yes. The per-feature environment variable takes precedence over the master switch. Even with `KIMI_CODE_EXPERIMENTAL_FLAG=1`, setting a specific flag's env var like `KIMI_CODE_EXPERIMENTAL_TOOL_SELECT=false` will disable that particular feature while keeping others enabled, following the resolution order defined in `FlagResolver.explain`.

### Where should developers define new experimental flags?

Add new flag definitions to the `FLAG_DEFINITIONS` array in [`packages/agent-core/src/flags/registry.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core/src/flags/registry.ts). Each entry must include a unique `id`, an `env` name prefixed with `KIMI_CODE_EXPERIMENTAL_`, and a boolean `default` value. The TypeScript compiler automatically updates the `FlagId` union to include the new flag identifier.

### How does the flag system handle type safety?

The `FlagId` union type is automatically derived from the `FLAG_DEFINITIONS` array using TypeScript's `as const satisfies` assertion in [`registry.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/registry.ts). This provides compile-time checking and IDE autocomplete when calling `flags.enabled()`, preventing references to undefined flags and ensuring that only registered experimental features can be queried.