MonoClaw

Plugins

Plugins are the most powerful way to extend Mona. They can add new tools, hooks, memory providers, and even custom CLI commands.

Plugin structure

A plugin is a Python package with a plugin.yaml manifest:

my-plugin/
├── plugin.yaml
├── __init__.py
├── tools.py
├── hooks.py
└── skills/
    └── my-skill.md

plugin.yaml

name: my-plugin
version: 1.0.0
description: "My custom MonoClaw plugin"
author: "Your Name"

entrypoints:
  tools: my_plugin.tools:register_tools
  hooks: my_plugin.hooks:register_hooks
  skills: my_plugin.skills:register_skills

dependencies:
  - requests>=2.28.0

Installing plugins

Local plugins

monoclaw plugin install /path/to/my-plugin

GitHub plugins

monoclaw plugin install github.com/user/my-plugin

PyPI plugins

monoclaw plugin install monoclaw-plugin-example

Creating tools

# my_plugin/tools.py
from monoclaw.plugins import Tool

class MyTool(Tool):
    name = "my_tool"
    description = "Does something useful"
    parameters = {
        "input": {"type": "string", "description": "Input to process"}
    }

    async def run(self, input: str) -> str:
        return f"Processed: {input}"

def register_tools():
    return [MyTool()]

Creating hooks

Hooks run at key lifecycle points:

# my_plugin/hooks.py
from monoclaw.plugins import Hook

class PreMessageHook(Hook):
    event = "pre_message"

    async def run(self, message: str) -> str:
        # Modify or log messages before processing
        print(f"User said: {message}")
        return message

class PostResponseHook(Hook):
    event = "post_response"

    async def run(self, response: str) -> str:
        # Modify or log responses
        return response

def register_hooks():
    return [PreMessageHook(), PostResponseHook()]

Available hook events

EventWhen it fires
pre_messageBefore Mona processes a user message
post_responseAfter Mona generates a response
pre_tool_callBefore a tool is executed
post_tool_callAfter a tool returns
session_startWhen a new session begins
session_endWhen a session ends
gateway_messageWhen a gateway receives a message

Plugin permissions

Plugins run with the same permissions as MonoClaw. They can:

  • Execute arbitrary Python code
  • Access the filesystem
  • Make network requests
  • Read configuration and secrets

Only install plugins from trusted sources.

Plugin development

Local development

# Link your plugin for development
monoclaw plugin link /path/to/my-plugin

This installs the plugin in editable mode so changes take effect immediately.

Testing

# Run plugin tests
monoclaw plugin test my-plugin

Publishing

  1. Push to GitHub
  2. Tag a release
  3. Users can install with monoclaw plugin install github.com/user/repo

Best practices

  • Keep plugins focused — One domain per plugin
  • Handle errors gracefully — Don't crash the agent
  • Document parameters — Clear descriptions help Mona use tools correctly
  • Version carefully — Breaking changes affect users
  • Respect privacy — Don't exfiltrate data without consent

Example: HTTP request plugin

# tools.py
import httpx
from monoclaw.plugins import Tool

class HttpRequestTool(Tool):
    name = "http_request"
    description = "Make HTTP requests"
    parameters = {
        "url": {"type": "string", "description": "URL to request"},
        "method": {"type": "string", "enum": ["GET", "POST"], "default": "GET"}
    }

    async def run(self, url: str, method: str = "GET") -> str:
        async with httpx.AsyncClient() as client:
            response = await client.request(method, url)
            return response.text

def register_tools():
    return [HttpRequestTool()]