# How to Extend kimi-cli with Custom Plugins: A Complete Guide

> Extend kimi-cli with custom plugins using its dynamic YAML-based architecture. Learn to build and integrate your own Python tools for enhanced AI agent capabilities.

- Repository: [Moonshot AI/kimi-cli](https://github.com/MoonshotAI/kimi-cli)
- Tags: how-to-guide
- Published: 2026-07-19

---

**kimi-cli supports custom plugins through a dynamic tool-loading architecture that imports Python classes implementing the `KimiTool` protocol based on import paths specified in YAML agent specifications.**

The MoonshotAI/kimi-cli repository provides a modular command-line interface for AI agents that can be extended without modifying core source code. By leveraging the dynamic tool-set system implemented in [`src/kimi_cli/tools/toolset.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/tools/toolset.py), developers can inject custom functionality by creating Python modules that follow the `KimiTool` interface and referencing them in agent specifications.

## Understanding the Plugin Architecture

The extension mechanism relies on three core components working together: the agent specification, the tool-set loader, and the base tool protocol.

### The KimiTool Protocol

Every plugin must inherit from the `KimiTool` base class defined in [`src/kimi_cli/tools/base.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/tools/base.py). This protocol requires implementing an async `run` method that returns a `ToolResult` object. The class must also define a `name` attribute that serves as the unique identifier the LLM uses to invoke the tool.

When the agent executes a function call, the runtime looks up the registered tool by this name and invokes its `run` method with the provided arguments.

### Dynamic Loading Mechanism

The loading flow follows a strict sequence implemented across the core modules:

1. **`KimiCLI.create`** in [[`src/kimi_cli/app.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/app.py)](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/app.py) initializes the runtime and parses the agent specification YAML file.
2. The specification's **`tools`** field contains a list of Python import paths (e.g., `my_module.MyToolClass`).
3. **`KimiToolset`** in [[`src/kimi_cli/tools/toolset.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/tools/toolset.py)](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/tools/toolset.py) iterates over these paths, dynamically imports the modules using standard Python import semantics, and registers any class inheriting from `KimiTool`.
4. Because the system relies on `PYTHONPATH` resolution, any module installed in the current environment or local directory can be loaded as a plugin.

## Creating Your First Custom Plugin

The repository includes a working example in `examples/custom-tools/` that demonstrates the complete implementation pattern. You can replicate this structure to build your own extensions.

### Step 1: Implement the Tool Class

Create a Python file that defines a class inheriting from `KimiTool`. The class must implement the `run` coroutine and return a `ToolResult` instance.

```python

# my_tool.py

from kimi_cli.tools.base import KimiTool, ToolResult

class MyTool(KimiTool):
    """A custom tool that generates personalized greetings."""
    name = "my_tool"

    async def run(self, name: str) -> ToolResult:
        """Execute the tool logic."""
        return ToolResult(output=f"Hello, {name}!")

```

Save this file in your working directory or package it as an installable Python module.

### Step 2: Define the Agent Specification

Create a YAML file that registers your tool by its import path. The `tools` list uses dot-notation module paths to locate your class.

```yaml

# myagent.yaml

name: my-custom-agent
tools:
  - my_tool.MyTool
system_prompt: |
  You are an agent equipped with a custom greeting tool.
  Use my_tool to greet users by name when requested.

```

### Step 3: Execute with the Custom Tool

Run the CLI with your custom specification. The tool loads dynamically at startup and becomes available for the LLM to invoke.

```bash
kimi --agent-spec myagent.yaml "Please greet the user named Alice"

```

The runtime imports `my_tool.MyTool`, registers it under the name `my_tool`, and makes it available for function calling during the session.

## Packaging Plugins for Reuse

For production workflows, package your tools as standard Python distributions. This ensures dependency management and portability across environments.

```python

# setup.py

from setuptools import setup, find_packages

setup(
    name="kimi-custom-greeting",
    version="0.1.0",
    packages=find_packages(),
    install_requires=["kimi-cli"],
    python_requires=">=3.9",
)

```

After installing with `pip install .`, reference the tool using its fully qualified import path in any agent specification:

```yaml
tools:
  - kimi_custom_greeting.greeting_tool.GreetingTool

```

## Key Source Files and Extension Points

Understanding these specific files helps when debugging plugin loading issues or extending functionality further:

- **[[`src/kimi_cli/app.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/app.py)](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/app.py)**: Contains `KimiCLI.create`, the entry point that orchestrates runtime initialization and specification parsing.
- **[[`src/kimi_cli/tools/toolset.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/tools/toolset.py)](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/tools/toolset.py)**: Implements the `KimiToolset` class responsible for dynamic module import and tool registration.
- **[[`src/kimi_cli/tools/base.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/tools/base.py)](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/tools/base.py)**: Defines the `KimiTool` abstract base class and `ToolResult` dataclass that all plugins must implement.
- **[[`examples/custom-tools/myagent.yaml`](https://github.com/MoonshotAI/kimi-cli/blob/main/examples/custom-tools/myagent.yaml)](https://github.com/MoonshotAI/kimi-cli/blob/main/examples/custom-tools/myagent.yaml)**: Reference implementation showing the YAML structure for registering custom tools.
- **[[`examples/custom-tools/my_tool.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/examples/custom-tools/my_tool.py)](https://github.com/MoonshotAI/kimi-cli/blob/main/examples/custom-tools/my_tool.py)**: Minimal working example of a custom tool implementation that can be copied as a template.

## Summary

- **kimi-cli** uses a dynamic import system that loads custom tools from standard Python modules without requiring core code modifications.
- The **`KimiTool`** protocol in [`src/kimi_cli/tools/base.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/tools/base.py) defines the interface: inherit from the base class, set a unique `name`, and implement the async `run` method.
- Tool registration happens through the **`tools`** field in YAML agent specifications, processed by **`KimiToolset`** in [`src/kimi_cli/tools/toolset.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/tools/toolset.py).
- Standard Python packaging conventions apply, allowing you to distribute plugins via `pip` and reference them using fully qualified import paths.

## Frequently Asked Questions

### Do I need to modify the core kimi-cli source code to add plugins?

No. The architecture is designed for external extension. You create standalone Python modules that implement the `KimiTool` interface, place them anywhere on your `PYTHONPATH`, and reference them in your agent specification YAML file. The `KimiToolset` loader in [`src/kimi_cli/tools/toolset.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/src/kimi_cli/tools/toolset.py) handles the dynamic import at runtime.

### What Python version is required for custom tools?

kimi-cli requires Python 3.9 or higher. Your custom plugins must be compatible with this version and should declare their dependencies in a [`setup.py`](https://github.com/MoonshotAI/kimi-cli/blob/main/setup.py) or [`pyproject.toml`](https://github.com/MoonshotAI/kimi-cli/blob/main/pyproject.toml) file if distributed as packages. The async `run` method must use modern Python async/await syntax.

### Can I use third-party dependencies in my plugins?

Yes. Since plugins are standard Python modules, you can import any package installed in your environment. List these dependencies in your package's `install_requires` to ensure they're present when the CLI attempts to load your tool. The dynamic importer in `KimiToolset` will fail gracefully with an import error if dependencies are missing.

### How does the CLI resolve import paths for custom tools?

The system uses Python's standard import machinery. When you specify `my_module.MyClass` in the agent specification, `KimiToolset` performs a dynamic import equivalent to `from my_module import MyClass`. This means the module must be available on `PYTHONPATH`, either installed via pip or located in your current working directory. Relative imports are not supported; use absolute module paths only.