🏠 Home ← Docs Index
Open Beta 📖 Interactive Reader Raw .md llms.txt

Tools & Skills User Guide

GoClaw provides a powerful ecosystem of tools and skills that enable the agent to interact with your system, data, and external services.

Tools (Function Calling)

Tools are capabilities that the agent can actively execute. GoClaw features a library of over 100 built-in tools (ranging from file operations and web automation to database and observability integrations). To prevent context window bloat and keep the LLM focused, GoClaw utilizes a RAG Tool Filter to dynamically select and load only the relevant tools for each user query.

Core Tools

Category Tools Description
File Operations file_read, file_write, file_edit, read_file_lines, file_search, glob_files Read, write, and search files within the workspace. file_edit and apply_patch are preferred for precise changes.
Shell & System shell_exec, shell_exec_multi, process, clipboard Execute commands (one, or several in sequence), manage background processes, and interact with the system clipboard.
Git & GitLab git, gitlab, gitlab_hook Perform git operations and interact with GitLab projects, issues, and merge requests; have a project's events run a SOP (gitlab_hook, an admin in a conversation).
Web & Network web_search, web_fetch, browser, http_request Search the web, fetch content, automate headless Chrome, and make API requests. All of them go through the outbound HTTP policy.
Database db_query, mongo_query, db_write, db_analyze, db_enrich Query SQL (PostgreSQL, MySQL, ClickHouse) and MongoDB databases (read-only); db_write inserts, updates and deletes rows on datasources with allow_write: true. db_analyze reads a datasource's schema and caches it (the tables first, then one table's columns); db_enrich adds business notes — what a column means, what its values stand for — to that cached schema.
Memory memory_search, memory_get, memory_write, archive_search, archive_get Search and manage long-term agent memory and session archives.
Knowledge wiki_read, wiki_write, doc_index, review_learned, notes_distill Read and write the organisation wiki shared by all agents, and read the pages copied from Wiki.js; index a web page, wiki page or Markdown file in the workspace into searchable memory (admins); review learned facts held back as unverified (admins); clear resolved error notes and merge duplicate notes.
Communication message, notify, email Send messages to Discord/Teams, trigger notifications, and manage emails.
Data & Utilities json_transform, regex, text_utils, calc, datetime, spreadsheet, diff Process data, perform math, handle dates, and compare text.
Agent & Sessions agents_list, subagents, sessions_list, sessions_history, sessions_spawn, webhooks Manage multiple agents and conversation sessions; read the webhook routes and what each received (webhooks, admins).
SOP & Administration sop_list, sop_get, sop_save, sop_run, sop_versions, sop_rollback, sop_review, sop_approve, sop_pin_channel, cron, update_core_instruction, capability_request Manage SOPs (versions, rollback, review date, approving a step that waits for approval, the channel a SOP's notices go to) and scheduled jobs; set the agent's core instruction; record a missing tool, view or permission for IT to provide.
Infrastructure & Code grafana_alerts, grafana_alert_rule, graylog_query, graylog_alert, uptrace_query, uptrace_monitor, zabbix_query, zabbix_alert, wazuh_query, wazuh_alert, netbox, parse_unl, sonarqube, sonarqube_hook, codereview_pull_repo, project_blast_radius The observability tools and NetBox; read EVE-NG .unl topology files; query SonarQube (tools.sonarqube, or several instances under tools.sonarqubes); clone a repository, index its code structure and list every function that calls a given one, directly or through others.
Media & Docs image, pdf, document, diagram_render, generate_pdf, generate_html, voice_input, voice_output Analyze images; extract text from PDF, .docx and .pptx files; render a Mermaid diagram or raw HTML to a PNG with headless Chrome; generate PDF and HTML reports; transcribe an audio file and turn text into speech.
Output Navigation read_output Navigate large tool results (over tools.max_result_chars, default 8,000 characters) kept in memory for an hour — search, slice, or paginate without re-running the tool.
Tool Discovery search_tools Find a tool the agent may use but that was not selected for this request, and make it callable from the next step. A matching tool the caller's role may not use (an admin-only one, for a user) is never added: the search says it needs an administrator.

Configuration & Security

Shell Execution

Shell access is controlled via an allowlist in config.yaml:

tools:
  shell:
    allow: ["git *", "npm *", "ls"]    # Allowed command prefixes
    deny: ["npm publish"]              # Refused even when allow matches

Outbound HTTP

Every tool that calls a URL goes through one outbound policy, tools.http: http_request, web_fetch, web_search, the browser, MCP servers over HTTP/SSE, gitlab, sonarqube, the observability tools (Grafana, Graylog, Uptrace, Zabbix, Wazuh, NetBox), and the tools that read a file from a URL (pdf, document, image, spreadsheet).

The policy denies by default: with no tools.http settings, every request is refused.

An integration's own host is the exception. gitlab, sonarqube and the observability tools may reach the host of the url (or Uptrace dsn) configured for the instance they call, private address included, without an allow entry: it is the address you configured, not one the model chose. That host is opened to that tool only — http_request and the browser still need it on allow — and deny still refuses it. Any other host such a call reaches, a redirect elsewhere say, is checked as usual. The Integrations page's Test runs under the same rule.

tools:
  http:
    default_policy: deny       # the default; see below
    allow:
      - "api.search.brave.com" # web_search with Brave
      - "*.example.com"        # example.com and every subdomain
      - "wiki.internal"        # an internal host: its private address is allowed too
      - "10.0.0.17"            # a URL whose host is written as this IP
      - "10.0.0.0/24"          # URLs whose host is an IP in this range
    deny:
      - "169.254.169.254"      # cloud metadata endpoint
agents:
  list:
    - id: ops
      tools:
        http:
          allow: ["wiki.internal", "api.github.com"]   # this agent reaches only these

The policy is read on every request, so a change applies without a restart. To add a host from the command line:

goclaw config append tools.http.allow=api.example.com
Hosts per run

One agent run (the answer to one message, a SOP step, a cron job) may reach at most tools.http.max_hosts_per_run different hosts, 100 unless set. Every request a tool makes counts: http_request, web_fetch, web_search, notify and the integration tools. A subagent counts toward the run that started it. Once the run has reached the limit, a request to a new host is refused (host "…" refused: this run has already reached 100 different hosts), hosts it already reached keep working, and the gateway log says [http-policy] a run reached tools.http.max_hosts_per_run. The browser's page loads are not counted.

An assistant's turn reaches a few hosts, a research turn a few dozen; a run that keeps going from one host to the next is working through a list of addresses. Raise the limit for an agent that genuinely needs more, in its own tools.http; 0 turns it off.

tools:
  http:
    max_hosts_per_run: 100

When the gateway is reachable from other machines (gateway.bind is lan, all or a non-loopback address, or an ingress tunnel is set) and tools.shell.allow is ["*"] or tools.http.default_policy is allow with an empty allow list, globally or for one agent, the gateway logs a [config] WARNING naming the setting at start-up and on every config change that alters it. Anyone who can message such an agent can have it run any command or reach any host for them.

Git Operations

Read-only operations are always allowed. Write operations must be explicitly enabled:

tools:
  git:
    allow_write: true

An agent's own tools.git.allow_write (in its agents.list entry) overrides the global setting, in either direction. Even with writes enabled, the git tool refuses:

Database Connections

Configure datasources in config.yaml:

datasources:
  analytics:
    driver: clickhouse
    dsn: "clickhouse://localhost:9000/analytics"
  crm:
    driver: postgres
    dsn: "${secret:CRM_DSN}"
    allow_write: true   # opens this datasource to db_write and metrics_store writes

db_query runs SELECT, SHOW, DESCRIBE, EXPLAIN and WITH queries only, and refuses one that hides a write (a data-modifying WITH, EXPLAIN ANALYZE of a write, SELECT … INTO). It returns at most tools.max_db_query_rows rows (default 10,000).

The database enforces the same rules, so they hold if goclaw's own checks miss something and when goclaw stops waiting:

Engine Time limit (about 29s, under db_query's 30s) Read-only
PostgreSQL statement_timeout in the query's transaction; client_connection_check_interval (14+) ends a query whose gateway died A read-only transaction
MySQL max_execution_time transaction_read_only=1 on the read's connection, put back after the read; a connection that cannot be put back is closed. A read-only transaction alone still runs CREATE, DROP and other DDL
MariaDB max_statement_time as MySQL
ClickHouse max_execution_time (with timeout_overflow_mode=throw), where the account lets goclaw set it; otherwise the profile's own readonly=1, where the account allows it: writes, SET, and url(), file(), remote(), dictionary() or format() read as a table are refused. DESCRIBE TABLE url(…) still connects out, so goclaw's checks refuse those calls everywhere. Read a dictionary with dictGet()

A DBA's tighter limit on the account is kept: goclaw sets the lower of the two. That covers PostgreSQL's statement_timeout and idle_in_transaction_session_timeout (ALTER ROLE … SET), and MySQL's and MariaDB's session time limit. On PostgreSQL, a pool whose DSN asked for the simple protocol runs an approved saved query on it, so its values keep the types they had.

A query the database stops at its time limit comes back with a message telling the agent to narrow it. A query cannot raise its own limit: SET, set_config, MySQL's SET_VAR and MAX_EXECUTION_TIME hints and ClickHouse's SETTINGS clause are refused before the query is sent.

What the account allows decides what ClickHouse is sent, and goclaw logs one [db_limits] line per datasource saying what that is:

Over ClickHouse's HTTP interface, goclaw also sends cancel_http_readonly_queries_on_client_close where the account allows it. Otherwise a query whose client gave up kept running there.

ClickHouse turns a deadline into a setting of its own, so every query goclaw sends ClickHouse has none: health checks, db_write, metrics_store and org-directory lookups included.

goclaw learns what each server allows when the datasource is first used. When it cannot, for example because the server is busy, db_query makes do for a minute and then tries again; Postgres still gets statement_timeout. A PostgreSQL DSN that asks for the simple protocol (default_query_exec_mode=simple_protocol, common with PgBouncer) is opened on the extended protocol without named prepared statements, which works through PgBouncer.

Every datasource is read-only unless it sets allow_write: true. On those, db_write can insert rows, and update or delete them by key (where takes equality, null and lists — no operators). Only admins and admin-authored SOP/cron runs are offered the tool; ordinary users, webhook-triggered runs and delegated SOP runs are refused. One call changes at most tools.max_db_write_rows rows (default 100): an update or delete that would change more is rolled back and nothing is written. ClickHouse datasources accept insert only; MongoDB is not supported.

GitLab Integration Setup

To use the gitlab tool, you need a Personal Access Token (PAT):

  1. Go to User Settings → Access Tokens in GitLab.
  2. Create a token with api and read_repository scopes.
  3. Configure it in config.yaml using an environment variable for security:
tools:
  gitlab:
    url: https://gitlab.com
    token: "${env:GITLAB_TOKEN}"
    allow_write: false

More GitLab instances go under tools.gitlabs, by name; the agent picks one with the tool's instance argument, and without it uses tools.gitlab:

tools:
  gitlabs:
    internal:
      url: https://gitlab.example.com
      token: "${secret:GITLAB_INTERNAL_TOKEN}"
      auth_type: oauth      # "pat" (default) sends PRIVATE-TOKEN; "oauth" sends Authorization: Bearer
      allow_write: true
      description: "Internal services"   # helps the agent choose the instance

An agent with its own tools.gitlab (in its agents.list entry) uses that instance for every call. The GitLab host needs no entry on tools.http.allow (see Outbound HTTP).


Tool Testing & Benchmarking (CLI)

You can call any registered tool directly from the command line — without starting the gateway or involving an LLM. This is useful for testing configurations, debugging tool output, and measuring latency.

List all tools

goclaw tools list

Execute a tool directly

# Basic call
goclaw tools exec datetime action=now

# Multiple args (auto-typed)
goclaw tools exec gitlab action=mrs_list project=group/repo page=2

# SQL query
goclaw tools exec db_query datasource=analytics query="SELECT count(*) FROM users"

Arguments use key=value syntax with automatic type detection:

Value Parsed as
page=2 number (as in a model's tool call)
active=true bool
name=hello string
"id='12345'" string (quoted, so it is not read as a number)
'filters={"status":"open"}' JSON object

The shell removes one level of quotes before GoClaw sees the argument: wrap a value that must stay a string in a second pair of quotes, and quote JSON and anything with *, ? or spaces. The tool reference lists each tool's arguments.

Output shows the full result (never truncated), execution time, char count, and line count.

Benchmark a tool

goclaw tools bench datetime action=now --runs=20
goclaw tools bench memory_search query=test --runs=10
Bench: datetime — 20 runs
  Min:    1ms
  Max:    8ms
  Avg:    3ms
  P95:    6ms
  Errors: 0 / 20
Last output (chars: 25):
2026-03-27T11:50:47+08:00

Skills (Context Injection)

Skills are Markdown files that provide specialized knowledge or best practices to the agent. Unlike tools, skills are injected into the agent's system prompt as reference material.

Managing Skills via CLI

Command Description
skills list List all available skills
skills install <source> Install a skill from a registry, URL, GitHub ref, or local path
skills show <name> View the content of a specific skill
skills remove <name> Uninstall a user-provided skill

Built-in Skills

GoClaw comes with built-in skills, including:

Custom Skills

You can add your own skills by placing .md files (or <name>/SKILL.md folders) in:

A skill with the same name as an earlier one replaces it, in this order: built-in, the agent's plugins, the workspace, the user-level directory.


Model Context Protocol (MCP)

GoClaw supports the Model Context Protocol, allowing the agent to connect to external MCP servers to gain additional tools and resources. Use the mcp tool to interact with configured servers.

Registering a server from the Web UI

The MCP tab registers servers without hand-editing config.yaml, and — the part a config file cannot do — proves a definition works before it is saved.

  1. Register server opens the editor. Pick the kind:
    • HTTP / SSE — a URL such as http://127.0.0.1:3001/mcp/. Leave transport on auto unless the server only speaks one of them.
    • Local command (stdio) — a command such as npx with arguments. It runs on the gateway host, as the gateway user.
  2. Test connection dials the draft as typed, before anything is written. A success reports the server's name, version, protocol, capabilities and every tool it advertises.
  3. Try a tool appears after a successful test: pick a tool, supply arguments as JSON, and run it. This calls the real server, so treat it as you would any other live call.
  4. Save writes the definition to mcp.servers.<name> in config.yaml. The config watcher picks it up, and any cached session for that name is closed so the agent uses the new definition immediately — no restart.

Saved servers are listed with a Test button, so an operator can check a server that used to work without opening the editor.

Credentials

The list and the editor show header and environment values as they are written in config.yaml. A token pasted as plain text is therefore shown to everyone who can open the dashboard, and it sits unencrypted in the file.

Store the token in the vault and write a reference instead — the reference is what the editor shows, and the gateway resolves it when it connects:

Authorization: Bearer ${secret:MY_MCP_TOKEN}

${env:VAR} and ${file:/path} (the file's first line) work the same way. See the secret reference syntax in config.yaml.example.

In config.yaml

A server saved from the Web UI lands under mcp.servers; you can also write it by hand:

mcp:
  servers:
    docs:
      url: "http://127.0.0.1:3001/mcp/"
      transport: auto                 # auto (Streamable HTTP, then SSE) | streamable | sse
      headers:
        Authorization: "Bearer ${secret:MY_MCP_TOKEN}"
      description: "Internal documentation search"   # helps the agent pick this server
    files:
      command: npx                    # stdio: runs on the gateway host
      args: ["-y", "@modelcontextprotocol/server-filesystem", "/data"]
      env:
        LOG_LEVEL: info

The agent reaches them through the mcp tool: list_servers, list_tools, and call_tool with server, tool and an arguments object, plus the resource and prompt actions (list_resources, read_resource, list_prompts, get_prompt, …). From the command line:

goclaw tools exec mcp action=call_tool server=docs tool=search 'arguments={"query":"hello"}'

If the test fails

The most common failure is not a broken server. GoClaw denies outbound HTTP to hosts that are not allowlisted, and private addresses on top of that — which is exactly where MCP servers usually live:

Outbound HTTP refused "127.0.0.1" … add "127.0.0.1" to tools.http.allow

Add the host to tools.http.allow in config and test again (see Outbound HTTP for how the list matches). The editor turns the other frequent failures — a 401, a wrong path, a command that is not installed, a port with nothing behind it — into the same kind of specific advice.