# How Kosong's Provider Abstraction Layer Handles Multiple LLM Providers in Kimi Code

> Discover how Kosong's provider abstraction layer unifies multiple LLM backends via a single ChatProvider interface and provider-specific adapters, simplifying integration within Kimi Code.

- Repository: [Moonshot AI/kimi-code](https://github.com/MoonshotAI/kimi-code)
- Tags: internals
- Published: 2026-08-16

---

**Kosong unifies multiple LLM backends through a single `ChatProvider` interface, with provider-specific adapters registered in a static lookup table at [`packages/kosong/src/providers/index.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/kosong/src/providers/index.ts).**

The Kosong provider abstraction layer is the architectural backbone of MoonshotAI's Kimi Code, enabling seamless switching between OpenAI, Anthropic, Google GenAI, Kimi, and other LLM services without changing application code. This article examines the three-layer design—unified interface, provider adapters, and factory registry—that makes this polymorphism possible.

## Unified Provider Interface: The `ChatProvider` Contract

At the center of the Kosong provider abstraction layer sits the `ChatProvider` interface defined in [`packages/kosong/src/provider.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/kosong/src/provider.ts). This contract establishes the common vocabulary that every LLM backend must implement:

- **Core methods**: `generate()`, `uploadVideo()`, and streaming variants
- **Shared option types**: `GenerateOptions` governs temperature, max tokens, and tool configurations
- **Standardized shapes**: Request and response structures normalized across providers

The interface declaration spans lines 213–221 in [`packages/kosong/src/provider.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/kosong/src/provider.ts), with supporting types like `GenerateOptions` appearing at lines 133–140. By coding against this abstraction, the rest of Kimi Code remains agnostic to which vendor actually fulfills the request.

## Provider-Specific Adapters: Translating Generic to Native

Each LLM service lives in its own adapter file under `packages/kosong/src/providers/`, translating `ChatProvider` calls into provider-native HTTP payloads:

| Provider | File | Key Responsibilities |
|----------|------|-------------------|
| OpenAI-compatible APIs | [`openai-common.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/openai-common.ts) | Error handling, token limits, finish reason mapping (lines 58–68) |
| Anthropic Claude | [`anthropic.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/anthropic.ts) | JSON schemas, tool-call formatting, native message structure (lines 110–119) |
| Google GenAI (Gemini) | [`google-genai.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/google-genai.ts) | Custom streaming semantics, content part handling |
| Internal Kimi service | [`kimi.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/kimi.ts) | Proprietary authentication and response parsing |

These adapters handle provider-specific quirks systematically:

1. **Stream chunk processing**: [`chat-completions-stream.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/chat-completions-stream.ts) (lines 24–31) normalizes incremental response formats
2. **Authentication**: [`request-auth.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/request-auth.ts) (lines 2–13) injects API keys and headers per provider conventions
3. **Message preprocessing**: [`merge-user-messages.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/merge-user-messages.ts) (lines 5–16) collapses consecutive user messages for providers with strict alternation requirements

## Factory Registry: `createProvider` and Static Discovery

The entry point for the Kosong provider abstraction layer is `createProvider(config)` in [`packages/kosong/src/providers/index.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/kosong/src/providers/index.ts) (lines 25–27). This factory enables runtime provider selection through a static registry pattern:

```typescript
// Static lookup table mapping ProviderType to adapter class
// Lines 41-49 in packages/kosong/src/providers/index.ts
const providerRegistry = {
  openai: OpenAIProvider,
  anthropic: AnthropicProvider,
  'google-genai': GoogleGenAIProvider,
  kimi: KimiProvider,
  // ...
} as const;

```

The registry is **purely static**—it performs lookup without instantiation, then constructs the appropriate adapter from `ProviderConfig` (which requires `type` and provider-specific options like `apiKey` and `model`).

## Capability Registry: Per-Model Feature Flags

Beyond basic routing, the abstraction layer exposes `getModelCapability` to query per-model features. Defined in [`packages/kosong/src/providers/capability-registry.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/kosong/src/providers/capability-registry.ts) (lines 41–44), this registry answers questions like:

- Does this model support tool calls?
- Is vision/multimodal input available?
- What are the context window and rate limits?

This enables dynamic capability detection without hardcoding provider-model matrices throughout Kimi Code.

## Practical Usage: Swapping Providers Without Code Changes

The `generate` function in [`packages/kosong/src/generate.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/kosong/src/generate.ts) (lines 215–218) consumes only the `ChatProvider` interface. This means the same orchestration code works identically across all backends:

```typescript
import { createProvider, generate } from '#/kosong';

// OpenAI backend
const openai = createProvider({
  type: 'openai',
  model: 'gpt-4o-mini',
  apiKey: process.env.OPENAI_API_KEY,
});

// Anthropic backend
const anthropic = createProvider({
  type: 'anthropic',
  model: 'claude-3-5-sonnet-20240620',
  apiKey: process.env.ANTHROPIC_API_KEY,
});

// Identical invocation, different backend
await generate(openai, {
  messages: [{ role: 'user', content: 'Explain quantum tunneling.' }],
});

await generate(anthropic, {
  messages: [{ role: 'user', content: 'Explain quantum tunneling.' }],
});

```

Tool calls, streaming responses, and error handling propagate through the same abstraction without caller awareness of the underlying provider.

## Summary

- **Single interface**: `ChatProvider` in [`packages/kosong/src/provider.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/kosong/src/provider.ts) defines the universal contract for all LLM interactions.
- **Adapter pattern**: Each provider implements this interface with native payload translation, error mapping, and streaming normalization.
- **Static registry**: [`packages/kosong/src/providers/index.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/kosong/src/providers/index.ts) maps `ProviderType` to concrete classes without runtime discovery overhead.
- **Capability-aware**: [`capability-registry.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/capability-registry.ts) exposes model-specific feature flags for dynamic behavior adjustment.
- **Caller-agnostic**: The `generate` entry point and downstream code operate on the abstraction, enabling provider swaps via configuration alone.

## Frequently Asked Questions

### How does Kosong handle provider-specific authentication schemes?

Each adapter implements authentication logic in [`request-auth.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/request-auth.ts) (lines 2–13) or internally within the provider file. OpenAI uses Bearer tokens, Anthropic requires `x-api-key` headers, and Google GenAI uses API‑key query parameters—these details are encapsulated so callers pass only a single `apiKey` property regardless of backend.

### What happens when a provider doesn't support a capability like tool calls?

The capability registry in [`capability-registry.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/capability-registry.ts) (lines 41–44) exposes per-model flags. Adapters throw descriptive errors for unsupported operations, and higher-level code can gate feature availability based on `getModelCapability` queries before invoking provider methods.

### Can I add a custom provider without modifying Kosong's core?

Yes. Implement the `ChatProvider` interface, add your class to the `providerRegistry` object in [`packages/kosong/src/providers/index.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/kosong/src/providers/index.ts) (lines 41–49), and extend the `ProviderType` union. The static registry pattern requires recompilation but no structural changes to the abstraction layer itself.

### How does streaming work across providers with different chunk formats?

The [`chat-completions-stream.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/chat-completions-stream.ts) module (lines 24–31) normalizes provider-specific streaming protocols into a unified async iterator. Each adapter produces chunks in its native format; the stream processor transforms these into consistent delta objects that the caller consumes uniformly.