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

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 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 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 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
  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:

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 exports a global singleton as flags (re-exported via packages/agent-core/src/flags/index.ts). Import using:

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:

{
  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:

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

Optionally enable via config.toml:

[experimental]
my_new_feature = true

Or force-enable all experimental features via environment variable:

export KIMI_CODE_EXPERIMENTAL_FLAG=1

Key Files in the Flag System

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 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. 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. 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →