How to Extend kimi-cli with Custom Plugins: A Complete Guide
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, 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. 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:
KimiCLI.createin [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.- The specification's
toolsfield contains a list of Python import paths (e.g.,my_module.MyToolClass). KimiToolsetin [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 fromKimiTool.- Because the system relies on
PYTHONPATHresolution, 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.
# 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.
# 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.
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.
# 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:
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): ContainsKimiCLI.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): Implements theKimiToolsetclass 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): Defines theKimiToolabstract base class andToolResultdataclass that all plugins must implement. - [
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): 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
KimiToolprotocol insrc/kimi_cli/tools/base.pydefines the interface: inherit from the base class, set a uniquename, and implement the asyncrunmethod. - Tool registration happens through the
toolsfield in YAML agent specifications, processed byKimiToolsetinsrc/kimi_cli/tools/toolset.py. - Standard Python packaging conventions apply, allowing you to distribute plugins via
pipand 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 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 or 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.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →