Skip to content

Tools System

Eshan Roy edited this page Jun 30, 2026 · 6 revisions

Tools System

M31 Autonomous (M31A) provides a curated set of tools that the LLM can invoke to interact with the filesystem, run commands, search code, and access the web. Tools are registered on a Dispatcher that handles permissions, rate limiting, and execution.

Architecture

flowchart TD
    LLM[LLM Response<br/>tool_call chunks] --> Engine[workflow/engine.go<br/>consumeStreamWithTools]
    Engine --> Dispatcher[tools/dispatcher.go<br/>Execute ToolCall]
    Dispatcher --> Rate[Rate Limiter<br/>token bucket]
    Dispatcher --> Perm[Permission Check<br/>rules + risk level]
    Dispatcher --> Lookup[Tool Lookup<br/>by name]
    Lookup --> Exec[Tool.Execute<br/>ctx, input]
    Exec --> Result[ToolResult]
    Result --> LLM

    style LLM fill:#e1f5fe
    style Dispatcher fill:#fff3e0
    style Result fill:#e8f5e9
Loading

Built-in Tools

Bash

Source: internal/tools/bash.go

Property Value
Risk Level dangerous
Timeout 30 minutes (configurable per call, max 1800s)
Output Limit 50,000 characters
Schema {command: string, timeout?: integer}

Features:

  • Process group management (SIGINT then SIGKILL after grace period)
  • Non-interactive environment variables (CI=true, DEBIAN_FRONTEND=noninteractive)
  • Stdin closed immediately to prevent hangs
  • Binary output detection (null byte check)
  • Output truncation with [... output truncated] marker
  • Concurrent stdout/stderr reading with per-stream buffers

FileRead

Source: internal/tools/fileread.go

Property Value
Risk Level safe
Max File Size 5 MB

Features:

  • Line offset and limit for partial reads
  • Line number prefix (cat -n format)
  • Long line truncation (>2000 chars)
  • Support for images and PDFs (rendered as attachments)

FileWrite

Source: internal/tools/filewrite.go

Property Value
Risk Level medium

Features:

  • Atomic writes (temp file + rename)
  • Auto-backup before overwrite (configurable, max 10 backups per file)
  • Directory auto-creation for new file paths

Edit

Source: internal/tools/edit.go

Property Value
Risk Level dangerous

Features:

  • Exact string replacement (old_string → new_string)
  • Line-range replacement (start_line + end_line + new_string)
  • Cascading replace: 7 strategies (exact, line-trimmed, whitespace-normalized, indent-normalized, line-skip, fuzzy-anchor)
  • Levenshtein similarity for fuzzy matching
  • replace_all flag for batch replacements
  • LCS-based diff summary generation
  • Same atomic write and backup as FileWrite

Glob

Source: internal/tools/glob.go

Property Value
Risk Level safe
Max Results 1,000 (configurable)

Features:

  • Standard glob patterns (**/*.go, src/**/*.ts)
  • Fallback retry with *.<ext> pattern when no matches
  • Sorted results by modification time
  • Skip directories: node_modules, vendor, .next, dist, build, target, .venv, __pycache__

Grep

Source: internal/tools/grep.go

Property Value
Risk Level safe
Max Results 100 (configurable)
Pattern Length Capped to prevent ReDoS

Features:

  • Ripgrep backend when available, pure-Go fallback otherwise
  • Full regex support with fixed_string mode for literal searches
  • File type filtering (include glob parameter)
  • Context lines (before/after match)
  • Ring buffer streaming mode: O(contextLines) memory when context > 0, O(1) when context = 0
  • ReDoS protection: rejects nested/adjacent quantifier patterns
  • Gitignore-aware file filtering with mtime-based cache
  • Result truncation with count reporting

FileDelete

Source: internal/tools/filedelete.go

Property Value
Risk Level destructive

Features:

  • Auto-backup before deletion
  • Path validation (prevents traversal attacks)

FileMove

Source: internal/tools/filemove.go

Property Value
Risk Level medium

FileList

Source: internal/tools/filelist.go

Property Value
Risk Level safe

CodeMap

Source: internal/tools/codemap.go

Property Value
Risk Level safe

Features:

  • Project structure mapping
  • Symbol extraction
  • Dependency graph generation

WebFetch

Source: internal/tools/webfetch.go

Property Value
Risk Level medium
Max Redirects 5 (configurable)

Features:

  • HTTP to HTTPS auto-upgrade
  • HTML to markdown conversion
  • SSRF protection (blocks private, loopback, link-local IPs)
  • Custom User-Agent header
  • Content type detection

WebSearch

Source: internal/tools/websearch.go

Property Value
Risk Level safe

Features:

  • SearXNG meta-search engine backend
  • No API key required
  • Configurable instance URL
  • Structured results (title, URL, snippet)

TodoWrite

Source: internal/tools/todo.go

Property Value
Risk Level safe

Features:

  • Task tracking within the session
  • Stored in session directory

TodoRead

Source: internal/tools/todoread.go

Property Value
Risk Level safe
Schema `{status?: "pending"

Features:

  • Reads and parses TODO.md from the session directory
  • Filters items by status (pending, in_progress, completed, cancelled, or all)
  • Returns structured summary with counts per status
  • Thread-safe session ID via atomic.Value
  • Read-only companion to TodoWrite

AskUserQuestion

Source: internal/tools/question.go

Property Value
Risk Level safe

Features:

  • Structured questions with multiple-choice options
  • Per-request response routing (prevents cross-caller mix-ups)
  • Timeout support

Agent

Source: internal/tools/agent.go

Property Value
Risk Level medium

Features:

  • Spawns parallel subagents with isolated worktrees
  • Background execution support
  • See Subagents for details

CodeComplexity

Source: internal/tools/codecomplexity.go

Property Value
Risk Level safe
Schema {skip_dirs?: string[]}

Features:

  • Scans Go source files in the project directory
  • Counts files and lines per package and per file
  • Ranks top packages and files by size
  • Produces a complexity score (low, medium, high)
  • Respects skip directories (configurable, merges with defaults)

See CodeComplexity Tool for detailed usage.

DevServer

Source: internal/tools/devserver.go

Property Value
Risk Level medium
Schema `{action: "start"

Features:

  • Start development servers (e.g., npm run dev, python -m http.server)
  • Stop running servers by ID with process group cleanup
  • List all running servers with uptime and port info
  • Check if a port is accepting connections
  • Cross-platform process management (Unix process groups, Windows taskkill)
  • Auto-cleanup on agent shutdown via StopAll()

HTTPCheck

Source: internal/tools/httpcheck.go

Property Value
Risk Level safe
Timeout 15 seconds per request
Schema {url: string, method?: string, expected_status?: number, expected_content?: string[], not_expected_content?: string[], max_body_bytes?: number}

Features:

  • HTTP requests with configurable method, expected status, and content validation
  • Positive and negative content assertions (expected_content / not_expected_content)
  • Redirect limit (10 max) and configurable body size cap (1MB default)
  • Used during runtime verification phase for smoke testing dev servers

Default Registration

All 19 tools are registered in internal/tools/defaults.go:

func DefaultDispatcher(workDir, backupDir, sessionsDir string, cfg *PermissionsConfig) (*Dispatcher, error) {
    d := NewDispatcher(cfg)
    d.Register(NewBash(workDir))
    d.Register(NewFileRead(workDir))
    d.Register(NewFileWrite(workDir, backupDir))
    d.Register(NewEdit(workDir, backupDir))
    d.Register(NewTodoWrite(sessionsDir, ""))
    d.Register(NewWebFetch(sessionsDir, false))
    d.Register(NewWebSearch(""))
    d.Register(NewAskUserQuestion(...))
    d.Register(NewGlob(workDir))
    d.Register(NewGrep(workDir))
    d.Register(NewFileList(workDir))
    d.Register(NewFileDelete(workDir, backupDir))
    d.Register(NewFileMove(workDir))
    d.Register(NewCodeMap(workDir))
    d.Register(NewCodeComplexity(workDir))
    d.Register(NewDevServer(workDir))
    d.Register(NewHTTPCheck())
    // Agent tool registered separately on parent dispatcher
    return d, nil
}

Dispatcher

Source: internal/tools/dispatcher.go

The Dispatcher is the central hub for tool execution. It provides:

Rate Limiting

Token bucket algorithm prevents resource exhaustion from LLMs generating excessive tool calls:

  • Burst capacity: ToolRateLimitBurst
  • Refill rate: ToolRateLimitPerSec
  • Background goroutine refills tokens; stopped via Stop() with sync.Once safety

Permission System

Every tool execution passes through ensurePermission():

  1. Rule matching -- Checks tool name and arguments against configured rules
  2. Risk assessment -- Classifies as safe, medium, dangerous, or destructive
  3. Agent defaults -- Per-agent permission profiles
  4. Interactive prompt -- Modal in the TUI (allow / allow always / deny / exit)
  5. Non-interactive fallback -- Blocks dangerous tools in shell mode

Input Normalization

The dispatcher handles two input formats from LLMs:

  • Nested: {"name":"Bash", "params":{"command":"ls"}}
  • Direct: {"name":"Bash", "command":"ls"}

Both are normalized to the same internal ToolInput struct.

Parameter Limit

Input is capped at 1000 parameters per tool call to prevent abuse.

Permission Request/Response Protocol

Communication between the dispatcher and TUI uses channels:

Dispatcher ──(PermissionRequest)──→ TUI modal
Dispatcher ←──(PermissionResponse)── TUI user action

Each request has a monotonically increasing ID (atomic counter) for routing responses to the correct waiter. Per-request channels prevent cross-caller response mix-ups in concurrent scenarios.

Clone this wiki locally