Skip to main content

Tool System

Loom’s tool system provides AI agents with capabilities to interact with the development environment through structured JSON schemas. Tools are implemented in loom-cli-tools and registered at runtime.

Architecture

Key components:
  • ToolRegistry: Central registry for all available tools
  • ToolContext: Execution context (workspace root, environment)
  • ToolDefinition: JSON schema for LLM consumption
  • ToolExecutionOutcome: Result type (success or error)

Tool Registration

Tools are registered during CLI initialization:

Built-in Tools

read_file

Read file contents from the workspace.
path
string
required
Path to file (absolute or relative to workspace)
max_bytes
integer
Maximum bytes to read (default: 1MB)
Returns:
Features:
  • Path validation (prevents directory traversal)
  • Workspace boundary enforcement
  • Automatic truncation for large files
  • UTF-8 lossy conversion

edit_file

Apply snippet-based edits to files.
path
string
required
Path to file (created if doesn’t exist)
edits
array
required
List of edit operationsEach edit:
  • old_str: Text to find (empty string for new files)
  • new_str: Replacement text
  • replace_all: Replace all occurrences (default: false)
Returns:
Edit semantics:
  • Edits applied sequentially
  • If old_str is empty: append new_str to file (create if needed)
  • If old_str found once: replace with new_str
  • If old_str found multiple times: error (unless replace_all: true)
  • If old_str not found: error

bash

Execute shell commands in the workspace.
command
string
required
Shell command to execute
cwd
string
Working directory (relative to workspace, default: workspace root)
timeout_secs
integer
Timeout in seconds (default: 60, max: 300)
Returns:
Features:
  • Runs commands via sh -c
  • Respects workspace boundaries (cwd validation)
  • Automatic timeout (prevents hanging)
  • Output truncation (256KB per stream)
  • Captures both stdout and stderr
The bash tool can execute arbitrary commands. Always validate inputs and enforce workspace boundaries.

list_files

List files in a directory (glob-like functionality).
path
string
Directory path (default: workspace root)
recursive
boolean
List files recursively (default: false)
max_depth
integer
Maximum recursion depth (default: 10)
Returns:
Perform web searches via Loom server proxy.
query
string
required
Search query in natural language
max_results
integer
Maximum results (default: 5, max: 10)
Implementation: Proxies to server endpoint: POST /proxy/cse Providers:
  • WebSearchToolGoogle: Google Custom Search Engine
  • WebSearchToolSerper: Serper.dev API
Web search requires API keys configured on the server. The tool automatically retries on transient failures using exponential backoff.

oracle

Reserved for future use (AI model introspection).

Tool Context

Every tool receives a ToolContext with:
Usage:

Error Handling

Tools return Result<serde_json::Value, ToolError>:
Error propagation:
1

Tool returns error

2

Executor wraps error

3

Error sent to LLM

4

LLM retries or adapts

The agent can correct the path or try a different approach.

Security

Path Validation

All file tools validate paths:
Prevents:
  • Directory traversal (../../../etc/passwd)
  • Absolute paths outside workspace (/etc/shadow)
  • Symlink escape (via canonicalize())

Bash Sandboxing

  • Commands run in workspace subdirectory
  • No network access (unless container allows)
  • Timeout prevents infinite loops
  • Output truncation prevents memory exhaustion

Resource Limits

Testing

Loom tools use property-based testing with proptest:
Test coverage:
  • Path validation (traversal, absolute, symlinks)
  • Content preservation (UTF-8, truncation)
  • Error conditions (not found, permissions)
  • Edge cases (empty files, large files)

Adding Custom Tools

1

Implement the Tool trait

2

Register in the registry

3

Write tests

Best Practices

Validate all inputs

Use schema validation and runtime checks. Never trust LLM-generated arguments.

Enforce resource limits

Set timeouts, max sizes, and depth limits to prevent abuse.

Return structured errors

Provide clear error messages the LLM can understand and act on.

Test with proptest

Use property-based testing to find edge cases.

Log tool execution

Use tracing for debugging: tracing::debug!("executing tool")

Keep tools atomic

One tool = one operation. Compose complex workflows in the agent layer.