# KimiSoul Architecture and Main Agent Loop: Inside MoonshotAI/kimi-cli

> Explore KimiSoul architecture, the orchestrator at MoonshotAI/kimi-cli, driving the main agent loop with Agents, Runtime, Context, Tools, and Hooks.

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

---

**KimiSoul is the core orchestrator in MoonshotAI/kimi-cli that wraps an Agent, Runtime, Conversation Context, dynamic injections, Toolset, and HookEngine to drive the main agent loop for every conversational turn.**

The `KimiSoul` class serves as the execution backbone of the Kimi CLI application, transforming raw user input into fully orchestrated agent turns. Understanding the **KimiSoul architecture** and how it manages the **main agent loop** is essential for anyone customizing or debugging the MoonshotAI/kimi-cli codebase. At its core, `KimiSoul` glues LLM inference, tool execution, context compaction, and user-defined hooks into a single extensible session.

## Core Components of the KimiSoul Architecture

### KimiSoul Class and State Management

The `KimiSoul` class is defined in [`src/kimi_cli/soul/kimisoul.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/soul/kimisoul.py) at lines 28–31. It wraps an `Agent` instance and its associated `Runtime`, while maintaining state for plan mode, dynamic injections, and the hook engine. During initialization at `KimiSoul.__init__` (lines 32–45), the class binds these subsystems together and prepares the conversation context.

### Agent and Runtime

The **Agent** provides the system prompt, toolset, and underlying LLM configuration, and it is instantiated inside `KimiSoul.__init__`. The **Runtime** dataclass, defined in [`src/kimi_cli/soul/agent.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/soul/agent.py) at lines 71–95, bundles the LLM client, OAuth manager, session state, and notification manager. Together, these objects supply the execution environment that `KimiSoul` orchestrates.

### Conversation Context

The **Context** object holds the message history, provides checkpointing, token counting, and automatic compaction. It is initialized as `self._context` in `KimiSoul.__init__` at lines 48–49 within [`src/kimi_cli/soul/kimisoul.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/soul/kimisoul.py). This component ensures the conversation stays within token budgets and can persist state across steps.

### Dynamic Injections and HookEngine

**Dynamic injections** are plugins that prepend synthetic system-reminder messages—such as AFK or plan-mode reminders—into the conversation. They are collected via `_collect_injections` at lines 65–78. The **HookEngine**, created at lines 80–82 of the same file, executes user-configurable hooks at well-defined lifecycle points including `UserPromptSubmit`, `Stop`, and `Notification` events.

### KimiToolset

The **Toolset** (`KimiToolset`) loads built-in tools, binds plan-mode state, and runs tool calls. Setup occurs in `_bind_plan_mode_tools` at lines 109–156 of [`src/kimi_cli/soul/kimisoul.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/soul/kimisoul.py). This module bridges the agent's reasoning with concrete tool execution.

## How the Main Agent Loop Executes a Turn

### Turn Initialization with `run`

Every turn begins with the `run` method in [`src/kimi_cli/soul/kimisoul.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/soul/kimisoul.py) (lines 60–78). This method prepares the turn, refreshes OAuth tokens, triggers the `UserPromptSubmit` hook, and determines whether the input is a slash command or a standard user message. It acts as the entry point that delegates into the deeper agent loop.

### The `_agent_loop` Method

The **main agent loop** itself resides in `_agent_loop` at lines 137–165 of [`src/kimi_cli/soul/kimisoul.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/soul/kimisoul.py). This method drives a single turn through the following lifecycle:

- **Turn initialization**: clears stale steers and loads deferred MCP tools.
- **Step guard**: enforces `max_steps_per_turn`.
- **Step begin**: emits a `StepBegin` wire event.
- **Context compaction**: automatically compacts the conversation when the token budget is exceeded (see the compaction check around lines 164–172).
- **Checkpoint**: persists the current state.
- **Step execution**: invokes `_step` to perform LLM calls, injection delivery, and tool execution.
- **Error handling**: catches `BackToTheFuture` for reverts or fatal errors.
- **Outcome resolution**: processes steers and decides whether to continue or finish the turn.

### Step Execution via `_step`

Each iteration of the loop calls `_step` at lines 111–128 of [`src/kimi_cli/soul/kimisoul.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/soul/kimisoul.py). This method handles:

- **Notification delivery** for root-only contexts (detailed around lines 133–165).
- **Dynamic injection collection** and insertion as a synthetic user message.
- **History normalization** via `normalize_history`.
- **LLM call with retry** using `kosong.step` and `tenacity`.
- **Toolset preparation** via `begin_step`.
- **Appending assistant and tool messages** back into the context.

### Turn Termination and Cleanup

After `_agent_loop` returns, the `run` method emits a `TurnEnd` event, tracks telemetry, and cleans up approval sources. This completes the conversational turn and returns control to the caller.

## Working with KimiSoul Programmatically

### Running a Turn

```python
from kimi_cli.agentspec import load_agent_spec
from kimi_cli.soul.agent import Agent, Runtime
from kimi_cli.soul.context import Context
from kimi_cli.soul.kimisoul import KimiSoul

# Load an agent spec (e.g., the default "code" agent)

agent_spec = load_agent_spec("code")
agent = Agent(spec=agent_spec)               # creates the Agent + its toolset

runtime = Runtime(...)                        # fill with Config, OAuth, Session, etc.

context = Context()                           # empty conversation context

soul = KimiSoul(agent, context=context)      # construct the soul

await soul.run("Write a Python script that prints Hello World")

```

### Adding Dynamic Injections

```python
from kimi_cli.soul.dynamic_injection import DynamicInjectionProvider

class MyReminderProvider(DynamicInjectionProvider):
    async def get_injections(self, history, soul):
        return [DynamicInjection(content="⚡ Remember to save your work!")]
        
soul.add_injection_provider(MyReminderProvider())

```

### Executing Slash Commands

```python
await soul.run("/skill:format_python", skip_user_prompt_hook=True)

```

## Key Source Files

| File | Description |
| --- | --- |
| [`src/kimi_cli/soul/kimisoul.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/soul/kimisoul.py) | Central orchestration class (`KimiSoul`) and the main agent loop. |
| [`src/kimi_cli/soul/agent.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/soul/agent.py) | Definition of `Agent` and the `Runtime` dataclass. |
| [`src/kimi_cli/soul/context.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/soul/context.py) | Message history, checkpointing, token counting, and compaction logic. |
| [`src/kimi_cli/soul/toolset.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/soul/toolset.py) | Tool loading, plan-mode binding, and tool call execution (`KimiToolset`). |
| [`src/kimi_cli/soul/slash.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/soul/slash.py) | Registry of built-in slash commands. |
| [`src/kimi_cli/hooks/engine.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/hooks/engine.py) | Hook engine implementation for user-configurable lifecycle hooks. |
| `src/kimi_cli/notifications/*` | Notification manager and wire events consumed by `_step`. |

## Summary

- **KimiSoul** is the central orchestrator in [`src/kimi_cli/soul/kimisoul.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/soul/kimisoul.py) that manages a full conversational turn.
- The **main agent loop** inside `_agent_loop` enforces step limits, compacts context, checkpoints state, and delegates execution to `_step`.
- **`_step`** handles notification delivery, dynamic injections, LLM calls with retry, and tool message appending.
- **Extension points** include `DynamicInjectionProvider`, the `HookEngine`, and the `KimiToolset`, all wired together during `KimiSoul.__init__`.

## Frequently Asked Questions

### What is KimiSoul in the kimi-cli project?

KimiSoul is the core orchestrator class defined in [`src/kimi_cli/soul/kimisoul.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/soul/kimisoul.py) that drives a Kimi CLI session by wrapping an `Agent`, its `Runtime`, and a `HookEngine`. It manages the full lifecycle of a conversational turn, from receiving user input to executing the main agent loop and emitting turn-level events.

### How does the main agent loop handle token budget limits?

During each iteration of `_agent_loop`, the loop checks whether the conversation exceeds its token budget and triggers automatic context compaction around lines 164–172. This compaction is managed by the `Context` object in [`src/kimi_cli/soul/context.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/soul/context.py), which preserves checkpoint state while reducing history size.

### What happens during a single step in the KimiSoul agent loop?

A single step is handled by the `_step` method at lines 111–128 of [`src/kimi_cli/soul/kimisoul.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/soul/kimisoul.py), which delivers notifications, collects dynamic injections, normalizes history, performs an LLM call with retry logic via `kosong.step`, and appends assistant and tool messages back into the context. Tool execution is coordinated through the `KimiToolset` after the LLM response is received.

### How can developers extend KimiSoul behavior?

Developers can extend `KimiSoul` by registering custom `DynamicInjectionProvider` instances for synthetic reminders, configuring hooks in the `HookEngine` for lifecycle events like `UserPromptSubmit`, or binding new tools via the toolset setup in `_bind_plan_mode_tools`. These extension points are initialized in `KimiSoul.__init__` and invoked within the main agent loop.