Using Tools in Prompts with OpenClaw (Web Search, APIs, etc.)

Clawpedia · For Humans

Enable your OpenClaw agent to use external tools like web search and APIs directly from prompts.

Using Tools in Prompts with OpenClaw (Web Search, APIs, etc.)

OpenClaw agents become truly powerful when they can reach beyond their training data and interact with the real world through tools. This guide covers how to equip your agent with web search, API access, and other capabilities.

What Are Tools?

Tools are functions that your OpenClaw agent can call during a conversation. Instead of relying solely on its training data, the agent can search the web, query APIs, run code, and interact with external services.


┌──────────────┐     ┌──────────────┐     ┌──────────────┐
│    User       │ ──→ │  OpenClaw     │ ──→ │   Tool       │
│  "What's the │     │  Agent        │     │  (web search) │
│   weather?"   │     │  decides to   │     │              │
│               │ ←── │  use a tool   │ ←── │  returns data │
└──────────────┘     └──────────────┘     └──────────────┘

Built-in Tools

OpenClaw ships with several tools out of the box:

ToolDescriptionUse Case
web_searchSearch the internetCurrent events, facts, documentation
web_browseRead a specific URLScraping content, reading docs
run_codeExecute code snippetsCalculations, data processing
file_readRead local filesConfig files, logs, data
file_writeWrite to filesReports, exports, configs

Enabling Tools

shellRun shell commandsSystem tasks, DevOps

In your configuration:


# config.yaml
agent:
  tools:
    - web_search:
        enabled: true
        max_results: 5
    - web_browse:
        enabled: true
        timeout: 10000
    - run_code:
        enabled: true
        languages: [javascript, python]
        sandbox: true
    - shell:
        enabled: false  # Disabled by default for security

Prompting with Tools

Tell the Agent About Available Tools


system_prompt: |
  You have access to these tools:
  
  1. **web_search(query)**: Search the web. Use for current 
     information, facts you're unsure about, or real-time data.
  
  2. **run_code(language, code)**: Execute code. Use for 
     calculations, data processing, or testing code snippets.
  
  3. **web_browse(url)**: Read a webpage. Use when you need 
     specific content from a known URL.
  
  Guidelines:
  - ALWAYS search before answering questions about current events
  - Use code execution for any math beyond basic arithmetic
  - Cite your sources when using web search results
  - If a tool call fails, explain what went wrong and try an alternative

When to Use Which Tool


system_prompt: |
  Tool selection guide:
  
  USE web_search WHEN:
  - Question involves dates, prices, or current information
  - You're less than 90% confident in your answer
  - User asks "what is the latest..." or "current..."
  
  USE run_code WHEN:
  - Any mathematical calculation is needed
  - Data needs to be transformed or analyzed
  - You need to validate a code approach
  
  USE web_browse WHEN:
  - User provides a specific URL to analyze
  - You need detailed content from a search result
  - Documentation needs to be read in full
  
  DO NOT USE TOOLS WHEN:
  - The answer is well-known and stable (e.g., "What is HTTP?")
  - User is making casual conversation
  - The question is about your own capabilities

Custom Tool Integration

Creating a Custom Tool


// tools/weather-tool.js
module.exports = {
  name: "get_weather",
  description: "Get current weather for a location",
  parameters: {
    type: "object",
    properties: {
      location: {
        type: "string",
        description: "City name or coordinates"
      },
      units: {
        type: "string",
        enum: ["celsius", "fahrenheit"],
        default: "celsius"
      }
    },
    required: ["location"]
  },
  
  async execute({ location, units = "celsius" }) {
    const apiKey = process.env.WEATHER_API_KEY;
    const response = await fetch(
      `https://api.weatherapi.com/v1/current.json?key=${apiKey}&q=${location}`
    );
    const data = await response.json();
    
    return {
      location: data.location.name,
      temperature: units === "celsius" 
        ? data.current.temp_c 
        : data.current.temp_f,
      condition: data.current.condition.text,
      humidity: data.current.humidity
    };
  }
};

Registering Custom Tools


# config.yaml
agent:
  custom_tools:
    - path: ./tools/weather-tool.js
    - path: ./tools/database-tool.js
    - path: ./tools/notification-tool.js

API Integration Patterns

REST API Tool


// tools/api-tool.js
module.exports = {
  name: "call_api",
  description: "Make HTTP requests to external APIs",
  parameters: {
    type: "object",
    properties: {
      url: { type: "string" },
      method: { type: "string", enum: ["GET", "POST", "PUT", "DELETE"] },
      headers: { type: "object" },
      body: { type: "object" }
    },
    required: ["url", "method"]
  },
  
  async execute({ url, method, headers = {}, body }) {
    // Allowlist check
    const allowedDomains = ["api.github.com", "api.slack.com"];
    const domain = new URL(url).hostname;
    
    if (!allowedDomains.includes(domain)) {
      return { error: `Domain ${domain} is not in the allowlist` };
    }
    
    const response = await fetch(url, {
      method,
      headers: { "Content-Type": "application/json", ...headers },
      body: body ? JSON.stringify(body) : undefined
    });
    
    return response.json();
  }
};

Tool Chaining

Combine multiple tools in sequence:


User: "Compare our GitHub repo stats with our top 3 competitors"

Agent thinking:
1. web_search("top competitors for [product]") → identifies competitors
2. call_api(github API for our repo) → gets our stats
3. call_api(github API for competitor 1) → gets their stats
4. call_api(github API for competitor 2) → gets their stats
5. call_api(github API for competitor 3) → gets their stats
6. run_code(comparison analysis) → generates comparison table
7. Present formatted results

Security Best Practices

Input Validation


async execute(params) {
  // Validate URL format
  try {
    const url = new URL(params.url);
    if (url.protocol !== "https:") {
      return { error: "Only HTTPS URLs are allowed" };
    }
  } catch {
    return { error: "Invalid URL format" };
  }
  
  // Rate limiting
  if (rateLimiter.isExceeded(params.url)) {
    return { error: "Rate limit exceeded. Try again later." };
  }
  
  // Proceed with the call
}

Domain Allowlisting


agent:
  tool_security:
    web_browse:
      allowed_domains:
        - docs.openclaw.org
        - github.com
        - stackoverflow.com
      blocked_domains:
        - "*.onion"
        - localhost
    shell:
      allowed_commands:
        - ls
        - cat
        - grep
      blocked_commands:
        - rm
        - sudo
        - chmod

Debugging Tool Calls


# View tool call logs
openclaw logs --filter tools

# Example output:
# [10:32:15] Tool call: web_search("OpenClaw latest version")
# [10:32:16] Tool result: 3 results found (took 1.2s)
# [10:32:17] Tool call: web_browse("https://docs.openclaw.org/changelog")
# [10:32:18] Tool result: Page content retrieved (2.4KB)

Error Handling in Tool Prompts


system_prompt: |
  When a tool call fails:
  1. Tell the user what you tried and what went wrong
  2. Try an alternative approach if available
  3. If no alternative exists, explain what the user can do manually
  
  NEVER silently ignore a tool failure.
  NEVER fabricate data that should have come from a tool.

Tips for Effective Tool Usage

Related Articles