Custom Tools ============ You can extend Folderbot with custom tools by creating ``.folderbot/tools.py`` in your root folder. Basic Example ------------- This example adds a tool that appends timestamped entries to a daily journal: .. code-block:: python # .folderbot/tools.py from datetime import datetime from pathlib import Path from typing import Any from pydantic import BaseModel, Field from folderbot.tools import ToolDefinition, ToolResult class JournalEntryInput(BaseModel): content: str = Field(description="The journal entry content") mood: str = Field( default="neutral", description="Current mood (happy, sad, neutral, excited)", ) class CustomTools: def __init__(self, root_folder: Path): self.root_folder = root_folder def get_tool_definitions(self) -> list[dict[str, Any]]: tools = [ ToolDefinition( name="add_journal_entry", description="Add a timestamped entry to today's journal", input_model=JournalEntryInput, ), ] return [t.to_api_format() for t in tools] def execute(self, tool_name: str, tool_input: dict[str, Any]) -> ToolResult: if tool_name == "add_journal_entry": return self._add_journal_entry(tool_input) return ToolResult(content=f"Unknown tool: {tool_name}", is_error=True) def _add_journal_entry(self, tool_input: dict[str, Any]) -> ToolResult: params = JournalEntryInput(**tool_input) journal_dir = self.root_folder / "journal" journal_dir.mkdir(exist_ok=True) today = datetime.now().strftime("%Y-%m-%d") journal_file = journal_dir / f"{today}.md" if not journal_file.exists(): journal_file.write_text(f"# Journal - {today}\n\n") timestamp = datetime.now().strftime("%H:%M") entry = f"### {timestamp}\n\n{params.content}\n\n---\n\n" with open(journal_file, "a") as f: f.write(entry) return ToolResult(content=f"Added journal entry to {today}.md") Now you can tell the bot: *"Add to my journal: Had a great meeting today"*. Required Interface ------------------ Your ``CustomTools`` class must implement: ``__init__(self, root_folder: Path)`` Constructor that receives the root folder path. ``get_tool_definitions(self) -> list[dict[str, Any]]`` Return a list of tool definitions in API format. Use :class:`~folderbot.tools.base.ToolDefinition` to build these. ``execute(self, tool_name: str, tool_input: dict[str, Any]) -> ToolResult`` Execute a tool and return a :class:`~folderbot.tools.base.ToolResult`. Factory Function ---------------- Instead of a ``CustomTools`` class, you can export a ``create_tools`` function: .. code-block:: python def create_tools(root_folder: Path): return CustomTools(root_folder) Package Structure ----------------- For more complex tools, use a package at ``.folderbot/tools/__init__.py``: .. code-block:: text .folderbot/ └── tools/ ├── __init__.py # Exports CustomTools or create_tools ├── journal.py # Journal tool implementation └── reminders.py # Reminder tool implementation