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.
Toolkit base class
Section titled “Toolkit base class”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 Toolkitfrom cyclops.toolkit.tool import BaseToolimport 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
Section titled “PluginManager”PluginManager orchestrates loading and registration. It holds a ToolRegistry and a dictionary of named Toolkit instances.
register
Section titled “register”Manually register a toolkit. This is useful in scripts and tests:
from cyclops.toolkit.plugins import PluginManagerfrom 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.
load_plugins
Section titled “load_plugins”Discovers and loads all toolkits registered under the "cyclops.toolkits" entry-point group:
manager.load_plugins()Call this once at startup.
register_tools
Section titled “register_tools”After loading, push all tool instances into the registry:
manager.register_tools()
print(registry.list_tools()) # ["get_weather", "get_forecast"]Full workflow
Section titled “Full workflow”from cyclops import Agent, AgentConfigfrom cyclops.toolkit.plugins import PluginManagerfrom 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?"))Entry-point registration
Section titled “Entry-point registration”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.
Example toolkit package layout
Section titled “Example toolkit package layout”my_weather_toolkit/├── pyproject.toml└── my_weather_toolkit/ ├── __init__.py ├── plugin.py <- WeatherToolkit class lives here └── tools.py <- WeatherTool, ForecastTool classes[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"Full example
Section titled “Full example”"""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 Toolkit2. Implement get_tools() to return your tools3. Register it via entry points or manually with PluginManager"""
import sysfrom pathlib import Path
# Add example_toolkit_plugin to path for this demosys.path.insert(0, str(Path(__file__).parent))
from cyclops import Agent, AgentConfigfrom cyclops.toolkit.plugins import PluginManagerfrom cyclops.toolkit.registry import ToolRegistryfrom 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()