Skip to main content

What are Tools?

Tools are the actions agents can take to interact with the world. They’re how agents read files, execute commands, search the web, and accomplish real tasks. When an agent receives a request, it decides which tools to use, calls them with appropriate parameters, receives the results, and uses that information to continue reasoning or respond to the user.

The Tool-Use Loop

┌──────────────────────────────────────────────────────────┐
│                     AGENT LOOP                            │
│                                                          │
│   User Input ──► LLM Decision ──► Tool Execution ──┐    │
│        ▲                                           │    │
│        │                                           │    │
│        └──────── Result Processing ◄───────────────┘    │
│                                                          │
│                  (Repeat until task complete)            │
└──────────────────────────────────────────────────────────┘
1

Receive Input

Agent receives a message from the user via a channel.
2

LLM Decision

The LLM analyzes the request and decides which tool(s) to use.
3

Tool Execution

klaw executes the tool with the provided parameters (2-minute timeout).
4

Result Processing

Tool output is formatted and fed back to the LLM.
5

Continue or Respond

LLM either calls more tools or generates a final response.

Built-in Tools

klaw includes 11 powerful tools out of the box:

Command Execution

bash

Execute shell commands with full system access.
{
  "tool": "bash",
  "input": {
    "command": "git status",
    "timeout": 30000
  }
}
Features:
  • 2-minute default timeout
  • Working directory preservation
  • Exit code and output capture
  • Streaming output for long commands

File Operations

read

Read file contents with line numbers.
{
  "tool": "read",
  "input": {
    "path": "/src/main.go",
    "offset": 0,
    "limit": 100
  }
}

write

Create or overwrite files.
{
  "tool": "write",
  "input": {
    "path": "/src/new.go",
    "content": "package main..."
  }
}

edit

Precise string replacement in files.
{
  "tool": "edit",
  "input": {
    "path": "/src/main.go",
    "old_string": "func old()",
    "new_string": "func new()"
  }
}

glob

Find files by pattern.
{
  "tool": "glob",
  "input": {
    "pattern": "**/*.go",
    "path": "/src"
  }
}

grep

Search file contents with regex.
{
  "tool": "grep",
  "input": {
    "pattern": "func.*Error",
    "path": "/src",
    "type": "go"
  }
}

web_search

Search the internet.
{
  "tool": "web_search",
  "input": {
    "query": "golang context best practices"
  }
}

Web

web_fetch

Fetch and process web content.
{
  "tool": "web_fetch",
  "input": {
    "url": "https://example.com/api/docs",
    "prompt": "Extract the authentication methods"
  }
}
Features:
  • HTML to markdown conversion
  • AI-powered content extraction
  • Redirect handling
  • 15-minute cache

Agent Management

agent_spawn

Create specialized sub-agents.
{
  "tool": "agent_spawn",
  "input": {
    "name": "researcher",
    "task": "Find best practices for API design"
  }
}

skill

Install and manage skills.
{
  "tool": "skill",
  "input": {
    "action": "install",
    "name": "docker"
  }
}

Scheduling

cron

Schedule recurring tasks.
{
  "tool": "cron",
  "input": {
    "schedule": "0 9 * * *",
    "task": "Check for security updates"
  }
}

Tool Schema

Each tool defines a JSON schema for its parameters:
type Tool interface {
    // Name returns the tool identifier
    Name() string

    // Description explains what the tool does
    Description() string

    // Schema returns JSON schema for parameters
    Schema() map[string]interface{}

    // Execute runs the tool with given input
    Execute(ctx context.Context, input map[string]interface{}) (string, error)
}

Example Schema (bash)

{
  "type": "object",
  "properties": {
    "command": {
      "type": "string",
      "description": "The command to execute"
    },
    "timeout": {
      "type": "integer",
      "description": "Timeout in milliseconds",
      "default": 120000
    },
    "workdir": {
      "type": "string",
      "description": "Working directory for command"
    }
  },
  "required": ["command"]
}

Tool Execution Flow

When an agent calls a tool:
┌─────────────────────────────────────────────────────────────┐
│ Tool Call: bash                                             │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ $ git log --oneline -5                                  │ │
│ └─────────────────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ Result:                                                     │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ a1b2c3d Fix authentication bug                          │ │
│ │ e4f5g6h Add user dashboard                              │ │
│ │ i7j8k9l Update dependencies                             │ │
│ │ m0n1o2p Initial commit                                  │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘

Tool Permissions

Control which tools agents can access:
# Agent with limited tools
[agent.restricted]
name = "restricted"
tools = ["read", "glob", "grep"]  # Read-only access

Permission Levels

LevelToolsUse Case
Read-onlyread, glob, grepCode review, analysis
File ops+ write, editDevelopment
Full+ bash, webAutomation, devops
Admin+ agent_spawn, skillAgent management

Custom Tools

Create custom tools by implementing the Tool interface:
package tools

type MyCustomTool struct{}

func (t *MyCustomTool) Name() string {
    return "my_tool"
}

func (t *MyCustomTool) Description() string {
    return "Does something custom"
}

func (t *MyCustomTool) Schema() map[string]interface{} {
    return map[string]interface{}{
        "type": "object",
        "properties": map[string]interface{}{
            "input": map[string]interface{}{
                "type":        "string",
                "description": "The input to process",
            },
        },
        "required": []string{"input"},
    }
}

func (t *MyCustomTool) Execute(ctx context.Context, input map[string]interface{}) (string, error) {
    // Your logic here
    return "Result", nil
}
Register the tool:
registry := tool.NewRegistry()
registry.Register(&MyCustomTool{})

Tool Output Formatting

Tool results are formatted for LLM consumption:
╭──────────────────────────────────────────╮
│ Tool: bash                               │
│ Command: ls -la /src                     │
├──────────────────────────────────────────┤
│ total 32                                 │
│ drwxr-xr-x  5 user  staff  160 Dec 14    │
│ -rw-r--r--  1 user  staff  1234 Dec 14   │
│ ...                                      │
╰──────────────────────────────────────────╯

Timeouts and Limits

SettingDefaultDescription
Tool timeout2 minutesMax execution time per tool
Output limit30,000 charsTruncation threshold
Concurrent tools1Tools execute sequentially
Override in config:
[tools]
timeout = 300000  # 5 minutes
output_limit = 50000

Best Practices

Only grant bash access when truly needed. Use specific file tools when possible.
Long-running commands should have explicit timeouts to prevent hanging.
Set workdir to limit file operations to specific directories.
Tool outputs are visible in the conversation. Sensitive data may be exposed.

Next Steps