Skip to content

Tools

Sonika AI Toolkit includes 18 built-in tools and supports custom tool creation via Pydantic.

Built-in Tools

Core File & System Tools

Tool Risk Description
RunBashTool 2 Execute shell commands (arbitrary code — always gated in ask mode)
BashSafeTool 1 Restricted shell: rejects metacharacters (; \| & $ \ > <`…) and destructive binaries by basename. Risk-reduction, NOT a sandbox
ReadFileTool 1 Read file contents (can exfiltrate any readable file into the model context)
WriteFileTool 1 Write content to files
ListDirTool 0 List directory contents
DeleteFileTool 2 Delete files
FindFileTool 0 Case-insensitive glob file search
RunPythonTool 2 Execute Python code (arbitrary code — always gated in ask mode)

All five file tools accept an optional root="/allowed/dir" constructor kwarg: every path is realpath-resolved and must stay under root (blocks ../ traversal and symlink escape). Without root the model can touch any path the process can — including the orchestrator's own MEMORY.md, whose contents are injected into future system prompts (memory poisoning). Set root in any deployment handling untrusted input.

Network & API Tools

Tool Risk Description
CallApiTool 1 Make HTTP API calls
SearchWebTool 0 Search the web (Serper API)
FetchWebPageTool 1 Fetch and extract web page content
EmailSMTPTool 1 Send emails via SMTP

CallApiTool and FetchWebPageTool ship an SSRF guard: URLs whose host resolves to loopback/private/link-local/reserved addresses (localhost, RFC1918 ranges, cloud metadata endpoints like 169.254.169.254) are rejected, and redirects are followed manually so every hop is re-checked. Pass allow_private_hosts=True at construction to call trusted internal hosts.

Secrets in tool args: values under keys matching password/token/secret/api_key/authorization/credential are masked as "***" in everything the orchestrator records (tools_executed, node_trace, approval interrupts) — the tool itself still receives the real value. Prefer sourcing credentials from env vars inside the tool over passing them as LLM-visible arguments.

Risk gating: in mode="ask", any tool with risk > 0 requires approval via a LangGraph interrupt. A tool that declares neither risk_level nor risk_hint is treated as risk 1 (gated) — unclassified tools never bypass the gate. In mode="auto" (the run/arun default) nothing is gated: only give the bot tools you trust it to run unattended.

Database Tools

Tool Description
SQLiteTool Query SQLite databases
PostgreSQLTool Query PostgreSQL databases
MySQLTool Query MySQL databases
RedisTool Interact with Redis

Integration Tools

Tool Description
EmailTool Send emails (simplified)
SaveContacto Save contact information

Signal Tools (internal)

These tools perform no action — the agents intercept their calls and react to them. You never register them yourself:

Tool Registered by Purpose
ask_user enable_user_questions=True Structured questions to the caller (interrupt / BotResponse.questions)
set_plan enable_planning=True (OrchestratorBot) Announce the structured execution plan
update_step enable_planning=True (OrchestratorBot) Report per-step progress (running/done/skipped/error)

Using Tools with Agents

from sonika_ai_toolkit import (
    OrchestratorBot, OpenAILanguageModel,
    RunBashTool, ReadFileTool, WriteFileTool, SearchWebTool,
)

llm = OpenAILanguageModel("sk-...", model_name="gpt-4o-mini")
bot = OrchestratorBot(
    strong_model=llm,
    fast_model=llm,
    instructions="You are a helpful assistant.",
    tools=[RunBashTool(), ReadFileTool(), WriteFileTool(), SearchWebTool()],
    memory_path="/tmp/bot_memory",
)

result = bot.run("List all Python files in the current directory")

Creating Custom Tools

Define a custom tool using Pydantic for the argument schema:

from pydantic import BaseModel, Field
from langchain_core.tools import BaseTool

class WeatherInput(BaseModel):
    city: str = Field(..., description="City name")
    units: str = Field("celsius", description="Temperature units: celsius or fahrenheit")

class WeatherTool(BaseTool):
    name: str = "get_weather"
    description: str = "Get current weather for a city"
    args_schema: type = WeatherInput

    def _run(self, city: str, units: str = "celsius") -> str:
        # Your implementation here
        return f"Weather in {city}: 22°C, sunny"

# Use with any agent
bot = OrchestratorBot(strong_model=llm, fast_model=llm, instructions="...", tools=[WeatherTool()])

args_schema required

Tools must have an args_schema (Pydantic model) for the LLM to correctly generate parameters.

Tool Registry

from sonika_ai_toolkit.tools.registry import ToolRegistry

registry = ToolRegistry()
registry.register(WeatherTool())
registry.get("get_weather")
registry.list_tools()

# Get tool descriptions formatted for LLM prompts
descriptions = registry.get_tool_descriptions()

Top-Level Imports

from sonika_ai_toolkit import (
    RunBashTool, BashSafeTool,
    ReadFileTool, WriteFileTool, ListDirTool, DeleteFileTool, FindFileTool,
    CallApiTool, SearchWebTool, FetchWebPageTool,
    RunPythonTool, GetDateTimeTool,
    EmailSMTPTool, SQLiteTool, PostgreSQLTool, MySQLTool, RedisTool,
)