๐Ÿ  Home โ† Docs Index
Open Beta ๐Ÿ“– Interactive Reader Raw .md llms.txt

Tools Engine Architecture

The GoClaw Tools Engine is a modular system for managing function-calling (tools), context injection (skills), event handling (hooks), and external extensions (plugins).

1. Tool Execution (Function-Calling)

Tools are registered via the Skill interface in Go. Each tool defines its own JSON schema (parameters) and implementation logic.

Interface

type Skill interface {
    Definition() llms.Tool    // JSON schema for the tool
    Execute(ctx context.Context, args map[string]any) (string, error)
}

Concurrent Execution via WorkerPool

When an LLM requests multiple tool calls in a single response, GoClaw executes them concurrently using a bounded WorkerPool (default: 8 workers, 64 queue). This prevents goroutine explosion and provides back-pressure under heavy load. Results are collected via channels and returned as a single response to the model.

Which Tools a Run Is Offered

GetTools(ctx) builds the list from the registry and the run's RuntimeScope; GetToolsFor then narrows it per request (section 3).

Sandboxing & Security


2. Skills System (Context Injection)

Skills provide specialized domain knowledge to the LLM via system prompt injection. Unlike tools, they are passive context providers.

Architecture

System prompt   = core instruction + IDENTITY.md + SOUL.md + AGENTS.md + instructions
                  + TOOLS.md + WORKSPACE + SKILLS
Session context = critical constraints + Memory.md + the person, their role + โ€ฆ
Message context = the time + the notes, lessons and personal memory the message matches + โ€ฆ
                  (after the person's message, not in the system prompt)

GetStaticSystemPromptFor puts the admin's core instruction first. A subagent's profile takes the place of IDENTITY.md and SOUL.md. Memory.md is not in the static prompt: it is part of the session context (SessionContexts), whose sections are dropped lowest-priority first when they exceed memory.context_budget_chars. See Memory: Session Context Injection.

A session's skills, like its tools, keep their places from turn to turn and a turn's new ones are added at the end (keepSessionSkills in rag_continuity.go), so the static prompt, which providers cache after the tools, holds across turns. The list starts again from the turn's own selection when it would carry more than 4 skills the turn did not pick, more than the skills section holds (skills.max_in_prompt, skills.max_prompt_chars), or after an hour idle; cron and SOP runs use their own selection.

Loading & Priority

Skills are loaded from four sources, with later sources overriding earlier ones of the same name:

  1. Built-in: Compiled into the binary.
  2. Plugins: the skills of the agent's plugins (the first plugin listed wins between plugins).
  3. Workspace: <agent workspace>/skills/ (~/.goclaw/workspace/skills/ for the default agent)
  4. User: ~/.goclaw/skills/

Frontmatter Support

Skills can include YAML frontmatter for metadata, tool requirements, and tags.


3. RAG Engine Integration

GoClaw utilizes a multi-layered RAG (Retrieval-Augmented Generation) engine to select relevant tools and skills for each user query (GetToolsFor, FilterSkillsFor in rag.go; tools.rag).


4. Hooks & Plugins

Admin Hooks (rules on tool calls)

Admins attach rules to the agent's tool calls on the Hooks page; they are saved under hooks: in config.yaml and run by hook_rules.go. Execute() runs the before-hooks ahead of the tool cache and the tool, and the after-hooks once the call ends, so both agent loops, SOP and cron runs and subagents are covered. Actions are block (before only), notify and webhook. A deciding hook fails closed: only an explicit {"decision": "allow"} lets the call through. A rule limited to agents matches the agent a call runs as, by its configured ID; main or default in the list, in any case, names the default agent, unless an agent is configured under that ID. A SOP run is its owner's when its schedule, the SOPs page, a resume or the background starts it; the webhook route's agent's when a route starts it; the conversation's agent's when sop_run starts it there.

Gateway Events (HookRegistry)

GoClaw implements a priority-based event registry for system-wide lifecycle events (internal/gateway/hooks.go). Handlers registered by Go code observe these events; they cannot change or stop what happens:

Extensions (Go / OpenClaw)

PluginAPI lets a Go plugin compiled into the gateway register hook handlers (RegisterHook) and HTTP routes (RegisterHTTPRoute). The gateway also discovers extension folders with a plugin.json or openclaw.plugin.json manifest in <state dir>/extensions/ and <workspace>/extensions/, and lists them at /api/extensions; it does not load or run code from them.

Agent Plugins

A separate feature: bundles of subagents, instructions, skills, hooks and MCP servers in the Agent Plugins layout VS Code uses (plugin.json, skills/<name>/SKILL.md, mcp.json). They are installed on the Plugins page into <state dir>/plugins and turned on per agent under plugins: in config.yaml. A workspace file of the same name overrides a plugin's part, and a plugin's hooks and MCP servers stay off until an admin approves each one.


5. Caching Layers

  1. Tool Result Cache: In-memory LRU cache with TTL and cross-tool invalidation (e.g., file_write invalidates file_read for the same path).
  2. LLM Response Cache: a cache in the state database (llm_cache table) for model responses that do not contain tool calls. It is on when cache.enabled and cache.llm_cache.enabled are both true (the default), keeps entries for cache.llm_cache.ttl seconds (default 300), and is used by the agent loop for every provider, for a first call that offers no tools. SOP steps bypass it.

6. Large Output Spill

When a tool returns more than max_result_chars (default: 8,000 characters), GoClaw spills the full content to an in-memory store instead of plain truncation. The LLM receives a compact, type-aware HEAD preview and a ref ID.

Flow

flowchart LR
    TOOL["<b>Tool Result</b><br/>&gt; 8,000 chars"] --> DET["<b>detectContentType()</b><br/>json / jsonl / html / xml / csv / text"]
    DET --> STORE["<b>OutputStore.Put(id, full)</b><br/>TTL: 1h ยท max: 200 entries"]
    STORE --> LLM["<b>LLM Receives Preview + ref</b><br/>Explore full data via read_output(ref)"]

Example header and preview returned to the LLM:

[LARGE OUTPUT: gitlab | type:json | lines:1847 | chars:58420 | ref:a3f8c2d1]
๐Ÿ›‘ TRUNCATED: 2950 of 58420 characters are shown below; 55470 are NOT.
...
Preview:
[0] {"id":234,"title":"Fix login","state":"merged"}
...
To explore full data โ€” call the SEPARATE 'read_output' TOOL ...:
read_output(ref: "a3f8c2d1", mode: "search", query: "<keyword>")

The preview is capped at 4,000 characters. When it holds the whole result, the header is followed by a line saying the complete result is shown, and Result: in place of Preview:. db_query results are always stored, even small ones (which are returned whole), so spreadsheet can build a file from the data_ref; a query with no rows returns a notice instead. Inside a SOP run, a stored result is also written to the run's directory, so a ref handed to a later step outlives the in-memory store.

Content Type Detection

Type Detect HEAD Preview
json starts with {/[ + valid JSON first 5 keys / items
jsonl every line is {...} first 5 objects
html <!DOCTYPE/<html <title> + text nodes
xml <?xml/leading <tag root + first 10 lines
csv header + comma/tab header + first 5 rows
text default first 60 lines

read_output Tool

Lets the LLM navigate stored outputs without re-running the original tool:

Mode Description
head First N lines (default 100)
tail Last N lines
slice Lines fromโ€“to
search Keyword grep with ยฑcontext_lines; on a line over 2,000 bytes, only the 1,000 bytes on each side of its first 10 matches
sql A read-only SELECT against the result as table data
all Full content (โ‰ค80KB only)

Every mode returns at most 80KB and ends with a note saying where it stopped and how to read on. The modes count lines, and a JSON result is often a single line, so without the cap head or search on an 860KB one-line payload returned all of it.


7. Report Generation

PDF (generate_pdf)

Builds the report (title, sections, tables, charts) as HTML and prints it to PDF with headless Chrome (chromedp, PrintToPDF), so Chrome or Chromium must be installed on the gateway host. Text uses the host's system fonts: Mongolian Cyrillic renders when the host has a font that covers it.

HTML (generate_html)

Generates arbitrary HTML pages (dashboards, charts, tables) and serves them at /goclaw/view/<slug>?token=<view_token>.


8. Strategic Roadmap

Future developments for the tools engine include: