# How to Implement Custom Agent Profiles in Kimi Code Using Contribution, Registry, and Catalog Extension Points

> Learn to implement custom agent profiles in Kimi Code. Register your ProfileData using CatalogService and let IAgentProfileService bind it for seamless integration.

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

---

**To implement custom agent profiles in Kimi Code, create a `ProfileData` definition, register it via `definePartialInstance` with the `CatalogService`, and let the `IAgentProfileService` bind it at runtime.**

Kimi Code's agent architecture exposes a clean three-layer extension system that lets you add new **agent profiles** without modifying core engine code. This article walks through the contribution → registry → catalog pipeline, using actual source paths from the MoonshotAI/kimi-code repository.

## Understanding the Three-Layer Architecture

Kimi Code organizes profile discovery through three distinct layers:

- **Contribution** — A module that exports a static object describing the profile
- **Registry** — The `CatalogService` that discovers all contributions at startup
- **Catalog** — The runtime lookup performed by `IAgentProfileService`

The built-in implementation in [`packages/agent-core-v2/src/kosong/provider/providers/kimi/kimi.contrib.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core-v2/src/kosong/provider/providers/kimi/kimi.contrib.ts) demonstrates this pattern. The `CatalogService` at [`packages/agent-core-v2/src/kosong/model/catalogService.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core-v2/src/kosong/model/catalogService.ts) registers each contribution under `CatalogService.register`, and the profile service at [`packages/agent-core-v2/src/agent/profile/profile.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core-v2/src/agent/profile/profile.ts) calls `catalog.get(profileName)` to retrieve and bind definitions.

## Step 1: Create a Profile Definition

Start by defining your profile data. Create a new TypeScript file in a custom provider folder, such as [`packages/agent-core-v2/src/kosong/provider/providers/my-profile/myProfile.contribute.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core-v2/src/kosong/provider/providers/my-profile/myProfile.contribute.ts).

Export a constant that satisfies the `ProfileData` type defined in [`packages/agent-core-v2/src/kosong/model/catalog.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core-v2/src/kosong/model/catalog.ts):

```typescript
import type { ProfileData } from '#/kosong/model/catalog';

export const myProfile: ProfileData = {
  profileName: 'my-assistant',
  systemPrompt: 'You are a helpful assistant that always speaks in rhymes.',
  modelAlias: 'gpt-4o-mini',
  thinkingLevel: 'off',
  disallowedTools: ['FileSystem'],
};

```

Key `ProfileData` fields include:
- `profileName` — Unique identifier for the profile
- `systemPrompt` — The agent's personality and instructions
- `modelAlias` — Default model to use
- `thinkingLevel` — Controls reasoning depth (`'off'`, `'low'`, `'medium'`, `'high'`)
- `disallowedTools` — Array of tool names to disable

## Step 2: Declare the Contribution

Register your profile with the global catalog using `definePartialInstance`. Add this declaration at the bottom of your contribution file:

```typescript
import { definePartialInstance } from '@moonshot-ai/kosong';
import { CatalogService } from '#/kosong/model/catalogService';

definePartialInstance(CatalogService, {
  add: (catalog) => catalog.register(myProfile),
});

```

This mirrors the pattern in [`kimi.contrib.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/kimi.contrib.ts). The `CatalogService` automatically scans for these contributions via its contribution loader.

## Step 3: Update Workspace Configuration

Ensure your new provider package is included in the build. Update both:

- [`pnpm-workspace.yaml`](https://github.com/MoonshotAI/kimi-code/blob/main/pnpm-workspace.yaml) — Add the new package path
- `flake.nix` — Include the source directory

These changes follow the monorepo's workspace maintenance rules documented in [`AGENTS.md`](https://github.com/MoonshotAI/kimi-code/blob/main/AGENTS.md) at the repository root.

## Step 4: Use the Custom Profile

When creating a session, pass the profile name in your request. The `IAgentProfileService` performs catalog lookup, binds the configuration, and applies it to the agent runtime.

REST API example:

```http
POST /v1/sessions/xyz/profile
Content-Type: application/json

{ "profile": "my-assistant" }

```

Node SDK example:

```typescript
import { Klient } from '@moonshot-ai/klient';
import { Session } from '@moonshot-ai/klient/session';

async function startSession() {
  const klient = new Klient();
  const session = await Session.create(klient, { id: 'demo' });

  // Bind the custom profile
  await session.profile.bind({ profile: 'my-assistant' });

  // Session now uses custom system prompt and model
  const reply = await session.prompt('Explain photosynthesis in rhyme.');
  console.log(reply);
}

```

## Complete Custom Profile Example

Here's a full implementation file for reference:

```typescript
// packages/agent-core-v2/src/kosong/provider/providers/my-profile/myProfile.contribute.ts

import type { ProfileData } from '#/kosong/model/catalog';
import { definePartialInstance } from '@moonshot-ai/kosong';
import { CatalogService } from '#/kosong/model/catalogService';

export const myProfile: ProfileData = {
  profileName: 'code-reviewer',
  systemPrompt:
    'You are a meticulous code reviewer. Focus on security, performance, and maintainability. Always suggest concrete improvements with code examples.',
  modelAlias: 'gpt-4o',
  thinkingLevel: 'medium',
  disallowedTools: ['WebSearch', 'CodeExecution'],
};

definePartialInstance(CatalogService, {
  add: (catalog) => catalog.register(myProfile),
});

```

## Step 5: Verify Your Implementation

Run the existing test suite to validate the contribution pipeline:

```bash
pnpm test packages/agent-core-v2/test/_base/contribution/registry.test.ts

```

Consider adding a dedicated test to assert that `catalog.get('my-assistant')` returns expected data and binds without errors.

Debug your bound profile via the API:

```http
GET /api/v1/sessions/demo/profile

```

The response includes the resolved `ProfileData` with system prompt, model alias, and all configuration fields.

## Key Source Files Reference

| File | Role |
|------|------|
| [`packages/agent-core-v2/src/agent/profile/profile.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core-v2/src/agent/profile/profile.ts) | Implements `IAgentProfileService`; performs profile lookup and binding |
| [`packages/agent-core-v2/src/kosong/model/catalog.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core-v2/src/kosong/model/catalog.ts) | Declares the `ProfileData` interface |
| [`packages/agent-core-v2/src/kosong/model/catalogService.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core-v2/src/kosong/model/catalogService.ts) | Central registry; provides `catalog.get(name)` and `register()` |
| [`packages/agent-core-v2/src/kosong/provider/providers/kimi/kimi.contrib.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core-v2/src/kosong/provider/providers/kimi/kimi.contrib.ts) | Reference implementation of built-in profiles |
| [`packages/agent-core-v2/test/_base/contribution/registry.test.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core-v2/test/_base/contribution/registry.test.ts) | Validates contribution loading |

## Summary

- **Custom agent profiles** extend Kimi Code through the contribution → registry → catalog pipeline
- Define profiles using the `ProfileData` interface from [`catalog.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/catalog.ts)
- Register via `definePartialInstance` with `CatalogService.register`
- The `IAgentProfileService` binds profiles at runtime using `catalog.get()`
- Update [`pnpm-workspace.yaml`](https://github.com/MoonshotAI/kimi-code/blob/main/pnpm-workspace.yaml) and `flake.nix` for new provider packages
- Test using the built-in contribution registry tests

## Frequently Asked Questions

### Can I override built-in profiles with custom ones?

Profile names must be unique within the catalog. The `CatalogService` throws if you attempt to register a duplicate name. To extend an existing profile, create a new name and reference the base configuration in your `systemPrompt` or use composition patterns in your contribution file.

### What happens if a requested profile isn't found?

According to the source in [`profile.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/profile.ts), the `IAgentProfileService` attempts `catalog.get(profileName)` and fails with a clear error if no match exists. The error propagates to the session creation or profile binding call, allowing you to catch and handle missing profiles gracefully.

### Can profiles be defined in JSON instead of TypeScript?

The `CatalogService` registers `ProfileData` objects directly. While the built-in contributions use TypeScript for type safety and `definePartialInstance` integration, you can load JSON definitions and wrap them in a TypeScript contribution file that calls `catalog.register()`. The runtime only sees the resolved object.

### How do I restrict which tools an agent can use?

Use the `disallowedTools` array in your `ProfileData`. List tool names exactly as registered in the tool registry. The agent runtime consults this list before executing any tool call, rejecting attempts to use forbidden tools with an appropriate error message.