Tool Manager & Base Classes
Relevant source files
The following files were used as context for generating this wiki page:
The Tool System in QQcode is a modular framework designed to discover, validate, and execute a variety of tools that enable the AI agent to interact with the local environment and external services. This system relies on a strictly typed foundation using Pydantic for argument and result validation, ensuring that interactions between the LLM and the system are predictable and error-resistant.
The architecture separates the definition of tools (BaseTool) from their orchestration (ToolManager). The system supports built-in tools (like bash, read_file, write_file, and grep), custom user-defined tools, and dynamic tools generated from Model Context Protocol (MCP) server definitions.
Sources: CLAUDE.md:46-51, vibe/core/config.py:341-356
Tool Base Classes and Validation
The foundation of every tool in the repository is the BaseTool class. It utilizes Pydantic v2 to enforce modern type safety for input arguments and output results.
Core Tool Components
- BaseTool: The abstract base class that all tools must inherit from. It defines the lifecycle of a tool execution, including setup, execution, and UI display logic.
- BaseToolConfig: A configuration model that governs tool-specific settings, such as execution permissions (
allow,ask,deny). - Tool Logic: Tools implement a
run()method which takes validated Pydantic models as input and returns a validated result model.
The diagram above illustrates the relationship between the base tool classes and the manager responsible for their lifecycle.
Sources: vibe/core/tools/base.py, vibe/core/config.py:101-110, CLAUDE.md:48-49
Permission and Configuration
Tool execution behavior is controlled through the BaseToolConfig within the project configuration.
| Option | Type | Default | Description |
|---|---|---|---|
permission | Literal["always", "ask", "never"] | "ask" | Determines if a tool requires user approval before execution. |
timeout | float | None | Optional execution timeout for the tool process. |
Sources: vibe/core/config.py:341-356, vibe/core/tools/base.py
Tool Manager and Discovery
The ToolManager is the central registry for the system. It is responsible for discovering tools from multiple locations and instantiating them with the appropriate configuration.
Discovery Logic
The manager scans several directories to populate the list of available tools:
- Built-in Tools: Hardcoded tools provided by the package (e.g.,
vibe/core/tools/builtins/). - Custom Tools: User-defined tools located in directories specified in
config.tomlvia thetool_pathsfield. - MCP Integration: Dynamic discovery of tools from configured MCP servers.
Sources: vibe/core/config.py:348-356, CLAUDE.md:50-51, vibe/core/llm/format.py:72-100
Active Tool Filtering
Not all discovered tools are necessarily available to the agent. The system applies filters based on the enabled_tools and disabled_tools configuration using glob and regex matching.
This flow describes how the ToolManager identifies which tools should be exposed to the LLM backend during a session.
Sources: vibe/core/llm/format.py:27-70, vibe/core/config.py:365-385
Model Context Protocol (MCP) Integration
QQcode implements a proxy system for MCP tools. When an MCP server is configured (via stdio, http, or streamable-http), the ToolManager creates dynamic tool classes that act as proxies to the remote MCP methods.
MCP Configuration Fields
| Field | Type | Description |
|---|---|---|
name | str | Short alias used as a prefix for tool names (e.g., server_tool). |
transport | Literal["http", "stdio", ...] | The communication method for the server. |
command | `str | list[str]` |
url | str | The endpoint for http transport. |
Sources: vibe/core/config.py:151-225, CLAUDE.md:51
Tool Execution and UI Rendering
The tool system extends into the CLI's Textual TUI through specialized widgets. Each tool can define how its "approval" state and "result" state are displayed to the user.
- Approval Widgets: Rendered when a tool's permission is set to
"ask". For example,BashApprovalWidgetdisplays the raw bash command in a markdown block before the user confirms execution. - Result Widgets: Rendered after execution.
ReadFileResultWidgethandles truncation of long file contents to prevent UI clutter.
Sources: vibe/cli/textual_ui/widgets/tool_widgets.py:7-150, vibe/core/tools/base.py
Example: Tool Result Handling
When a tool finishes, it produces a ToolResult. The UI widgets (like ToolResultWidget) process this data to show a summary to the user.
# vibe/cli/textual_ui/widgets/tool_widgets.py:25-30
class ToolResultWidget(Static):
def __init__(self, data: dict, collapsed: bool = True) -> None:
super().__init__()
self.data = data
self.collapsed = collapsed
self.add_class("tool-result-widget")
Sources: vibe/cli/textual_ui/widgets/tool_widgets.py:25-30
Summary
The Tool Manager and Base Classes provide a robust, type-safe infrastructure for extending the agent's capabilities. By enforcing Pydantic validation at the base level and providing a flexible discovery mechanism for local and MCP-based tools, the system ensures that the AI agent can safely and effectively manipulate the codebase while maintaining strict user control through a configurable permission system.