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

Agent Runtime

GoClaw runs one or more agents in one process. Each agent is an entry in agents.list with its own workspace, model and memory, and channel messages reach an agent through routing. With no agents.list, there is one agent, main. Every agent processes messages with an LLM provider and tool calling.

Architecture

flowchart TD
    MSG["User Message"] --> RUNTIME["<b>Agent Runtime</b><br/>System Prompt + History + Memory"]
    RUNTIME --> LLM["<b>LLM Provider</b><br/>Gemini / Claude / OpenAI / DeepSeek"]
    LLM -->|Tool Calls| POOL["<b>WorkerPool</b><br/>Parallel execution ยท Bounded concurrency"]
    POOL -->|Tool Results| LLM
    LLM -->|Streamed Tokens| RES["Final Response"]
    RES --> CH["Channel Output"]

Agent Loop

The event-driven agent loop (ProcessStream) is shared across all LLM providers:

  1. Build the system prompt from workspace files + skills + memory
  2. Append session history and the new user message
  3. Call the LLM with the tools selected for this request: the core tools, plus the tools Tool RAG picks for the message (tools.rag.top_k, default 12) and the agent's most-used tools (tools.rag.usage_prior, default 6). The model can add a tool the selection left out with search_tools
  4. If the LLM returns tool calls:
    • Execute tools concurrently via the bounded WorkerPool
    • Feed tool results back to the LLM via event channels
    • Repeat (up to tools.max_tool_iterations, default 20)
  5. If the LLM returns text only, stream EventTokenChunk to the client

The Gemini provider uses a custom loop (native genai SDK) that natively streams content, but follows the same logical flow.

LLM Providers

Provider Config Key SDK
OpenAI openai github.com/openai/openai-go/v3 (official)
Claude (Anthropic) claude github.com/anthropics/anthropic-sdk-go (official)
Gemini gemini google.golang.org/genai (native)
Gemini Legacy (deprecated) gemini-legacy served as gemini
DeepSeek deepseek github.com/openai/openai-go/v3, DeepSeek's API (DeepSeek publishes no Go SDK)
Ollama ollama github.com/ollama/ollama/api (official)

The provider is chosen at startup from ai.provider. An agent's agents.list[].model overrides it for that agent, either as a provider name (claude) or as provider/model (claude/claude-sonnet-4-5-20250929). With neither set, the provider is openai.

Model Failover

Every provider makes a model call again when it fails because the provider is overloaded (twice, after about 2 and 6 seconds) or on the network (once, after half a second); quota, billing and key errors are not retried (Provider Fallback).

When the provider still fails before the reply has used a tool, the request moves to the next provider/model of ai.fallback, or of the agent's own agents.list[].fallback, which replaces it. A provider that keeps failing is put in cooldown and skipped while others remain. Model Failover explains how.

System Prompt

The system prompt is assembled in this order (GetStaticSystemPromptFor in agent.go):

  1. Core instruction โ€” the admin's core instruction for this agent, when one is set
  2. IDENTITY.md and SOUL.md โ€” Identity, persona, tone, boundaries. A subagent gets its profile here instead
  3. AGENTS.md โ€” Operating instructions, rules
  4. Instructions โ€” the admin's instructions/<name>.instructions.md that apply to this run and name no tools
  5. TOOLS.md โ€” Tool usage notes and conventions (narrowed to the step's tools in a SOP step)
  6. Tool priority; when Tool RAG is on, finding tools (search_tools); when you cannot get it: say which of three it is, in a sentence or two (no tool can do it; a tool exists but needs an administrator, was not offered here or was blocked by a rule; or the tool failed or found nothing), and never present other data as the answer; and GoClaw documentation: goclaw_docs for how GoClaw is configured and how it works, not for data a webhook or a system sent or holds
  7. Workspace, runtime and workspace files โ€” Working directory path, OS, host, timezone, and a listing of the workspace
  8. Skills โ€” Loaded skill markdown (built-in + user + workspace), filtered by Skill RAG
  9. Memory protocol and memory routing policy โ€” Which memory scope to use, and who may teach what
  10. Subagent delegation โ€” when the agent has subagents.allow_agents

A missing file is skipped. Memory.md, personal and global memory, agent notes and lessons are not part of this prompt: what holds for the session goes into the session context that follows it, and what was found for the message (the notes, lessons and personal memory it matches, and the current time) follows the person's message, after the history, so the providers' prompt caches keep the conversation from turn to turn (Memory).

Bootstrap File Protection

The following files are read-only except to an admin and to cron and SOP runs that act for no one in particular:

The file_write and file_edit tools refuse to write them for other callers.

Workspace

The default agent's workspace is ~/.goclaw/workspace/. Every other agent's is ~/.goclaw/agents/<id>/workspace/. agents.list[].workspace sets another path for either.

The workspace is the agent's working directory for all file operations. Path traversal outside the workspace is blocked.

Bootstrap Files

File Purpose
SOUL.md Agent persona and boundaries
AGENTS.md Operating rules and guidelines
TOOLS.md Tool documentation and conventions
Memory.md Long-term memory (shared across sessions)

A new workspace is seeded with these four files from defaults built into the binary. In the default agent's workspace, TOOLS.md and AGENTS.md are written again from those defaults at every start (AGENTS.md from the tools.mode profile), so edits to those two files there do not last; SOUL.md and Memory.md are seeded only when missing. Rules of your own belong in an instruction (instructions/<name>.instructions.md, on the Web UI's Instructions page) instead.

Memory

Memory.md is the agent's curated long-term memory; it goes into the session context of every request. Everything the agent learns at run time is stored as records in the database, not as files:

Canvas

There is no canvas tool the model calls directly (canvas_show exists in canvas.go but is not registered). Files reach the canvas from tools that produce them:

These files are collected for the request and sent as attachments with the answer, on every channel. Screenshots and diagrams are stored in ~/.goclaw/canvas/.