Tools are the agent's actions. All tools implement the Tool ABC from navi/tools/base.py.
navi/tools/)Registered in build_default_registries() as builtins. Never removed on hot-reload.
| Tool | Name | Description |
|---|---|---|
WebSearchTool |
web_search |
DuckDuckGo search |
WebViewTool |
web_view |
Fetch and render a URL |
FilesystemTool |
filesystem |
Read/write/list local files (path restrictions via config) |
HttpRequestTool |
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 into remote hosts; connection pool keyed by session ID |
ImageViewTool |
image_view |
Load image from path/URL → returns 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 |
WriteToolTool |
write_tool |
Write a new user tool file and reload immediately |
ListToolsTool |
list_tools |
Return the live tool list from registry |
ToolManualTool |
tool_manual |
Return manuals/{name}.md or auto-generate from schema |
MemorySaveTool |
memory_save |
Save a fact to long-term memory |
MemorySearchTool |
memory_search |
Search long-term memory facts |
MemoryForgetTool |
memory_forget |
Delete a fact from long-term memory |
SpawnAgentTool |
spawn_agent |
Spawn an isolated subagent (blocking, synchronous from caller's view) |
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 |
DeleteToolTool |
delete_tool |
Delete a user tool file |
TestToolTool |
test_tool |
Run a user tool and verify its output |
ReflectTool |
reflect |
Self-reflection and analysis |
tools/*.py)Written by the agent via write_tool or manually. Auto-discovered at startup.
_ 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.
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.
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: booloutput: str — always a string; LLM sees thiserror: 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)navi/tools/loader.py)load_tools_from_dir(tools_dir) returns LoadResult(loaded, errors).
Load order:
name, description, parameters, execute).Tool subclasses).Errors are isolated per file — one broken file does not prevent others from loading. Errors are logged and returned in LoadResult.errors.
reload_tools tool calls ToolRegistry.reload_user_tools(tools_dir):
_builtin_names.load_tools_from_dir.New tools become available from the next user message (tool schemas are built at run_stream() entry, not during execution).
write_toolWriteToolTool validates the code before writing (checks for the 4 required definitions). On success:
tools/{name}.py.tools/enabled.json.reload_user_tools() — tool is registered immediately.The agent should call tool_manual("write_tool") before using write_tool for the first time — the manual at manuals/write_tool.md has the full format reference and a complete example.
Both are per-session, stored in-memory keyed by current_session_id.
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.
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.