Newer
Older
navi-1 / docs / tools.md

Tool System

Tools are the agent's actions. All tools implement the Tool ABC from navi/tools/base.py.

Two tiers

Built-in tools (navi/tools/)

Registered in build_default_registries() as builtins. Never removed on hot-reload.

Tool Name Description
WebSearchTool mcp__navi_web__web_search DuckDuckGo search
WebViewTool mcp__navi_web__web_view Fetch and render a URL
FilesystemTool filesystem Read/write/list/copy/grep/diff local files (path restrictions via config)
HttpRequestTool mcp__navi_web__http_request Generic HTTP client (GET/POST/etc.)
CodeExecTool code_exec Execute Python in a subprocess sandbox
TerminalTool terminal Run shell commands (command allowlist via config)
SshExecTool ssh_exec SSH exec and SCP file transfer; connection pool keyed by session ID
ImageViewTool image_view Load image from path/URL → resize to 1024px, convert to JPEG, return base64 for multimodal LLM
TodoTool todo Per-session task checklist (set/update/read)
ScratchpadTool scratchpad Per-session named working notes (write/append/read/clear)
ReloadToolsTool reload_tools Hot-reload user tools without server restart
ListToolsTool list_tools Return the live tool list from registry
ToolManualTool tool_manual Return manuals/{name}.md or auto-generate from schema
MemoryTool memory Unified memory tool: save, search, and forget facts
SpawnAgentTool spawn_agent Spawn an isolated subagent (blocking). Optional profile_id selects another profile; omitted means parent profile. inherit_system_prompt=true prepends the parent profile's full system prompt as a base layer for the subagent
SwitchProfileTool switch_profile Switch the active profile for a session
ListProfilesTool list_profiles List all available profiles
ShareFileTool share_file Copy an existing local file into session files and return a download link
ContentPublishTool content_publish Register an existing session file for inline viewing in chat
McpTool (gnexus-creds) mcp__gnexus_creds__search_secrets Search personal secrets (UUID id, masked values)
McpTool (gnexus-creds) mcp__gnexus_creds__get_secret Get secret metadata and masked fields
McpTool (gnexus-creds) mcp__gnexus_creds__reveal_secret Decrypt and return plaintext value (audited)
McpTool (gnexus-creds) mcp__gnexus_creds__create_secret Create a new secret with encrypted fields
McpTool (gnexus-creds) mcp__gnexus_creds__update_secret Update fields/metadata of an existing secret
McpTool (gnexus-creds) mcp__gnexus_creds__set_secret_status Change secret status (actual / outdated / archived)
McpTool (gnexus-creds) mcp__gnexus_creds__archive_secret Permanently hide secret from MCP queries
McpTool (navi-3d) mcp__navi_3d__compile_scad Compile an OpenSCAD script into a binary STL file
McpTool (navi-3d) mcp__navi_3d__lint_scad Lightweight OpenSCAD source linting before STL compilation
McpTool (navi-3d) mcp__navi_3d__render_stl Render preview PNG images from an STL file (up to 3 views)
McpTool (navi-web) mcp__navi_web__web_search Web search (SearXNG primary, DDG fallback, Brave tertiary)
McpTool (navi-web) mcp__navi_web__web_view Open a URL in a headless browser and return clean readable text
McpTool (navi-web) mcp__navi_web__http_request Raw HTTP request (GET/POST/PUT/PATCH/DELETE)
McpStatusTool mcp_status Check connectivity and list tools for configured MCP servers
ReflectTool reflect Self-reflection and analysis
ScheduleRecallTool schedule_recall Schedule a headless callback for the current session (once/recurring/immediate)
ManageRecallTool manage_recall Cancel, skip, or list scheduled recalls for the current session

User tools (tools/*.py)

Written manually or via create_mcp_server. Auto-discovered at startup.

  • Files starting with _ are ignored.
  • tools/enabled.json — list of user tool names to include in all profiles automatically.
  • tools/_template.py — canonical format reference (not loaded).

Currently present: get_current_datetime.py, gmail.py, weather.py.


Tool formats

Module-level format (preferred for user tools)

name = "my_tool"
description = "What it does and when to use it — be specific."
parameters = {
    "type": "object",
    "properties": {
        "param": {"type": "string", "description": "..."}
    },
    "required": ["param"]
}

async def execute(params: dict) -> str:
    # Return a plain string on success.
    # Raise an exception to signal failure.
    return "result"

No classes, no module-level print(). The loader wraps execute in a Tool subclass automatically.

Class-based format (built-in tools)

from navi.tools.base import Tool, ToolResult

class MyTool(Tool):
    name = "my_tool"
    description = "..."
    parameters = {"type": "object", "properties": {...}, "required": [...]}

    async def execute(self, params: dict) -> ToolResult:
        return ToolResult(success=True, output="result")

ToolResult fields:

  • success: bool
  • output: str — always a string; LLM sees this
  • error: str | None — included in output on failure via to_message_content()
  • metadata: dict — internal hints (e.g. is_image: True → triggers image injection into context)

Tool loading (navi/tools/loader.py)

load_tools_from_dir(tools_dir) returns LoadResult(loaded, errors).

Load order:

  1. Try module-level format (checks for name, description, parameters, execute).
  2. Fall back to class-based (scans for Tool subclasses).

Errors are isolated per file — one broken file does not prevent others from loading. Errors are logged and returned in LoadResult.errors.


Middleware hooks

Tools support before_execute / after_execute middleware hooks registered via ToolRegistry.add_middleware(). The built-in LoggingMiddleware logs every tool call with duration and result summary.

Use middleware for cross-cutting concerns: metrics, rate limiting, authorization, audit logging.

Hot-reload

reload_tools tool calls ToolRegistry.reload_user_tools(tools_dir):

  1. Drops all tools that are NOT in _builtin_names.
  2. Re-runs load_tools_from_dir.
  3. New tools registered without server restart.

New tools become available from the next user message (tool schemas are built at run_stream() entry, not during execution).


Self-extension via MCP servers

New capabilities are added as MCP servers using create_mcp_server. The server scaffolding includes:

  1. A directory under mcp-servers/{name}/.
  2. A server.py entrypoint with stdio transport.
  3. A config file at mcp_servers.d/{name}.json.
  4. Registration via reload_tools or server restart.

The agent should call tool_manual("create_mcp_server") before using it for the first time.


Scratchpad and Todo

Both are per-session, backed by the PostgreSQL KV-store (session_store table) and survive server restarts.

Scratchpad — named sections for working notes within a task. Operations: write, append, read, clear. Subagents get isolated scratchpads (unique UUID-based session ID in run_ephemeral()).

Todo — checklist for tracking multi-step plans. Operations: set (replace all tasks), update (set status of one task), read. Statuses: pending, in_progress, done, failed, skipped.


Image tool flow

When image_view succeeds, it returns ToolResult with metadata={"is_image": True, "base64": "..."}.

The agent detects this and appends a synthetic user message with the image to session.context (but not session.messages). This makes the image visible to the next LLM call without polluting the display history.

See sessions.md for the dual-buffer design.