Tools are executable capabilities that allow the agent to interact with the environment — reading files, running commands, searching the web, and more.
All tools inherit from the abstract Tool class in nanobot/agent/tools/base.py:
class Tool(ABC): """ Abstract base class for agent tools. Tools are capabilities that the agent can use to interact with the environment, such as reading files, executing commands, etc. """ @property @abstractmethod def name(self) -> str: """Tool name used in function calls.""" pass @property @abstractmethod def description(self) -> str: """Description of what the tool does.""" pass @property @abstractmethod def parameters(self) -> dict[str, Any]: """JSON Schema for tool parameters.""" pass @abstractmethod async def execute(self, **kwargs: Any) -> str: """ Execute the tool with given parameters. Returns: String result of the tool execution. """ pass
class WriteFileTool(Tool): """Tool to write content to a file.""" @property def name(self) -> str: return "write_file" @property def parameters(self) -> dict[str, Any]: return { "type": "object", "properties": { "path": { "type": "string", "description": "The file path to write to" }, "content": { "type": "string", "description": "The content to write" }, }, "required": ["path", "content"], } async def execute(self, path: str, content: str, **kwargs: Any) -> str: file_path = _resolve_path(path, self._workspace, self._allowed_dir) file_path.parent.mkdir(parents=True, exist_ok=True) file_path.write_text(content, encoding="utf-8") return f"Successfully wrote {len(content)} bytes to {file_path}"
See nanobot/agent/tools/filesystem.py:76-111.
edit_file - Edit File by Replacement
class EditFileTool(Tool): """Tool to edit a file by replacing text.""" @property def description(self) -> str: return "Edit a file by replacing old_text with new_text. The old_text must exist exactly in the file." async def execute(self, path: str, old_text: str, new_text: str, **kwargs: Any) -> str: file_path = _resolve_path(path, self._workspace, self._allowed_dir) content = file_path.read_text(encoding="utf-8") if old_text not in content: return self._not_found_message(old_text, content, path) count = content.count(old_text) if count > 1: return f"Warning: old_text appears {count} times. Please provide more context to make it unique." new_content = content.replace(old_text, new_text, 1) file_path.write_text(new_content, encoding="utf-8") return f"Successfully edited {file_path}"
Features intelligent error messages with diff output when text is not found.See nanobot/agent/tools/filesystem.py:114-192.
list_dir - List Directory Contents
class ListDirTool(Tool): """Tool to list directory contents.""" async def execute(self, path: str, **kwargs: Any) -> str: dir_path = _resolve_path(path, self._workspace, self._allowed_dir) items = [] for item in sorted(dir_path.iterdir()): prefix = "📁 " if item.is_dir() else "📄 " items.append(f"{prefix}{item.name}") return "\n".join(items)
Tools automatically validate parameters against their JSON schema:
def validate_params(self, params: dict[str, Any]) -> list[str]: """Validate tool parameters against JSON schema. Returns error list (empty if valid).""" if not isinstance(params, dict): return [f"parameters must be an object, got {type(params).__name__}"] schema = self.parameters or {} return self._validate(params, {**schema, "type": "object"}, "")
Validation checks:
Type matching (string, integer, boolean, array, object)
{ "type": "function", "function": { "name": "read_file", "description": "Read the contents of a file at the given path.", "parameters": { "type": "object", "properties": { "path": { "type": "string", "description": "The file path to read" } }, "required": ["path"] } }}
Filesystem Tools: Can be restricted to workspace directory with restrict_to_workspace=TrueShell Tool: Includes deny patterns for dangerous commands (rm -rf, format, dd, etc.)Web Tools: Validate URLs and limit content size to prevent DoS