goclaw: a Go agent runtime that borrows OpenClaw's skill format
An open-source AI assistant framework like openclaw
At a glance
- What is it?
- goclaw is an MIT-licensed Go framework for building AI agents, with a Markdown-based skill system, JSONL session persistence and thirteen chat channel adapters. Its strongest idea is also its tightest constraint: skills are prompt text plus environment checks, not sandboxed code.
- Who is it for?
- Adopt goclaw if you want an agent runtime in Go that reuses the existing OpenClaw skill corpus and you are willing to treat skills as prompt injection rather than sandboxed plugins. Do not adopt it if you need per-skill code isolation, or if you cannot run the binaries a skill declares in its requires.bins block.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 173 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The gap goclaw fills: OpenClaw skills without the Node runtime
OpenClaw built a following around a particular way of extending an agent: you write a SKILL.md file, drop it in a directory, and the agent picks it up. The skill is prose. It tells the model which existing tools to call and in what order. goclaw ports that convention to Go. The README describes it as the Go version of OpenClaw and states that the skills directory from openclaw/skills can be copied over directly, and that the loader also follows the AgentSkills specification.
The audience is narrow and identifiable. It is a Go engineer who already has a service written in Go, wants an agent loop inside that binary, and does not want to run a separate Node process and bridge to it over HTTP. The repository layout supports that reading: agent, channels, bus, config, providers, gateway, cron, session and cli are all top-level packages in one module, and main.go is the only entry point. You get one binary, not a service mesh.
The second audience is anyone who has accumulated OpenClaw skills and wants to keep them. Because the format is the same, the migration cost is a directory copy, not a rewrite. That is the real selling point, and it is worth being precise about what it does and does not buy you.
What a skill actually is: injected prompt text plus a binary check
The README is unusually direct here, and the honesty is useful. Skills are described as prompt-driven: a skill is an instruction set injected into the system prompt that guides the LLM to use existing tools such as exec and read_file. There is no plugin ABI, no dynamic library, no subprocess protocol. A skill is a Markdown file with a YAML front matter block, and its entire runtime effect is on the text the model sees.
The front matter carries a name, a description, and a metadata.openclaw.requires block. The README's example declares bins: ["python3"], with the comment that the skill loads only when python3 exists. This is the gating mechanism. The loader inspects the host environment, and a skill whose declared binaries are absent is skipped rather than loaded and then failing at call time. The README gives weather and git-helper as illustrations: weather activates only if curl is installed, git-helper only if git is.
That design has a clear consequence. A skill cannot do anything the agent's existing tools cannot already do. It cannot register a new tool, only describe how to combine the ones that exist. If you need a capability that is not reachable through exec, read_file, the web tools or the browser tools, a SKILL.md will not get you there. You would be modifying the Go code in agent/tools/ instead. Gating is also a presence check, not a version check: the README shows requires.bins, and nothing in the supplied material indicates that a minimum version can be expressed.
Config and skill resolution: two lookup chains that behave differently
There are two ordering rules in goclaw, and they run in opposite directions. Confusing them is the most likely source of a silent misconfiguration.
Configuration files are resolved first-match-wins. The README lists ~/.goclaw/config.json as the highest priority, then ./config.json in the current directory, then environment variables with the GOSKILLS_ prefix. The first one found is used, and the rest are ignored. You can override the search entirely with the --config flag. Both YAML and JSON are accepted. Note the mismatch in naming: the config directory is .goclaw and the environment prefix is GOSKILLS_. The README does not reconcile this, and it reads like a leftover from an earlier name.
Skills resolve the other way. All three directories are loaded, and a later load overwrites an earlier one when names collide. The order given is ~/.goclaw/skills/ first (lowest priority), then ${WORKSPACE}/skills/, then ./skills/ in the current directory, which the README calls out as highest priority because it loads last. WORKSPACE defaults to ~/.goclaw/workspace.
So a global config beats a local one, but a local skill beats a global one. If you keep a personal config in your home directory and a project config in the repository, the project config will not be read. That is a defensible choice for a user-level tool and a surprising one for a repository that also ships a multi-channel gateway.
Sessions, memory and the channel fan-out
Session state is stored as JSONL, one file per session, and the README says the full tool call chain is recorded and can be recovered. This is a plain-text append log rather than a database. The practical upside is that you can read a session with grep and diff two runs against each other. The practical cost is that nothing prunes or compacts those files, and the supplied material does not describe a retention policy or a rotation command.
Memory is separate and offers two backends: a built-in vector database and something the README calls QMD (Quick Markdown Database). The cli/commands directory contains a memory.go subcommand, so there is a management surface for it, though the README does not document its flags. Treat the memory subsystem as the least specified part of the project.
The channel layer is the widest surface. channels/ holds one file per adapter: telegram, whatsapp, feishu, qq, wework, dingtalk, infoflow, gotify, slack, discord, googlechat, teams and weixin. Each sits behind a base interface with a manager coordinating them, and the README notes that a single channel can hold multiple account instances. Messages flow through the bus package, which defines events and a queue, and the gateway package exposes a WebSocket server with its own protocol definitions. For a team already running a bot on three of those platforms, having them behind one interface is the difference between three codebases and one config block.
Getting it running: the commands the README gives
The quick start is a clone and a build. The README shows git clone, then go mod tidy, then go build -o goclaw . for a Go-only binary, or make build-full when you want the UI included, which the README recommends. There is also go run main.go start for a direct run. After starting, the README says the dashboard is reachable at http://localhost:28789/dashboard/.
Configuration is a JSON or YAML file. The README points at internal/config.example.json and shows a structure with a workspace.path, an agents.defaults block carrying model.primary, max_iterations, temperature and max_tokens, and a models block with mode set to merge and a providers map. The example configures qianfan with baseUrl https://qianfan.baidubce.com/v2 and api set to openai-completions, plus an openai provider. API keys are referenced as ${QIANFAN_API_KEY} and ${OPENAI_API_KEY}, so environment substitution happens during load. The README lists OpenAI, Qianfan, Anthropic and OpenRouter as providers, with failover support.
Skill inspection is a single command: ./goclaw skills list. Installing a skill means placing its folder in one of the three directories described above. The cli package also exposes agent, agents, sessions, cron_cli, approvals and system commands, plus subcommands for tui, gateway, browser, health, status, memory and logs, and docs/cli.md is referenced as the detailed CLI reference. None of those subcommands are documented in the README itself, so the docs directory is where you would have to look.
Where goclaw is the wrong tool
The skill model is the limitation. Because a skill is prompt text and the agent's tools include exec, shell and browser control, installing an unfamiliar skill means giving a language model a set of instructions that may tell it to run arbitrary commands. Gating checks whether python3 exists; it does not check what the script does. The README mentions Docker sandboxing and permission control as part of the tool system, and there is an approvals command in the CLI, but the supplied material does not explain how approvals are configured or which tools they gate. If your threat model requires per-skill isolation, goclaw's skill system does not provide it, and copying skills from a public directory is a code-execution decision made in prose.
The second case is scale of configuration. A framework that ships thirteen channel adapters, a WebSocket gateway, a cron scheduler, a browser controller and two memory backends carries a lot of surface. If you want an agent that answers questions in a terminal, most of that is dead weight, and a smaller library with a single provider and a REPL would be less to maintain. The README does not present a minimal mode.
The third is version sensitivity. The releases listed are v0.4.0 in March 2026, preceded by v0.3.4 and v0.3.3 within three weeks of each other in late February and early March. Three releases in that window, on a project still below 1.0, suggests the config schema and CLI are still moving. Pin a commit if you build on it.
The alternative, and the actual difference
The obvious comparison is OpenClaw itself, which goclaw explicitly mirrors and whose skills it imports. The difference is the runtime, not the feature list. OpenClaw is a JavaScript and TypeScript project; goclaw is a single Go binary with no Node dependency. That matters if your deployment target is a small container, if you already ship Go services and want the agent in-process, or if you want to call the agent from Go code directly rather than over a network boundary. It matters less if you are already running a Node stack, in which case porting to Go buys you nothing and costs you the upstream project's head start on features.
A second alternative is to skip the framework and write the loop yourself against a provider SDK. The goclaw agent loop is a small number of files: loop.go, context.go, memory.go, skills.go and subagent.go. If your requirements are one provider, one channel and no skills, reimplementing that is a few hundred lines and leaves you with no dependency to track. What you would be rebuilding is the parts you would otherwise get free: the JSONL session format with tool call recovery, the channel manager, the cron scheduler and the provider factory with failover. The trade is between a dependency that moves and code you own.
Licence and the cost of keeping up
goclaw is MIT licensed, which permits commercial use, modification and redistribution provided the copyright notice and permission notice are retained. That is the permissive end of the spectrum and imposes no copyleft obligation on your own code. This is a description of the licence text, not legal advice; if you are redistributing a modified binary, read the LICENSE file in the repository and get your own counsel.
The maintenance cost has two parts. The first is upstream drift. goclaw tracks the OpenClaw skill specification and the AgentSkills specification, so a change in either format is a change you inherit. The second is the config surface: providers, channels, agents, workspace and models all live in one file whose lookup order is first-match-wins, which means a stale ~/.goclaw/config.json silently shadows the repository config. When something behaves oddly after an upgrade, that file is the first place to look, and the --config flag is the way to bypass the search entirely while you isolate the problem.
Editorial conclusion
Adopt goclaw if you want an agent runtime in Go that reuses the existing OpenClaw skill corpus and you are willing to treat skills as prompt injection rather than sandboxed plugins. Do not adopt it if you need per-skill code isolation, or if you cannot run the binaries a skill declares in its requires.bins block. Before committing, clone the repository, run go build -o goclaw . and then ./goclaw skills list to confirm which skills pass gating on your machine, and read agent/skills.go to see exactly how the loader resolves the three skill directories and which one wins on a name collision.
Community notes