Skip to content

Plugins

The plugin system lets you package tools as a Toolkit class, distribute it as a Python package, and have Cyclops discover it automatically via entry points. No manual registration needed.

Subclass Toolkit and add BaseTool instances as class attributes. The get_tools() method scans the class for any attribute that is a BaseTool instance and returns them as a list.

from cyclops.toolkit.plugins import Toolkit
from cyclops.toolkit.tool import BaseTool
import random
class WeatherTool(BaseTool):
def __init__(self):
super().__init__(name="get_weather", description="Get weather for a location.")
async def execute(self, location: str) -> str:
temps = {"london": 61, "tokyo": 74, "new york": 68}
temp = temps.get(location.lower(), random.randint(55, 85))
return f"{location}: {temp}F"
class ForecastTool(BaseTool):
def __init__(self):
super().__init__(name="get_forecast", description="Get a 3-day forecast.")
async def execute(self, location: str) -> str:
return f"Forecast for {location}: Day 1: 70F, Day 2: 68F, Day 3: 72F"
class WeatherToolkit(Toolkit):
"""Provides weather and forecast tools."""
weather = WeatherTool()
forecast = ForecastTool()

Tools are discovered by attribute inspection. There is no registration call needed inside the class.

PluginManager orchestrates loading and registration. It holds a ToolRegistry and a dictionary of named Toolkit instances.

Manually register a toolkit. This is useful in scripts and tests:

from cyclops.toolkit.plugins import PluginManager
from cyclops.toolkit.registry import ToolRegistry
registry = ToolRegistry()
manager = PluginManager(registry)
manager.register(WeatherToolkit())

An optional name argument overrides the class name used as the plugin key.

Discovers and loads all toolkits registered under the "cyclops.toolkits" entry-point group:

manager.load_plugins()

Call this once at startup.

After loading, push all tool instances into the registry:

manager.register_tools()
print(registry.list_tools()) # ["get_weather", "get_forecast"]
from cyclops import Agent, AgentConfig
from cyclops.toolkit.plugins import PluginManager
from cyclops.toolkit.registry import ToolRegistry
def build_agent() -> Agent:
registry = ToolRegistry()
manager = PluginManager(registry)
# Auto-discover all installed toolkit plugins.
manager.load_plugins()
manager.register_tools()
tools = [registry.get_tool(name) for name in registry.list_tools()]
config = AgentConfig(model="groq/llama-3.1-8b-instant")
return Agent(config, tools=tools)
agent = build_agent()
print(agent.run("What is the weather in London?"))

To make a toolkit auto-discoverable, add it to the [project.entry-points."cyclops.toolkits"] section of your package’s pyproject.toml:

[project.entry-points."cyclops.toolkits"]
weather = "my_weather_package.plugin:WeatherToolkit"

The key (weather) becomes the plugin name reported by get_plugin_names(). The value is a dotted import path to the Toolkit subclass.

After installing the package (pip install my-weather-package), calling manager.load_plugins() will find and instantiate WeatherToolkit automatically.

my_weather_toolkit/
├── pyproject.toml
└── my_weather_toolkit/
├── __init__.py
├── plugin.py <- WeatherToolkit class lives here
└── tools.py <- WeatherTool, ForecastTool classes
pyproject.toml
[project]
name = "my-weather-toolkit"
version = "0.1.0"
dependencies = ["cyclops-ai>=0.1.0"]
[project.entry-points."cyclops.toolkits"]
weather = "my_weather_toolkit.plugin:WeatherToolkit"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
examples/plugin_system.py
"""Plugin system example - Discover and load toolkit plugins
This example shows how to manually load a toolkit plugin.
In production, plugins would be installed via uv and auto-discovered.
To create a toolkit plugin:
1. Create a class that inherits from Toolkit
2. Implement get_tools() to return your tools
3. Register it via entry points or manually with PluginManager
"""
import sys
from pathlib import Path
# Add example_toolkit_plugin to path for this demo
sys.path.insert(0, str(Path(__file__).parent))
from cyclops import Agent, AgentConfig
from cyclops.toolkit.plugins import PluginManager
from cyclops.toolkit.registry import ToolRegistry
from example_toolkit_plugin import WeatherToolkit
def main():
# Create plugin manager
registry = ToolRegistry()
plugin_manager = PluginManager(registry)
# Manually register the toolkit plugin (in production, this would be via entry points)
plugin_manager.register(WeatherToolkit())
# Load tools from plugins
plugin_manager.register_tools()
print(f"Loaded plugins: {plugin_manager.get_plugin_names()}")
print(f"Available tools: {registry.list_tools()}\n")
# Get tools from registry for Agent
tools = [registry.get_tool(name) for name in registry.list_tools()]
# Create agent with plugin-provided tools
config = AgentConfig(model="ollama/qwen3:4b")
agent = Agent(config, tools=tools)
print("Agent with plugin-provided tools:\n")
# Use weather tool
response = agent.run("What's the weather in Seattle?")
print("Q: What's the weather in Seattle?")
print(f"A: {response}\n")
# Use forecast tool
response = agent.run("Give me a 3-day forecast for Portland")
print("Q: Give me a 3-day forecast for Portland")
print(f"A: {response}\n")
if __name__ == "__main__":
main()