calute.extensions.plugins#

Plugin system for Calute.

Supports four plugin types:

  • tool: Provides callable tool functions for agents.

  • hook: Provides lifecycle hooks (before/after tool, bootstrap, etc.).

  • provider: Provides LLM provider implementations.

  • channel: (Future) Provides communication channel integrations.

Plugins are Python modules or classes that register themselves with the PluginRegistry. Local plugin discovery scans a configured directory for modules containing a register(registry) function.

Example plugin module (my_plugin.py):

from calute.extensions.plugins import PluginMeta, PluginType

PLUGIN_META = PluginMeta(
    name="my_plugin",
    version="1.0.0",
    plugin_type=PluginType.TOOL,
    description="My custom tools",
)

def my_tool(query: str) -> str:
    '''Search for something.'''
    return f"Results for {query}"

def register(registry):
    registry.register_tool("my_tool", my_tool, meta=PLUGIN_META)
exception calute.extensions.plugins.PluginConflictError(name: str, existing: str)[source]#

Bases: Exception

Raised when a plugin or resource name conflicts with an existing registration.

name#

The name of the plugin or resource that caused the conflict.

existing#

The name of the already-registered plugin that owns the conflicting resource.

class calute.extensions.plugins.PluginMeta(name: str, version: str = '0.1.0', plugin_type: ~calute.extensions.plugins.PluginType = PluginType.TOOL, description: str = '', author: str = '', dependencies: list[str] = <factory>, version_constraints: dict[str, str] = <factory>)[source]#

Bases: object

Metadata describing a Calute plugin.

Every plugin must provide a PluginMeta instance when it registers itself. The metadata is used for dependency resolution, conflict detection, and informational logging.

name#

A unique identifier for the plugin (e.g., "my_search_plugin").

Type

str

version#

A semver-style version string for the plugin (default "0.1.0").

Type

str

plugin_type#

The category of functionality the plugin provides.

Type

calute.extensions.plugins.PluginType

description#

A short human-readable description of the plugin.

Type

str

author#

The name or handle of the plugin author.

Type

str

dependencies#

A list of dependency strings (plugin names, optionally with version constraints like "other_plugin>=1.0").

Type

list[str]

version_constraints#

A mapping of plugin names to version constraint expressions (e.g., {"core": ">=2.0,<3.0"}). These are checked in addition to dependencies.

Type

dict[str, str]

author: str = ''#
dependencies: list[str]#
description: str = ''#
name: str#
plugin_type: PluginType = 'tool'#
version: str = '0.1.0'#
version_constraints: dict[str, str]#
class calute.extensions.plugins.PluginRegistry[source]#

Bases: object

Central registry for plugin management, discovery, and dependency validation.

Plugins register tools, hooks, and providers through this registry. The registry tracks ownership so that all resources belonging to a plugin can be removed atomically via unregister_plugin().

_plugins#

Internal mapping of plugin name to RegisteredPlugin.

_tools#

Mapping of tool name to (callable, plugin_name) tuple.

_hooks#

Mapping of hook name to list of (callable, plugin_name) tuples, in registration order.

_providers#

Mapping of provider name to (provider, plugin_name) tuple.

Example

>>> registry = PluginRegistry()
>>> registry.register_tool("my_tool", my_func, meta=PluginMeta(name="test"))
>>> func = registry.get_tool("my_tool")
discover(directory: str | pathlib.Path) list[str][source]#

Discover and load plugins from a directory.

Scans the given directory for top-level Python files (ignoring those starting with _). Each file is loaded as a temporary module; if it exposes a register(registry) function, that function is called with self to let the plugin register its resources.

Modules are removed from sys.modules after loading to avoid polluting the global namespace.

Parameters

directory – Path to the directory to scan for plugin modules.

Returns

A list of plugin names that were newly registered during discovery.

get_all_tools() dict[str, Callable][source]#

Return a mapping of tool name to callable for all registered tools.

Returns

A dictionary mapping each tool name to its callable implementation. The result is a new dict; mutating it does not affect the registry.

get_hooks(hook_name: str) list[Callable][source]#

Get all registered hook callbacks for a hook point.

Parameters

hook_name – The hook point name to query.

Returns

A list of callable hooks in registration order. Returns an empty list if no hooks are registered for the given name.

get_load_order() list[str][source]#

Return plugin names in dependency-safe order (dependencies first).

Raises

calute.extensions.dependency.CircularDependencyError – If circular deps exist.

get_plugin(name: str) calute.extensions.plugins.RegisteredPlugin | None[source]#

Look up a registered plugin by name.

Parameters

name – The plugin name to look up.

Returns

The RegisteredPlugin instance, or None if no plugin with the given name exists.

get_provider(provider_name: str) Any | None[source]#

Look up a registered LLM provider by name.

Parameters

provider_name – The name the provider was registered under.

Returns

The provider instance, or None if not found.

get_tool(tool_name: str) Optional[Callable][source]#

Look up a registered tool by name.

Parameters

tool_name – The name the tool was registered under.

Returns

The callable tool function, or None if no tool with the given name is registered.

property plugin_names: list[str]#

Return the names of all registered plugins.

Returns

A list of plugin name strings in insertion order.

register_hook(hook_name: str, func: Callable, meta: calute.extensions.plugins.PluginMeta | None = None, plugin_name: str | None = None) None[source]#

Register a hook callback function.

Multiple hooks can be registered for the same hook point; they are stored in registration order. If meta is provided and the owning plugin is not yet registered, it is auto-registered first.

Parameters
  • hook_name – The hook point name (e.g., "before_tool_call").

  • func – The callable to invoke at this hook point.

  • meta – Optional plugin metadata. If provided and the plugin is not yet registered, register_plugin() is called automatically.

  • plugin_name – Explicit plugin name override. If omitted, the name is inferred from meta or defaults to "__standalone__".

register_plugin(meta: PluginMeta) RegisteredPlugin[source]#

Register a plugin by its metadata.

Creates a new RegisteredPlugin entry and stores it in the internal registry. Duplicate names are not allowed.

Parameters

meta – The PluginMeta describing the plugin.

Returns

The newly created RegisteredPlugin handle.

Raises

PluginConflictError – If a plugin with the same name is already registered.

register_provider(provider_name: str, provider: Any, meta: calute.extensions.plugins.PluginMeta | None = None, plugin_name: str | None = None) None[source]#

Register an LLM provider implementation.

Only one provider can be registered per provider_name. If meta is provided and the owning plugin is not yet registered, it is auto-registered first.

Parameters
  • provider_name – A unique name for the provider (e.g., "openai").

  • provider – The provider instance or factory.

  • meta – Optional plugin metadata for auto-registration.

  • plugin_name – Explicit plugin name override.

Raises

PluginConflictError – If a provider with the same name is already registered.

register_tool(tool_name: str, func: Callable, meta: calute.extensions.plugins.PluginMeta | None = None, plugin_name: str | None = None) None[source]#

Register a tool function.

Parameters
  • tool_name – Name for the tool (used for policy checks and LLM schema).

  • func – The callable tool function.

  • meta – Optional plugin metadata (auto-registers plugin if not already).

  • plugin_name – Name of the owning plugin (inferred from meta if provided).

unregister_plugin(name: str) None[source]#

Remove a plugin and all its associated tools, hooks, and providers.

If the plugin is not found, this method is a no-op.

Parameters

name – The name of the plugin to remove.

validate_dependencies() list[str][source]#

Validate that all registered plugins have their dependencies met.

Returns a list of error messages (empty if all dependencies are satisfied).

class calute.extensions.plugins.PluginType(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)[source]#

Bases: Enum

Enumeration of plugin categories supported by the Calute plugin system.

Each plugin declares its type via PluginMeta, and the PluginRegistry uses the type to route registrations to the correct internal storage.

TOOL#

Provides callable tool functions for agents.

HOOK#

Provides lifecycle hooks (before/after tool, bootstrap, etc.).

PROVIDER#

Provides LLM provider implementations.

CHANNEL#

Communication channel integrations (reserved for future use).

SEARCH#

Search-engine integrations.

SPEECH#

Speech/TTS integrations.

CHANNEL = 'channel'#
HOOK = 'hook'#
PROVIDER = 'provider'#
SEARCH = 'search'#
SPEECH = 'speech'#
TOOL = 'tool'#
class calute.extensions.plugins.RegisteredPlugin(meta: ~calute.extensions.plugins.PluginMeta, tools: dict[str, typing.Callable] = <factory>, hooks: dict[str, typing.Callable] = <factory>, provider: ~typing.Any = None)[source]#

Bases: object

A plugin that has been registered with the PluginRegistry.

Aggregates the plugin metadata together with the tools, hooks, and provider that the plugin contributed during registration.

meta#

The metadata describing the plugin.

Type

calute.extensions.plugins.PluginMeta

tools#

A mapping of tool names to their callable implementations registered by this plugin.

Type

dict[str, Callable]

hooks#

A mapping of hook point names to their callable implementations registered by this plugin.

Type

dict[str, Callable]

provider#

An optional LLM provider instance registered by this plugin. None if the plugin does not provide a provider.

Type

Any

hooks: dict[str, Callable]#
meta: PluginMeta#
provider: Any = None#
tools: dict[str, Callable]#