โ† All guides

The ZeroClaw config.toml Reference, With Working Examples

ZeroClaw.net ยท Updated 2026-08-18

The ZeroClaw config.toml Reference, With Working Examples

Almost everything about a ZeroClaw agent is decided in one file. The runtime's trait-based architecture means the model, the memory backend, the channels and the security boundaries are all selected rather than coded โ€” and config.toml is where that selection happens.

This guide walks through each section, then gives complete working examples you can adapt.

Configuration keys move between versions in a project this young. Run zeroclaw doctor after any edit โ€” it validates the file and tells you which key it did not understand, which is faster than guessing.

Where the file lives

Configuration sits in ZeroClaw's config directory, created by zeroclaw onboard. On Linux and macOS this is typically under ~/.config/zeroclaw/; on Windows, under your user profile's application data directory. To find it on your system:

zeroclaw status

The same directory holds the encryption key file used for secrets. Keep the whole directory out of version control, and set restrictive permissions on it:

chmod 700 ~/.config/zeroclaw

TOML in sixty seconds

If you have not used TOML: [section] headers group keys, key = "value" assigns strings, arrays use square brackets, and [section.subsection] nests. Strings need quotes; numbers and booleans do not. A # starts a comment.

[provider]
name = "openrouter"
temperature = 0.7
stream = true
models = ["primary", "fallback"]

The single most common mistake is an unquoted string. model = llama3 is a syntax error; model = "llama3" is what you meant.

The [provider] section

Where the thinking happens. ZeroClaw speaks the OpenAI-compatible API shape, so this section works the same whether you are pointing at a commercial API or a local server.

[provider]
name = "openrouter"
model = "anthropic/claude-sonnet-4"
api_key_env = "OPENROUTER_API_KEY"
base_url = "https://openrouter.ai/api/v1"
temperature = 0.7
max_tokens = 4096
  • name โ€” the provider implementation to use.
  • model โ€” the model identifier, in whatever form your provider expects. Provider-specific: OpenRouter wants vendor/model, Ollama wants a local tag such as qwen3:4b.
  • base_url โ€” the API endpoint. Changing this alone is usually enough to redirect to a different OpenAI-compatible service.
  • api_key_env โ€” the environment variable holding the key. Prefer this to inlining a key, and prefer zeroclaw onboard to both, since onboarding encrypts the credential at rest.
  • temperature โ€” sampling randomness. For agents that call tools, keep this low. Creative variance is a liability when the output is a command rather than prose.
  • max_tokens โ€” response ceiling. Also a cost ceiling, which is the more useful way to think about it.

Pointing at a local Ollama server instead:

[provider]
name = "ollama"
model = "qwen3:4b"
base_url = "http://localhost:11434/v1"
temperature = 0.3

No API key, no per-token cost, no outbound network requirement.

The [memory] section

What the agent knows between sessions. ZeroClaw's memory engine has no external dependency โ€” there is no vector database to operate alongside it.

[memory]
backend = "sqlite"
path = "/home/agent/workspace/.memory/agent.db"
auto_recall = true
vector_weight = 0.7
keyword_weight = 0.3
max_results = 10
  • backend โ€” sqlite for structured storage and the best retrieval performance, markdown for human-readable files you can inspect and edit by hand, or an ephemeral mode that forgets everything on exit.
  • auto_recall โ€” when true, relevant context is retrieved and injected automatically rather than being manually assembled into each prompt. This is the feature that makes memory useful rather than decorative.
  • vector_weight / keyword_weight โ€” the hybrid search balance. Vector similarity finds conceptually related memories; keyword matching finds exact terms. The 0.7/0.3 default favours meaning over literal matching. Raise the keyword weight if your agent deals in precise identifiers โ€” ticket numbers, SKUs, filenames โ€” where exact matching matters more than semantic similarity.
  • max_results โ€” how many memories to pull into context. Higher means better recall and larger, slower, more expensive prompts.

The markdown backend is worth considering while you are still developing. Being able to open a file and read exactly what your agent remembers is a debugging advantage that outweighs the retrieval performance difference at small scale.

The [security] section

The section to get right before the agent does anything real.

[security]
workspace = "/home/agent/workspace"
allowed_commands = ["git", "ls", "cat"]
require_pairing = true
autonomy_level = "supervised"
  • workspace โ€” the only directory the agent may touch. Everything outside is inaccessible.
  • allowed_commands โ€” deny-by-default shell execution. Only these executables can run.
  • require_pairing โ€” new channel connections must present a pairing code.
  • autonomy_level โ€” supervised modes require approval before actions execute.

Two warnings that deserve repeating. Allowlisting git effectively grants code execution, because git hooks run arbitrary commands โ€” the same is true of cargo, npm and make. And the workspace path should be a directory created for the agent, never your home directory. Our security guide covers the reasoning and the failure modes in full.

The [channels] section

How humans reach the agent. Each channel is configured independently and several can run at once.

[channels.telegram]
enabled = true
token_env = "TELEGRAM_BOT_TOKEN"
allowed_users = ["123456789"]

[channels.web]
enabled = true
bind = "127.0.0.1"
port = 3000

[channels.whatsapp]
enabled = false

allowed_users is a second gate alongside pairing โ€” even a paired connection is rejected if the account is not on the list. For a personal agent, listing your own user ID and nothing else is the correct configuration.

Note the bind address on the web channel. 127.0.0.1 accepts local connections only. Changing it to 0.0.0.0 exposes the dashboard to your entire network, and that is a deliberate decision rather than a default โ€” see the web UI and gateway guide before making it.

The [tools] section

What the agent can do beyond producing text.

[tools]
enabled = ["file_read", "file_write", "shell", "http"]
timeout_seconds = 30

[tools.http]
allowed_domains = ["api.github.com"]

Enable only what a task genuinely requires. http is the one to think hardest about: an agent with unrestricted network access can send the contents of its workspace anywhere, which undoes much of what workspace scoping bought you. allowed_domains narrows that considerably.

timeout_seconds bounds how long a single tool call may run โ€” the control that prevents one wedged command from hanging the agent indefinitely.

The [identity] section

The agent's persona and behavioural definition.

[identity]
format = "aieos"
path = "/home/agent/workspace/identity.json"

ZeroClaw supports AIEOS, a portable JSON specification describing traits, psychology, linguistics and motivations, and it also reads OpenClaw's Markdown identity files (IDENTITY.md, SOUL.md) directly. If you are migrating, point at the existing files rather than converting them:

[identity]
format = "markdown"
path = "/home/agent/workspace/IDENTITY.md"

Complete example: a local, private agent

Everything on your own hardware. No API key, no outbound requests, nothing leaves the machine.

[provider]
name = "ollama"
model = "qwen3:4b"
base_url = "http://localhost:11434/v1"
temperature = 0.3
max_tokens = 2048

[memory]
backend = "sqlite"
path = "/home/agent/workspace/.memory/agent.db"
auto_recall = true
vector_weight = 0.7
keyword_weight = 0.3

[security]
workspace = "/home/agent/workspace"
allowed_commands = ["ls", "cat"]
require_pairing = true
autonomy_level = "supervised"

[channels.telegram]
enabled = true
token_env = "TELEGRAM_BOT_TOKEN"
allowed_users = ["123456789"]

[tools]
enabled = ["file_read", "file_write"]
timeout_seconds = 30

Note what is absent: no shell tool, no http tool, a two-command allowlist. This agent can read and write files in one directory and talk to you. That is a deliberately small surface, and it is the right starting point.

Complete example: a hosted-model development agent

More capable, for work you are supervising directly.

[provider]
name = "openrouter"
model = "anthropic/claude-sonnet-4"
api_key_env = "OPENROUTER_API_KEY"
base_url = "https://openrouter.ai/api/v1"
temperature = 0.2
max_tokens = 8192

[memory]
backend = "markdown"
path = "/home/agent/projects/.memory"
auto_recall = true
max_results = 15

[security]
workspace = "/home/agent/projects/current"
allowed_commands = ["git", "cargo", "ls", "cat", "grep"]
require_pairing = true
autonomy_level = "supervised"

[channels.web]
enabled = true
bind = "127.0.0.1"
port = 3000

[tools]
enabled = ["file_read", "file_write", "shell"]
timeout_seconds = 120

[tools.http]
allowed_domains = ["api.github.com", "crates.io"]

The longer timeout accommodates builds. git and cargo are allowlisted because the job requires them โ€” and that means this agent effectively has code execution, so it runs supervised, in a project directory, as a user that owns nothing else.

Validating changes

zeroclaw doctor          # validate configuration and check connectivity
zeroclaw status          # show the runtime's current view of its config
zeroclaw channel doctor  # check channel health specifically

If doctor reports a key it does not recognise, check it against your installed version rather than assuming the documentation is current โ€” this includes the documentation on this page.

Practical tips

Keep the file in version control, keep secrets out. Commit config.toml with api_key_env references; never commit the key file or the config directory itself.

Change one thing at a time. When an agent starts behaving strangely after five simultaneous edits, you have no way to identify which one caused it.

Comment your reasoning. In six months, # low temperature: this agent calls tools will explain a decision that would otherwise look arbitrary.

Keep separate configs per agent. Distinct workspaces, distinct allowlists, distinct memory stores. A shared configuration means a compromise of the least careful agent reaches the most sensitive one.

Related reading

ZeroClaw.net is an independent community resource. It is not the official ZeroClaw project and is not affiliated with ZeroClaw Labs, OpenClaw or PicoClaw. Always check the official project repository before installing software.