Skip to Content

Connect OpenClaw

This page is for your own OpenClaw install β€” the one you installed from npm, not the Companion OpenClaw app from the Hub app store.

Nothing here requires a Companion build. The packaged app installs stock OpenClaw from npm; the only difference is that it arrives pre-wired.

Before you start

You need two API keys and the addresses of both servers.

<hub-url> and <memory-url> below are your two servers’ base URLs β€” everything before /api/mcp. Neither has a port you can assume, so take both from the Hub dashboard if you are unsure: Hub, Memory.

OpenClaw can do this itself. Everything on this page β€” the MCP servers and first-class memory β€” is also published as an agent-readable skill. Ask it to set itself up from https://docs.ci.computer/connect/SKILL.md, or install the skillΒ  so it is there next time. You still supply the two keys. See Or let your agent do it.

Add the servers

Add Companion Hub

Prefer the CLI. openclaw mcp add probes the server before saving, so a wrong URL or key fails immediately instead of at first use:

openclaw mcp add ci-hub --url "<hub-url>/api/mcp" --transport streamable-http --header "Authorization=Bearer <hub-key>"

Add Companion Memory

openclaw mcp add ci-memory --url "<memory-url>/api/mcp" --transport streamable-http --header "Authorization=Bearer <memory-key>"

One line each, deliberately: a trailing \ continues a command in bash, but in PowerShell and cmd it is just another argument β€” pasted there, the first line runs without its --url and every later line fails as an unknown command.

Confirm both registered

openclaw mcp probe

This reports each server with the number of tools it advertises. Read the counts, not just the names β€” a server listed with 0 tools is connected and useless, and that is the failure this step exists to catch.

The same underlying problem can also surface as a line beginning ! rather than a tool count, when the server answers tools/list with -32601 Method not found instead of an empty list. Treat either shape as the same finding.

Editing the config by hand

openclaw mcp add writes ~/.openclaw/openclaw.json. You can edit it directly instead:

{ "mcp": { "servers": { "ci-hub": { "url": "<hub-url>/api/mcp", "transport": "streamable-http", "headers": { "Authorization": "Bearer ${HUB_MCP_API_KEY}" } }, "ci-memory": { "url": "<memory-url>/api/mcp", "transport": "streamable-http", "headers": { "Authorization": "Bearer ${CI_MEMORY_API_KEY}" } } } } }

Prefer the ${ENV_VAR} form over pasting keys directly, so the credential never lands in a config file that might be backed up or committed. The name must be upper-case (A-Z, 0-9, _, not starting with a digit).

Export it everywhere OpenClaw runs, not just in your shell. Substitution happens when the config is loaded, so a variable set in your terminal but not in the service environment is unset at load time. OpenClaw does not fail loudly: it logs missing env var "…" - feature using this value will be unavailable, leaves the literal ${VAR} in place, and starts normally. The server then sends Authorization: Bearer ${CI_MEMORY_API_KEY} verbatim and gets a 401 β€” so this arrives looking like a bad key rather than a missing one. Check the startup log before you go replacing credentials.

Setting the variable where the gateway can see it

The ${VAR} syntax itself is platform-neutral β€” OpenClaw substitutes it when the config loads. What differs is how you put the variable somewhere the gateway process inherits it.

# This shell only: export CI_MEMORY_API_KEY='<memory-key>' # Persist it: add that line to ~/.zshrc, ~/.bashrc, or the systemd unit's # Environment= / EnvironmentFile= if the gateway runs as a service.

The transport field must be streamable-http. OpenClaw is the client that names this field transport; Hermes omits it and Claude Code calls it type. Copying a working entry between clients without translating that field is a common failure.

After a hand edit, a running OpenClaw has to be told to pick it up:

openclaw mcp reload

reload only affects the process it runs in. It disposes the cached MCP runtimes held by that CLI invocation β€” which is the right command when OpenClaw is embedded in the same process, and a no-op when it is not. If you run OpenClaw as a service or a separate gateway, that process keeps its old config and you must restart it β€” openclaw daemon restart. The command reports success either way, because a fresh CLI process genuinely has nothing cached to dispose.

This is easy to miss, because openclaw mcp probe is also a separate process that reads the file and dials the server itself β€” it will report success while the running agent is still on the old config.

Verify

Ask your agent to list what it can do, or check directly:

openclaw mcp probe

Expect both servers listed with a non-zero tool count. If ci-memory shows zero, the key is missing the Intents scope β€” see the scope trap.

Read the ! lines too. A server that errors during the probe β€” including one answering -32601 Method not found, the other symptom of a missing Intents scope β€” is reported as a diagnostic rather than listed with a count, so scanning only for 0 tools misses it.

Removing a server

Revoking a key does not remove the entry that used it, and a stale entry fails on every start:

openclaw mcp unset ci-memory

Do this whenever you rotate or revoke a key, or the client keeps trying the old credential.

OPENCLAW_DATA_DIR does not isolate openclaw mcp add β€” OpenClaw does not read that variable at all, so the command writes to the real ~/.openclaw/openclaw.json. To isolate a scripted test, use one of the mechanisms OpenClaw does support: the --profile <name> flag, or the OPENCLAW_CONFIG_PATH / OPENCLAW_STATE_DIR environment variables.

First-class memory

Everything above gives your agent memory it can call. What it does not give you is memory that accumulates on its own β€” passive turn capture and bootstrap context injected at the start of a session. That comes from a memory-slot provider, OpenClaw’s plugins.slots.memory, which is a different mechanism from MCP entirely.

The provider is published as @companionintelligence/openclaw-memory. You do not need MCP configured to use it β€” the two are independent, and you can do this instead of the sections above if passive memory is all you want.

There are two ways to install it. They produce the same configuration.

The official way

Install the plugin

openclaw plugins install npm:@companionintelligence/openclaw-memory@2026.8.3

If this fails, check your Node version before anything else. OpenClaw refuses to run at all on a Node outside its supported range and says so β€” Node.js >=22.22.3 <23, >=24.15.0 <25, or >=25.9.0 is required β€” which reads like a plugin problem when it appears here. It is not; upgrade Node, or if you use a version manager check that the version on your PATH is the one you think it is. Verified working on native Windows against the pinned OpenClaw release once Node is in range.

Fill in what the installer does not

This is the step people miss. plugins install registers the plugin and stops there β€” it does not select it as your memory provider, and none of the rest of this block is written for you. Edit ~/.openclaw/openclaw.json:

Install before you edit, not after. slots.memory naming a plugin that is not installed yet makes the whole config invalid β€” plugin not found: companionintelligence β€” and OpenClaw then refuses to run plugins install, so you cannot fix it by carrying on. If you have already done it in that order, remove the plugins block, install, then put it back.

{ "plugins": { "slots": { "memory": "companionintelligence" }, "entries": { "companionintelligence": { "enabled": true, "hooks": { "allowConversationAccess": true }, "config": { "url": "<memory-url>", "token": "<memory-key>" } } } }, "tools": { "alsoAllow": ["memory_store"] }, "hooks": { "internal": { "entries": { "session-memory": { "enabled": false } } } } }

Every line earns its place:

KeyWhy
slots.memorySelects the provider. Without it the plugin is installed and inert
hooks.allowConversationAccessOpenClaw only delivers conversation hooks to a plugin that opts in. Without it you get the tools and nothing accumulates β€” the entire point of this section
tools.alsoAllowIf a tools profile or allowlist narrows your tool set, the built-in group:memory group covers search and get only, so memory_store has to be named. On an unrestricted config it is harmless
session-memory disabledOpenClaw’s bundled hook keeps a parallel local memory β€” session summaries written to workspace files on /new and /reset β€” that this provider does not manage and expects not to compete with

Add to tools.alsoAllow, and never introduce tools.allow. alsoAllow extends the default set; allow replaces it with an exclusive allowlist, so creating it denies every tool not named in it and breaks unrelated things on your machine.

The key for token needs different scopes than an MCP key. This provider talks REST, not MCP, so the key must carry the Memory scope (plus Intents for the intent tools) at capability Read & write β€” the dialog’s default. A key minted for the MCP sections above (MCP + Intents) is refused on every capture call, and the plugin never breaks your session over a failed write, so the result is memory that silently never accumulates while every check on this page passes. One key with Memory, Intents and MCP covers both setups. See Get Your API Keys.

url is the Companion Memory base URL β€” the same <memory-url> used above, without /api/mcp. It is written once and never re-resolved, so this agent is configured for exactly one network position. A laptop that reaches your Hub over a VPN at home and not at all from a cafΓ© needs the address that works from wherever it actually runs. See Find your address first for the routes and how to read each one off the dashboard.

Restart and verify

Configuration is read at startup, so the gateway has to come back before any of this takes effect:

openclaw daemon restart

That is the command when the gateway runs as an installed service β€” launchd on macOS, systemd on Linux, a Scheduled Task named OpenClaw Gateway on native Windows. openclaw daemon status tells you whether yours is one, naming the service manager and the unit or task it found. If you instead start the gateway yourself in a terminal, stop that process and start it again β€” daemon restart manages the service and will not touch a gateway you are running by hand.

Then:

openclaw plugins inspect companionintelligence --runtime --json

Look inside the plugin object for "status": "loaded" and "activationReason": "selected memory slot". toolNames should include memory_store.

Know what each check proves. plugins inspect is a separate process that reads the config from disk and loads the plugin itself β€” the same trap this page describes for openclaw mcp probe β€” so it reports loaded whether or not the running gateway has restarted, and it never dials the server, so a typo in url or an unreachable address still loads cleanly. The check that exercises the running gateway and the connection is /ci-memory in a live session.

The proof that passive capture is actually on: have a short conversation, then look for the turn in the Companion Memory dashboard β€” or start a fresh session and ask about something from the last one. Nothing in that flow calls a memory tool by hand, which is the point.

The cihub connect way

If you are working on the Hub host itself, one command does the install and the configuration:

cihub connect openclaw --memory-url "<memory-url>" --memory-key "<memory-key>"

It probes the server before touching anything, installs the pinned plugin version, writes every key in the table above, and backs up your config first. Add --dry-run to see exactly what it would do and write nothing. You still restart the gateway afterwards β€” openclaw daemon restart β€” as the command’s output reminds you.

The pre-flight probe checks the key as well as the address β€” it calls an endpoint that requires the Memory scope, so a key that would fail silently at capture time is refused up front, with nothing written.

It configures the machine it runs on. If your agent lives on your laptop and the Hub is an appliance across the room, use the official way on the laptop β€” that split is the design, not a gap.

Optionally add --hub-url and --hub-key and it will register the Hub MCP server too, replacing the openclaw mcp add ci-hub step near the top of this page.

When memory does not accumulate

The command refused with β€œthe memory slot is held by …”. Another provider is selected, and the configuration this page writes would take the slot from it. That selection was a deliberate choice you or a previous setup made, so cihub connect refuses to overwrite it without --force. (Plain openclaw plugins install does not touch the slot either way β€” which is why step 2 exists.)

Setup succeeded, tools appear, nothing is captured. Two usual causes, both silent. First, the key: wrong, or missing the Memory scope, or minted Read-only β€” the plugin swallows failed writes rather than break your session, and no check on this page can catch a bad key, so re-check the key before anything else. Second, hooks.allowConversationAccess: it must be true on the plugin’s own entry β€” not at the top level.

Session summaries still pile up in workspace memory/*.md files. The bundled session-memory hook is still enabled, keeping its parallel local memory alongside this provider.

Changes did nothing. A running gateway keeps its old config. openclaw mcp reload does not help here β€” it disposes MCP runtimes in the process that runs it, and this is not MCP. Restart the gateway with openclaw daemon restart, or by stopping and starting it yourself if you do not run it as a service.

Last updated on