# How Runtime and Agent Classes Interact in Kimi-CLI: Dependency Injection and Multi-Agent Architecture

> Explore how the Runtime class serves as a service container for the Agent class in Kimi-CLI. Learn about dependency injection and multi-agent architecture in this technical deep dive.

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

---

**The `Runtime` class acts as a service container that provides execution-time dependencies to the `Agent` class, which encapsulates system prompts and toolsets, while sub-agents receive deep-copied runtimes via `copy_for_subagent` to maintain shared state with role-specific isolation.**

The interaction between Runtime and Agent classes forms the architectural backbone of the MoonshotAI/kimi-cli project. This design pattern decouples service management from agent logic, enabling sophisticated multi-agent workflows through runtime composition and inheritance. Understanding how these classes collaborate is essential for extending the framework or implementing custom agent behaviors.

## The Runtime Service Container

### Core Responsibilities

The **`Runtime`** dataclass serves as a comprehensive service locator that aggregates all execution-time dependencies a Kimi agent requires. It encapsulates session handling, configuration management, OAuth credentials, LLM access, notification systems, and background task management. When an agent needs to interact with external services or access configuration state, it retrieves these capabilities through its stored `Runtime` instance rather than instantiating them directly.

### Factory Initialization via Runtime.create

The framework constructs runtimes through the **`Runtime.create`** class method defined in [`src/kimi_cli/soul/agent.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/soul/agent.py) (lines 71-104). This factory method initializes a fully-populated runtime containing:

- Configuration objects and logger instances
- OAuth manager for authentication flows
- LLM client for model interactions
- Session state management
- Built-in system prompt arguments (`builtin_args`)
- Skill discovery mechanisms
- Notification and background task managers

```python
from kimi_cli.soul.agent import Runtime
from kimi_cli.config import Config
from kimi_cli.auth.oauth import OAuthManager
from kimi_cli.llm import LLM
from kimi_cli.session import Session

runtime = await Runtime.create(
    config=Config(...),
    oauth=OAuthManager(...),
    llm=LLM(...),
    session=Session(...),
    yolo=False,
)

```

## Agent Class Integration with Runtime Services

### The load_agent Bridge Function

The **`load_agent`** function in [`src/kimi_cli/soul/agent.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/soul/agent.py) (lines 84-92) serves as the primary bridge between `Runtime` and `Agent` classes. This function receives a `Runtime` instance and uses it to:

- Render the system prompt via `_load_system_prompt` using the runtime's `builtin_args`
- Register built-in sub-agent types in the runtime's `LaborMarket`
- Construct a dependency map (`tool_deps`) that includes the runtime itself and its fields

The resulting **`Agent`** dataclass stores the original `Runtime` object directly, giving it persistent access to all underlying services throughout its lifecycle.

### Dependency Injection Through tool_deps

The runtime propagates its services to individual tools through the `tool_deps` parameter. When `KimiToolset` initializes, it consumes this dependency map, allowing tools to access runtime fields such as configuration, session state, and LLM clients. This injection pattern ensures tools remain stateless while accessing shared resources.

```python
from kimi_cli.tools.base import BaseTool

class EchoTool(BaseTool):
    name = "echo"

    async def run(self, message: str) -> str:
        logger = self.runtime.config.logger
        logger.info("EchoTool called")
        return f"ECHO: {message}"

```

## Sub-Agent Architecture and Runtime Inheritance

### Deep Copying with copy_for_subagent

When the `/agent` tool spawns sub-agents, it invokes **`Runtime.copy_for_subagent`** (defined in [`src/kimi_cli/soul/agent.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/soul/agent.py), lines 39-70). This method creates a new `Runtime` instance that preserves the parent agent's execution context while enabling role-specific customization. The method accepts parameters for `agent_id`, `subagent_type`, and optional `llm_override` configurations.

### Shared State vs Role-Specific Isolation

The `copy_for_subagent` method implements a sophisticated sharing strategy:

- **Shared references**: Immutable fields such as `config`, `oauth`, and `session` are reused across parent and child agents
- **Mutable collection sharing**: Collections like `additional_dirs` are shared by reference so changes propagate across the agent hierarchy
- **Isolated components**: Each sub-agent receives a distinct `DenwaRenji` instance and a role-specific `BackgroundTaskManager`

```python

# Inside a tool implementation (e.g., the /agent tool)

sub_runtime = agent.runtime.copy_for_subagent(
    agent_id="sub-123",
    subagent_type="my-subtype",
    llm_override=None,
)

sub_agent = await load_agent(
    agent_file=Path("agents/sub.yaml"),
    runtime=sub_runtime,
    mcp_configs=[],
)

```

## Implementation Examples

### Creating a Root Runtime and Loading the Main Agent

This example demonstrates the standard initialization pattern for a primary agent:

```python
from pathlib import Path
from kimi_cli.soul.agent import Runtime, load_agent

# Initialize the service container

runtime = await Runtime.create(
    config=my_config,
    oauth=my_oauth,
    llm=my_llm,
    session=my_session,
    yolo=False,
)

# Load agent with runtime injection

agent = await load_agent(
    agent_file=Path("agents/default.yaml"),
    runtime=runtime,
    mcp_configs=[],
)

```

### Spawning a Sub-Agent from a Running Agent

Sub-agents inherit the parent's runtime state while maintaining isolation:

```python

# Within an agent tool execution context

sub_runtime = agent.runtime.copy_for_subagent(
    agent_id="helper-001",
    subagent_type="analyzer",
)

sub_agent = await load_agent(
    agent_file=Path("agents/analyzer.yaml"),
    runtime=sub_runtime,
    mcp_configs=[],
)

```

## Summary

- The **`Runtime`** class functions as a comprehensive service container managing all execution-time dependencies including configuration, LLM access, and session state.
- The **`Agent`** class stores a `Runtime` reference and consumes its services through the `load_agent` initialization process and `tool_deps` injection.
- **`Runtime.create`** builds fully populated runtime instances, while **`load_agent`** bridges the runtime services with agent-specific configuration.
- **`Runtime.copy_for_subagent`** enables multi-agent hierarchies by deep-copying runtimes with selective state sharing and role-specific isolation.
- Tools access runtime services through dependency injection, maintaining clean separation between tool logic and service management.

## Frequently Asked Questions

### What services does the Runtime class actually provide to Agents?

The `Runtime` class provides session management, OAuth authentication, LLM client access, configuration objects, notification systems, background task management, and built-in system prompt arguments. According to the `kimi-cli` source code, these services are aggregated in [`src/kimi_cli/soul/agent.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/soul/agent.py) and passed to agents during the `load_agent` initialization phase.

### How do sub-agents share state with their parent agents?

Sub-agents share state through the `copy_for_subagent` method, which creates a new runtime that reuses references to immutable fields like `config` and `session` while sharing mutable collections such as `additional_dirs`. This ensures that file system changes or configuration updates propagate across the agent hierarchy while maintaining separate execution contexts for background tasks.

### Where is the Agent class defined and what does it store?

The `Agent` dataclass is defined in [`src/kimi_cli/soul/agent.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/soul/agent.py) (lines 72-80). It stores the agent name, rendered system prompt, a `KimiToolset` instance, and the `Runtime` object passed during initialization. This structure allows the agent to maintain its specific configuration while delegating service access to the runtime.

### How does dependency injection work for custom tools?

Custom tools receive runtime access through the `tool_deps` dependency map constructed during `load_agent` execution. The `KimiToolset` passes these dependencies to each tool instance, allowing tools to access `self.runtime` and its fields (such as `config.logger` or `session`) without direct instantiation, as implemented in [`src/kimi_cli/soul/agent.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/soul/agent.py).