openclaw/docs/cli/agents.md
Peter Steinberger 76ba4650f0
fix: prevent empty recreation of retained PostgreSQL agent stores (#188350)
* fix: preserve retained PostgreSQL agent stores during creation

Publish new agent anchors only after PostgreSQL schema and identity initialization. Refuse missing or mismatched retained namespaces before creation effects, while allowing failed initial creation to retry. Document matched-backup restoration and explicit manual discard.

Co-authored-by: Chris Eckert <christopher.k.eckert@gmail.com>

* fix: distinguish unverifiable retained PostgreSQL stores

* fix: link retained PostgreSQL verification recovery

---------

Co-authored-by: Chris Eckert <christopher.k.eckert@gmail.com>
2026-10-30 15:42:08 +01:00

23 KiB

summary read_when title
CLI reference for `openclaw agents` (roles, teams, workspaces, routing, and identity)
You want multiple isolated agents (workspaces + routing + auth)
You want to create an agent from a role or set up a coordinated team
Agents

openclaw agents

Manage isolated agents (workspaces + auth + routing). Running openclaw agents with no subcommand is equivalent to openclaw agents list.

Creation summaries strip terminal escape sequences and show embedded newlines, tabs, and carriage returns as \n, \t, and \r. Workspace paths and other values in saved configuration and --json output retain their original contents.

Examples

openclaw agents list
openclaw agents list --bindings
openclaw agents add work --workspace ~/.openclaw/workspace-work
openclaw agents add work --workspace ~/.openclaw/workspace-work --bind telegram:*
openclaw agents add ops --workspace ~/.openclaw/workspace-ops --bind telegram:ops --non-interactive
openclaw agents add research --role researcher --non-interactive
openclaw agents team create --non-interactive
openclaw agents bindings
openclaw agents bind --agent work --bind telegram:ops
openclaw agents unbind --agent work --bind telegram:ops
openclaw agents set-identity --workspace ~/.openclaw/workspace --from-identity
openclaw agents set-identity --agent main --avatar avatars/openclaw.png
openclaw agents delete work

Command surface

agents list

Options: --json, --bindings (include full routing rules, not only per-agent counts/summaries).

For an explicit multi-agent roster, the default badge and JSON isDefault field use agents.defaults.systemAgent.agentId. Doctor preserves the migrated default there across restarts. Without a designation, every entry reports isDefault: false; set one with openclaw config set agents.defaults.systemAgent.agentId <id>. The Control UI's Set Default action writes the same designation.

Provider-status labels include optional account display names beside account IDs. Routing rules continue to identify accounts by channel and account ID.

An agent whose database belongs to another agent appears as degraded, with the refusal reason and repair guidance. The Gateway can continue serving healthy agents when a secondary agent is refused. Follow Doctor's database recovery guidance, then restart the Gateway after repairing the files.

Provider rows summarize local account status for the displayed binding scopes. A wildcard includes each locally known account once; message routing still applies peer and account precedence. Stored bindings with an omitted or blank account id refer to the literal default account key, independently of a channel's preferred account for commands. Use --json --bindings to include provider rows in JSON.

Identity fields saved in config take precedence. Fields that are not configured fall back to IDENTITY.md in the agent's workspace. Unsupported avatar values and unreadable local images also fall back to the workspace avatar.

agents add [name]

Options: --role <role>, --workspace <dir>, --model <id>, --agent-dir <dir>, --bind <channel[:accountId]> (repeatable), --non-interactive, --json.

Basic non-interactive creation uses the local Gateway while it is running. The command binds to that Gateway's state owner; an unsupported method, lost reply, or authentication failure never retries the write locally. Check agents list before retrying an uncertain result.

Interactive setup, --role, --agent-dir, and --bind require the local Gateway to be stopped. These setup flows hold exclusive state ownership through workspace, credential, and config settlement. Stop the Gateway through its service owner, wait for it to exit, and rerun the same command.

  • The automation flags --workspace, --model, --agent-dir, --bind, and --non-interactive select the non-interactive path. Non-interactive mode requires an agent name and, unless --role is supplied, --workspace.
  • --json alone keeps the guided wizard interactive. Prompts and status are written to stderr, and stdout contains one JSON summary after setup completes.
  • Non-interactive --json reports normalized agent IDs in the summary without extra stdout status messages.
  • If a requested binding belongs to another agent, non-interactive creation keeps the new agent and any non-conflicting bindings but exits with status 1. The summary names the conflicts; resolve them with agents bind and agents unbind instead of recreating the agent.
  • main is an ordinary agent id. Recreating it after another agent owns the installation can require openclaw doctor --fix to repair legacy session or shared-auth ownership first.
  • Interactive mode offers optional auth copying. When the fleet has no default agent, choose a source agent or Skip copying auth profiles (the default). Selecting a source still requires confirmation before copying. Only portable static credentials (api_key and static token profiles) are copied unless a credential opts out with copyToAgents: false; OAuth refresh-token profiles are not copied unless a provider opts in with copyToAgents: true. Without a copy, OAuth stays available through the shared auth base. If the source agent has its own local OAuth profile, sign in separately for the new agent.
  • An agent id whose deletion has finished can be recreated with agents add. Creation claims the finished deletion record when it publishes the new agent, including when the wizard copies or configures auth. An id whose deletion cleanup is still pending is refused until cleanup finishes.

With PostgreSQL agent storage, a retained local anchor must still match an initialized server namespace. If that namespace is missing, empty, or belongs to another store, creation refuses before changing the workspace or configuration. Restore a matching backup, or follow the manual discard procedure if the history is intentionally gone. A failed first creation can be retried normally; an incomplete anchor left by an older version requires the same conservative recovery.

Role templates

--role works in interactive and non-interactive creation, including --json. Bundled roles are Template sources: each role directory contains a CLAW.md manifest with identity and SOUL.md content, plus its operating program in workspace/AGENTS.md. Available roles:

Role Title Purpose
coordinator Chief of staff Coordinate specialists as your single point of contact.
researcher Researcher Gather evidence and return a cited research brief.
writer Writer Turn a brief and source material into a usable draft.
reviewer Reviewer Check artifacts against requirements and return actionable findings.

A role seeds AGENTS.md, SOUL.md, and a complete IDENTITY.md; USER.md still uses the standard template. Existing workspace files are preserved. The role's name, emoji, and theme are saved in agent config, and new role workspaces skip the identity ceremony: no BOOTSTRAP.md is created. The bundled roles leave skills unchanged. Role delegation settings are also applied. A standalone chief of staff targets the standard specialist ids; use the team command to create and wire all four agents. When creating an agent through Ask OpenClaw, you can give a display name separately from its id, such as “QA Writer” with id qa-writer. The approval includes both. An explicit display name replaces the role's default name while keeping its emoji, theme, and operating instructions. Unknown roles are rejected with the available role names. A workspace with an unfinished bootstrap cannot adopt a role. OpenClaw checks completion before adding role files; rejected adoption leaves workspace files and agent config unchanged. Complete its bootstrap or choose a new workspace.

With Templates enabled, the equivalent source path is openclaw templates add docs/reference/templates/roles/<role> from a source checkout. Follow the Template preview and consent flow to add it. Use agents team create to wire the agents into a team.

agents team create

Team creation requires the local Gateway to be stopped and holds exclusive state ownership until the created agents and config changes have settled.

Options: --preset <name> (default and only bundled preset: team), --coordinator <id> (default: coordinator), --prefix <p>, --workspace-root <dir>, --non-interactive, --json.

Creates a chief of staff (coordinator) plus researcher, writer, and reviewer from the role templates. Each workspace lives at <workspace-root>/<agentId>; the default root is the installation's default workspace directory. --prefix editorial namespaces every id, producing editorial-coordinator, editorial-researcher, editorial-writer, and editorial-reviewer. It also prefixes a custom --coordinator id. If any resulting id exists, the command reports the conflicts and adds no agents.

Existing agents remain in place, including an implicit main on an already configured installation.

openclaw agents team create --prefix editorial --workspace-root ~/agents --non-interactive --json
openclaw agent --agent editorial-coordinator --message "Research this topic and draft a brief."

The coordinator's subagents.allowAgents names the three specialist ids and delegationMode is "prefer". Specialists receive subagents.allowAgents: [] and instructions to return results without further delegation. This does not change global delegation defaults or tool policy. See Team preset. Delegation remains team wiring in config; the role Templates will carry these settings once the separate Template profile support lands.

The coordinator is an explicit chat target. If agents.defaults.systemAgent.agentId is unset, team creation sets it to the coordinator for ambient system work and default-compatible operations. An existing owner is preserved and reported. Channel bindings take precedence over this default. With --json, the summary includes coordinatorId, the created agents and their paths, ambientOwnerId, and a note when another ambient owner is retained.

agents bindings

Options: --agent <id>, --json.

agents bind

Options: --agent <id> (defaults to the current default agent), --bind <channel[:accountId]> (repeatable), --json.

agents unbind

Options: --agent <id> (defaults to the current default agent), --bind <channel[:accountId]> (repeatable), --all, --json. Accepts either --all or one or more --bind values, not both.

agents set-identity

Options: --agent <id>, --workspace <dir>, --identity-file <path>, --from-identity, --name <name>, --theme <theme>, --emoji <emoji>, --avatar <value>, --json. See Set identity below.

agents delete <id>

Options: --force, --json.

  • The only configured agent cannot be deleted.
  • Without --force, interactive confirmation is required (fails in a non-TTY session; re-run with --force).
  • Workspace, agent state, and session transcript directories move to Trash, not hard-deleted. If Trash is unavailable, the agent is removed from config but cleanup remains pending. After config publication succeeds, Gateway deletion returns UNAVAILABLE with the path failures in its error message and the existing removed and failed details attached to the error response. Offline deletion reports those path outcomes through --json.
  • Gateway deletion durably closes new sessions, turns, and automations, then aborts and waits for active turns and background memory/session work to settle before retiring storage. In a shared session store, deletion cancels only the deleted agent's work; surviving agents remain admitted. Already accepted storage work settles before retirement. Late session writes are refused as soon as draining starts without interrupting cleanup. A terminal status update refused by deletion does not block the drain; deletion still waits for the turn's execution and cleanup to finish. Gateway-wide session views, health summaries, usage-cost reports and backfill, and terminal snapshots continue for surviving agents without reopening the deleting agent's store. The Gateway resumes interrupted deletions after restart, including journals from older versions.
  • While deletion cleanup is pending, new session writes remain refused even if draining or restart recovery fails. If deletion rolls back before removing the agent from config, it persists retained terminal updates before reopening the agent. Resolve the reported failure and retry deletion. Workspace, agent-directory, and session-store relocation is also refused until cleanup finishes; updates that leave the storage targets unchanged remain available.
  • Gateway deletion gives active runs 15 seconds to drain. If a run does not stop after cancellation, deletion reports its session ID and preserves the agent's configuration and storage. Wait for the named run to end, then retry deletion.
  • Deletion closes every terminal for the agent, including detached terminals and terminals opened without a chat session, and waits for their processes to exit before retiring storage. Terminals for surviving agents remain usable.
  • Independent background commands are also cancelled and drained when their agent is deleted. Idle MCP runtimes retire before storage, while active MCP views keep deletion pending; close those views and retry. Tracked browser tabs use the same best-effort cleanup as session deletion.
  • During an upgrade, Doctor backs up and prepares a resumable pending deletion's old database schema under deletion ownership. Gateway recovery then completes normal session cleanup, including native bindings and related state, before applying the recorded file-removal choice.
  • If session-store cleanup fails, the agent is removed from config but its files and pending cleanup are retained. Resolve the reported storage error, then retry the same deletion command. After config publication succeeds, Gateway deletion returns UNAVAILABLE, names the failing cleanup step and database path in failed, and attaches purgeFailed: true to its error response; offline --json reports the same flag until the purge succeeds.
  • On installations that have not migrated shared auth yet, the legacy owner cannot be deleted. Run openclaw doctor --fix; after relocation into shared state SQLite, main follows the same deletion rules as any other agent.
  • An agent that owns a session database still used by another configured agent cannot be deleted, even when retaining files. Keep that owner configured; moving shared history to another owner requires a supported migration, which is not currently available.
  • When the Gateway is reachable, deletion routes through the Gateway so config and session-store cleanup share the same writer as runtime traffic. If the configured local Gateway cannot be reached before connecting, the CLI falls back to the offline local path and removes the agent's scheduled jobs transactionally. If local Gateway credentials are unavailable before the CLI can test reachability, deletion still falls back locally but warns that cron cleanup was skipped because a live scheduler may own the store.
  • Deletion removes the agent's bindings but not the channel accounts they routed, and it removes only bindings that target the deleted agent. A surviving account-wide or channel-wide binding to another agent keeps the whole account routing; a surviving peer binding only covers messages from that peer, so messages from other peers on the account can still be left ownerless. If deletion leaves a single configured agent, routing falls back to that sole agent. Unbound traffic is left undispatched when no fallback owner resolves; a configured agents.defaults.systemAgent.agentId, retained legacy owner, or caller-supplied owner can still catch it. A channel that keeps inbound messages for retry (Telegram, for example) may deliver a still-queued message after rebinding; see the routing retry limits. To retire the agent's bot as well, remove its channel account before deleting the agent, naming a surviving agent so channel-plugin discovery has a workspace owner: openclaw channels remove --agent <surviving-agent-id> --channel <channel> --account <id> --delete. Without --agent, a multi-agent config with no fallback owner fails with AgentSelectionRequiredError. Skip account removal if another agent's binding still uses that account.
  • If another agent's workspace is the same path, inside this workspace, or contains this workspace, the workspace is retained, and --json reports workspaceRetained, workspaceRetainedReason, and workspaceSharedWith.
  • Cleanup also retains directories containing another agent's registered database, so deleting a parent directory cannot discard the survivor's history.
  • Cleanup resolves symlink targets using their filesystem meaning, including .. segments, so a dangling workspace link cannot select an unrelated neighboring directory.

Automatic local fallback never applies to a remote Gateway or an OPENCLAW_GATEWAY_URL override, including loopback SSH tunnels. Connection or credential failures exit with an error and leave local config, workspace, and session state alone. Restore the Gateway connection and credentials, or run the command on the Gateway host.

Routing bindings

Use routing bindings to pin inbound channel traffic to a specific agent.

If you also want different visible skills per agent, configure agents.defaults.skills and agents.entries.*.skills in openclaw.json. See Skills config and Configuration reference.

List bindings:

openclaw agents bindings
openclaw agents bindings --agent work
openclaw agents bindings --json

Add bindings:

openclaw agents bind --agent work --bind telegram:ops --bind discord:guild-a

You can also add bindings when creating an agent:

openclaw agents add work --workspace ~/.openclaw/workspace-work --bind telegram:* --bind discord:*

If you omit accountId (--bind <channel>), OpenClaw resolves it from plugin setup hooks, forced account binding, or the channel's configured account count.

If you omit --agent for bind or unbind, OpenClaw targets the current default agent.

--bind format

Format Meaning
--bind <channel>:* Match all accounts on the channel.
--bind <channel>:<account> Match one account.
--bind <channel> Match the default account only, unless the CLI can safely resolve a plugin-specific account scope.

Binding scope behavior

  • A stored binding without accountId matches the literal default account key only.
  • accountId: "*" is the channel-wide fallback (all accounts) and is less specific than an explicit account binding.
  • Binding conflicts, duplicate detection, and removal compare normalized account IDs, just like message routing; account ID casing does not create a separate route.
  • If the same agent already has a matching channel binding without accountId, and you later bind with an explicit or resolved accountId, OpenClaw upgrades that existing binding in place instead of adding a duplicate.

Examples:

# match all accounts on the channel
openclaw agents bind --agent work --bind telegram:*

# match a specific account
openclaw agents bind --agent work --bind telegram:ops

# initial channel-only binding
openclaw agents bind --agent work --bind telegram

# later upgrade to account-scoped binding
openclaw agents bind --agent work --bind telegram:alerts

After the upgrade, routing for that binding is scoped to telegram:alerts. If you also want default-account routing, add it explicitly (for example --bind telegram:default).

Remove bindings:

openclaw agents unbind --agent work --bind telegram:ops
openclaw agents unbind --agent work --all

Identity files

Each agent workspace can include an IDENTITY.md at the workspace root:

  • Example path: ~/.openclaw/workspace/IDENTITY.md
  • set-identity --from-identity reads from the workspace root (or an explicit --identity-file).
  • Identity files must be valid UTF-8. Invalid encoding fails the import without changing the saved identity.

Avatar paths resolve relative to the workspace root and cannot escape it, even through a symlink.

Set identity

set-identity writes fields into agents.entries.*.identity: name, theme, emoji, avatar (workspace-relative path, http(s) URL, or data URI).

  • --agent or --workspace selects the target agent. If --workspace matches more than one agent, the command fails and asks you to pass --agent.
  • --workspace and --identity-file only select the agent or identity file. They do not change agents.entries.*.workspace. Explicitly empty or whitespace-only values are rejected; omit the flag to use the default identity location. Nonblank source paths preserve leading and trailing whitespace; quote them in your shell to select the exact file or directory. For --json, workspace is the resolved identity directory: the --workspace locator, the parent of --identity-file, or the agent's workspace when identity is read from there. It is null only when identity is supplied through flags with no identity directory. storedWorkspace reports the agent's persisted workspace.
  • Relocate an existing agent with openclaw config set agents.entries.<id>.workspace <dir>, then follow the CLI restart hint and confirm with openclaw agents list.
  • Local workspace-relative avatar image files are limited to 2 MB. HTTP(S) URLs and data: URIs are not checked against the local file-size limit.
  • When no explicit identity fields are provided, the command reads identity data from IDENTITY.md.

Load from IDENTITY.md:

openclaw agents set-identity --workspace ~/.openclaw/workspace --from-identity

Override fields explicitly:

openclaw agents set-identity --agent main --name "OpenClaw" --emoji "🦞" --avatar avatars/openclaw.png

Relocate the stored workspace:

openclaw config set agents.entries.work.workspace ~/.openclaw/workspace-work
openclaw agents list

Config sample:

{
  agents: {
    entries: {
      main: {
        identity: {
          name: "OpenClaw",
          theme: "space lobster",
          emoji: "🦞",
          avatar: "avatars/openclaw.png",
        },
      },
    },
  },
}