#mattermost help

1 messages · Page 1 of 1 (latest)

misty moon
#

I am setting up mattermost, and have question about the docs regarding native slash commands. what is callback url?

stark matrixBOT
#

To help others find answers, you can mark your question as solved via Right click solution message -> Apps -> âś… Mark Solution

idle craterBOT
chilly birchBOT
#

It’s the full URL Mattermost will POST to when someone runs a native slash command.

So:

  • callbackPath = just the path, like /api/channels/mattermost/command
  • callbackUrl = the full externally reachable URL, like https://gateway.example.com/api/channels/mattermost/command

Example:

commands: {
  native: true,
  callbackPath: "/api/channels/mattermost/command",
  callbackUrl: "https://gateway.example.com/api/channels/mattermost/command",
}
#

You usually need callbackUrl when Mattermost cannot directly reach OpenClaw’s auto-detected local address, for example with:

  • reverse proxies
  • Docker / separate hosts
  • Tailscale / private network
  • public gateway URL differing from local bind address

If you leave it out, OpenClaw tries to derive it automatically.

Important bits:

  • Mattermost must be able to reach that URL
  • don’t use localhost unless Mattermost is on the same host/network namespace
  • don’t use your Mattermost base URL unless it reverse proxies that callback path to OpenClaw

Docs:

misty moon
#

So that is the same host:port as the gateway ws?

chilly birchBOT
#

Yep, usually same host and port as the gateway, but use the HTTP(S) URL, not the ws:// / wss:// URL.

So if your gateway is reachable at:

  • http://myhost:18789

then the callback URL is typically:

  • http://myhost:18789/api/channels/mattermost/command

If your WS endpoint is something like:

  • ws://myhost:18789/...

then the callback is still:

  • http://myhost:18789/api/channels/mattermost/command
#

And if you’re behind TLS / proxy:

  • wss://gateway.example.com/... corresponds to
  • https://gateway.example.com/api/channels/mattermost/command

So, same gateway base address, different protocol/path.

Quick rule:

  • WebSocket client connection: ws:// or wss://
  • Mattermost slash callback: http:// or https://

You can test it with:

curl https://<gateway-host>/api/channels/mattermost/command
#

A good sign is 405 Method Not Allowed, because that means OpenClaw is there and waiting for POSTs.

If you want, paste your actual gateway URL and I’ll translate it into the exact callback URL.

misty moon
#

And how do I do the equivalent of binding a channel in Mattermost to an agent?

chilly birchBOT
#

If you mean persistent routing of a Mattermost channel to a specific agent, there isn’t a Mattermost /focus equivalent right now.

For Mattermost, you do it with agent bindings:

Bind the whole Mattermost account to an agent

openclaw agents bind --agent work --bind mattermost:default

That routes Mattermost traffic for that account to work.

Bind one specific Mattermost channel to an agent

Use a bindings[] entry in config:

#
{
  bindings: [
    {
      agentId: "work",
      match: {
        channel: "mattermost",
        accountId: "default",
        peer: { kind: "channel", id: "<mattermost-channel-id>" },
      },
    },
  ],
}

A few important bits:

#
  • peer.kind: "channel" is what you want for a Mattermost channel
  • use the Mattermost channel ID, not the display name
  • put specific peer bindings before broader Mattermost bindings, since routing is “most specific wins”

So the practical difference is:

  • Discord thread/topic style focus = interactive binding features
  • Mattermost = normal routing bindings via config (or account-level agents bind)

Docs:

If you want, I can help you write the exact bindings block if you paste:

  1. your agent id
  2. your Mattermost account id (default if you only have one)
#
  1. the Mattermost channel id
misty moon
#

I'm confused about your comment that there isn't a way to bind a channel to an agent, but then you show binding json that shows binding channel to agent. What is different?

chilly birchBOT
#

Yeah, that was sloppy wording on my part, sorry.

What I meant was:

Mattermost does support channel → agent routing

You can statically bind a specific Mattermost channel to an agent with config like:

{
  bindings: [
    {
      agentId: "work",
      match: {
        channel: "mattermost",
        peer: { kind: "channel", id: "<channel-id>" },
      },
#
    },
  ],
}

What Mattermost does not currently have

It does not have the more interactive “focus/bind this conversation/thread now” flow that some other surfaces have, like:

  • /focus ...
  • thread-bound agent sessions
  • live per-thread rebinding from chat commands

So the difference is:

  • Static routing binding: yes, Mattermost supports this
  • Interactive runtime binding/focus feature: no, not in the same way
#

Also:

  • openclaw agents bind --bind mattermost:default is account-level binding
  • bindings[].match.peer is specific-channel binding

So you absolutely can bind a Mattermost channel to an agent, it just happens through routing config, not through a Mattermost-native focus command.

Docs:

If you want, I can give you a tiny “account-level vs single-channel” config example side by side.

misty moon
#

Ok that makes sense, another question is I use /status often but it seems that Mattermost already uses that command for itself. How to do?

chilly birchBOT
#

Yep, for Mattermost the answer is: use /oc_status, not /status.

Mattermost already owns /status, so OpenClaw registers its native Mattermost commands with an oc_ prefix to avoid collisions, for example:

  • /oc_status
  • /oc_help
  • /oc_model
  • /oc_models
  • /oc_new

Important bit: this only works if you enabled native Mattermost commands:

channels: {
  mattermost: {
    commands: {
#
      native: true
    }
  }
}

native: "auto" is effectively off for Mattermost, so you need true.

So the short version is:

  • /status = Mattermost’s command
  • /oc_status = OpenClaw’s command

Docs: https://docs.openclaw.ai/channels/mattermost

If you want, I can also give you the minimal working Mattermost commands block for native slash commands.

misty moon
#

How do you get the channel-id?

chilly birchBOT
#

For bindings, I’d use the real Mattermost channel ID.

The easiest reliable way is the Mattermost API. If your channel URL is:

https://chat.example.com/<team-name>/channels/<channel-name>

then query:

curl -H "Authorization: Bearer $MATTERMOST_BOT_TOKEN" \
  "https://chat.example.com/api/v4/teams/name/<team-name>/channels/name/<channel-name>"

That returns channel JSON, including:

#
{
  "id": "xxxxxxxxxxxxxxxxxxxxxxxxxx",
  "name": "channel-name",
  "display_name": "Channel Name"
}

Use that id in the binding:

peer: { kind: "channel", id: "xxxxxxxxxxxxxxxxxxxxxxxxxx" }

Small nuance:

  • for outbound send targets, OpenClaw can resolve names like #alerts
#
  • for bindings[].match.peer.id, use the actual opaque Mattermost ID

If you want, send me a fake example URL like:

https://chat.example.com/myteam/channels/alerts

and I’ll show you the exact API call + binding snippet.

misty moon
#

So no way to get the channel-id from the mattermost web gui?

chilly birchBOT
#

Right, not from the normal Mattermost web UI in any nice built-in way, as far as I know.

The regular GUI usually gives you:

  • team name
  • channel name
  • channel URL

…but not the opaque channel ID directly.

So I’d split it like this:

  • Normal web GUI: no, not really
  • Browser devtools / network tab: yes, you can often find it there
  • Mattermost API: yes, this is the clean/reliable way

That’s why I recommended the API call. It’s the least annoying path 🙂

#

If you really want a browser-only route, I can help you grab it from devtools too.

misty moon
#

yes show me how using devtools

chilly birchBOT
#

Yep, easiest devtools path is via the Network tab.

Method 1, Network tab

  1. Open the Mattermost channel you care about.
  2. Open devtools (F12 or right click → Inspect).
  3. Go to Network.
  4. Filter to Fetch/XHR.
  5. Reload the page, or switch to another channel and back.
  6. In the filter box, try searching for:
    • channels
    • posts
    • your channel name
  7. Open a request that returns channel data, then check Response or Preview.
  8. Look for an object like:
#
{
  "id": "xxxxxxxxxxxxxxxxxxxxxxxxxx",
  "name": "alerts",
  "display_name": "Alerts"
}

That id is the channel ID.

What usually works best

A request returning a list of channels for the team is often the easiest one, because you can just find your channel by name / display_name and copy its id.

If you want a slightly more direct trick

In Network, filter for:

#
channels

then click requests whose response is a JSON array/object of channels, not CSS/JS assets.


If you get stuck, paste a screenshot of the Network request names you see, and I’ll tell you which one to open.

misty moon
#

ok I added a binding for a channel to a agent. But in the channel I tried /oc_status and it didn't work

chilly birchBOT
#

Got it. First, what does openclaw --version show?

Also, what exactly happens when you run /oc_status?

  • Mattermost says command not found
  • you get Unauthorized / no allowlist
  • it says Processing... and then nothing
  • some other error

Those point to different causes.

Most likely, it’s one of these:

1. The slash command never registered

Binding a channel to an agent does not register Mattermost slash commands by itself.

Check that you have:

#
channels: {
  mattermost: {
    commands: {
      native: true
    }
  }
}

Then restart the gateway and check logs:

openclaw logs --follow

You want to see something like:

#
mattermost: slash commands registered (... callback=...)

If you see errors like:

  • failed to register slash commands
  • native slash commands enabled but no commands could be registered

then registration is the problem.

2. The callback URL is unreachable from Mattermost

If Mattermost can show the command but callback POSTs never reach OpenClaw, /oc_status won’t complete.

Quick check from the Mattermost side/network path:

#
curl https://<gateway-host>/api/channels/mattermost/command

A good result is:

405 Method Not Allowed

If you get 404 or it times out, the callback path is wrong or unreachable.

If your callback uses a private/internal host, Mattermost may also need:

ServiceSettings.AllowedUntrustedInternalConnections

to include that host/domain.

#

3. The channel/user is not authorized

A binding only says which agent should handle the message. It does not automatically allow commands in that channel.

Mattermost channels default to allowlist behavior, so you may need either:

  • groupPolicy: "open" for testing, or
  • groupAllowFrom, or
  • commands.allowFrom

If OpenClaw receives the slash command but denies it, you’ll usually see an unauthorized-style response.


If you paste these 3 things, I can narrow it down fast:

  1. openclaw --version
  2. your channels.mattermost config block
misty moon
#

I have this as commands section
"commands": {
"native": true,
"nativeSkills": true,
"callbackPath": "/api/channels/mattermost/command",
"callbackUrl": "http://100.76.32.93:18789/api/channels/mattermost/command"
}

I do see this in a log
2026-04-18T05:00:02.187-04:00 info plugins {"subsystem":"plugins"} mattermost: registered slash command callback at /api/channels/mattermost/command

chilly birchBOT
#

That log line is useful, but it only means OpenClaw mounted the HTTP callback route.

It does not prove Mattermost successfully registered /oc_status.

The key distinction is:

  • good but incomplete:
    mattermost: registered slash command callback at /api/channels/mattermost/command
  • what we also want to see:
    mattermost: slash commands registered (... commands across ... teams, callback=...)

So from what you’ve pasted, I’d check these next:

1. Is the config block under channels.mattermost.commands?

If that snippet is under the global top-level commands, that’s the problem.

It should be shaped like:

#
{
  channels: {
    mattermost: {
      commands: {
        native: true,
        nativeSkills: true,
        callbackPath: "/api/channels/mattermost/command",
        callbackUrl: "http://100.76.32.93:18789/api/channels/mattermost/command"
      }
    }
  }
}

2. Look for the real registration log

Search logs for any of these:

#
  • mattermost: slash commands registered
  • mattermost: failed to register slash commands
  • mattermost: failed to register slash commands for team
  • mattermost: native slash commands enabled but no commands could be registered

If you only have the callback-route log, registration may have failed after that.

3. Your callback URL is a private 100.x.x.x address

That can work, but only if the Mattermost server can reach it.

From the Mattermost server, this should work:

curl http://100.76.32.93:18789/api/channels/mattermost/command

Expected result:

#
405 Method Not Allowed

If it times out or 404s, that’s the issue.

Also, because it’s a private/internal address, Mattermost may need:

ServiceSettings.AllowedUntrustedInternalConnections

to include:

100.76.32.93

4. If /oc_status exists but replies “Unauthorized”

#

Then registration is fine, and the problem is channel access control.

A binding does not authorize the channel. For quick testing, you can temporarily make Mattermost groups open:

channels: {
  mattermost: {
    groupPolicy: "open"
  }
}

(or set groupAllowFrom properly)

5. What does Mattermost itself do?

This matters a lot:

#
  • If Mattermost says /oc_status is unknown → registration problem
  • If it runs but hangs / nothing comes back → callback reachability problem
  • If it says Unauthorized → allowlist / policy problem

Also, please send:

openclaw --version

and if you can, paste the log lines around:

  • gateway startup
  • the moment you run /oc_status

That should narrow it down pretty fast.

misty moon
#

$ curl http://100.76.32.93:18789/api/channels/mattermost/command | jq
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 108 100 108 0 0 777 0 --:--:-- --:--:-- --:--:-- 782
{
"response_type": "ephemeral",
"text": "Slash commands are not yet initialized. Please try again in a moment."
}

chilly birchBOT
#

Ah, that narrows it down a lot.

That response means:

  • the callback URL is reachable
  • but slash commands never finished initializing

So the problem is not the channel binding, and not basic network reachability to the callback.

It means OpenClaw mounted the route, but did not successfully activate/register the Mattermost slash commands.

In practice, you should be seeing a startup log like:

mattermost: slash commands registered (... commands across ... teams, callback=...)
#

If instead you only see the callback-route log, then registration failed earlier.

What to check next

  1. Make sure the config is under channels.mattermost.commands, not global top-level commands.

  2. Restart the gateway, then inspect startup logs specifically for Mattermost slash registration.

You want to find either:

  • mattermost: slash commands registered
  • or one of these errors:
    • mattermost: failed to register slash commands
    • mattermost: failed to register slash commands for team ...
    • mattermost: native slash commands enabled but no commands could be registered
  1. Paste those startup log lines here.
#

What this likely means

One of these is happening:

  • OpenClaw failed to register the /oc_* commands with Mattermost
  • it failed for every team
  • or the commands config is on the wrong config path / wrong account

Very important

Your curl result also means the docs check changes slightly here:

  • 405 = callback route is active and slash commands initialized
  • 503 "not yet initialized" = route exists, but slash registration/activation failed

So you’re actually pretty close, we just need the registration failure log, not the callback log.

Also please send:

#
openclaw --version

and if possible the full channels.mattermost block (with secrets redacted).

misty moon
#

in openclaw.json

"mattermost": {
"enabled": true,
"botToken": "xxx",
"baseUrl": "https://mattermost.search.dontexist.com",
"dmPolicy": "pairing", "commands": {
"native": true,
"nativeSkills": true, "callbackPath": "/api/channels/mattermost/command",
"callbackUrl": "http://100.76.32.93:18789/api/channels/mattermost/command" } }

[mattermost] connected as @openclaw
2026-04-18T08:52:43.515-04:00 [mattermost] native slash commands enabled but no commands could be registered; keeping slash callbacks inactive
2026-04-18T08:52:43.516-04:00 [mattermost] interactions callbackUrl resolved to http://localhost:18789/mattermost/interactions/default (loopback) while baseUrl is https://mattermost.search.dontexist.com. This MAY be unreachable depending on your deployment. If button clicks don't work, set channels.mattermost.interactions.callbackBaseUrl to a URL reachable from the Mattermost server (e.g. your public reverse proxy URL).

chilly birchBOT
#

Nice, this is the smoking gun:

native slash commands enabled but no commands could be registered; keeping slash callbacks inactive

So the issue is not the callback path anymore.
OpenClaw connected to Mattermost, but it failed to create any /oc_* commands in Mattermost.

Also, this warning is separate:

interactions callbackUrl resolved to http://localhost:18789/...

That affects buttons/interactions, not /oc_status.

#

What this most likely means

Usually one of these:

  1. The bot is not in any Mattermost team

    • slash commands are registered per team
    • if @openclaw is not actually a member of the team, OpenClaw has nowhere to register them
  2. Mattermost does not allow this user/bot to manage slash commands

    • integrations/slash commands may be disabled
    • or restricted to admins / users with the right permission
  3. Command registration failed, and the detailed failure lines just weren’t in the pasted snippet

What I’d check next

A. Is @openclaw in the team?

#

Not just connected, but actually added to the team where this channel lives.

That’s the first thing I’d check, because this exact log can happen if the bot has zero teams.

B. Are custom slash commands enabled in Mattermost?

Mattermost can block slash command creation if integrations are disabled or restricted.

C. Search logs for the more detailed lines

Look for any of these:

  • failed to list existing commands
  • failed to register command /oc_status
  • failed to register slash commands for team
  • trigger /oc_status already used

Those will tell us whether it’s permissions, team membership, or a naming conflict.

#

What success should look like

After fixing it and restarting, you want to see:

mattermost: slash commands registered (... commands across ... teams, callback=...)

Not just the callback route line.

My best guess from what you pasted

Most likely: @openclaw is not actually in the Mattermost team, or the bot/user lacks permission to create slash commands there.

If you want, next paste either:

  1. whether @openclaw is in the team, and
#
  1. any extra log lines containing failed to register command

and I can narrow it down further.

misty moon
#

Yes probably openclaw bot is not part of team. How to add it to team?

chilly birchBOT
#

Yep, in Mattermost bot accounts are basically users, so you add them to a team like a normal member.

Usual UI path

  1. Open the target team in Mattermost
  2. Open the team dropdown / menu
  3. Click Invite People (or Add Members)
  4. Search for the bot account, like @openclaw
  5. Invite it to the team

Then also add it to the specific channel if needed, same idea:

  1. Open the channel
  2. Channel menu
  3. Add Members
  4. Add @openclaw
#

If the bot does not show up

You may need to do it from admin settings instead:

  • System Console → User Management → Teams → <your team> → Add Members
  • or check Integrations / Bot Accounts to confirm the bot exists and is enabled

After adding it

Restart the gateway, then look for:

mattermost: slash commands registered (... commands across ... teams, callback=...)

That’s the log line you want.

Small note: team membership is the important part for slash command registration. Channel membership is still a good idea for normal operation.

#

If you want, after you add it, paste the next startup log and I’ll sanity check it.

misty moon
#

ok getting close
2026-04-18T09:03:09.329-04:00 [mattermost] registered command /oc_status (id=uexa4bp9z3bsmkip4jcbgbd1ch)

But running /oc_status in mattermost I get "Command with a trigger of 'oc_status' failed."

chilly birchBOT
#

Yep, that means registration is working now 🎉

So the remaining failure is on invocation, not setup.

The key question now is: does the callback request actually reach OpenClaw when you run /oc_status?

What to check

Run /oc_status, then immediately check OpenClaw logs.

You want to see a line like:

mattermost: slash command /oc_status from ...

If you do not see that line

#

Mattermost is failing before OpenClaw ever receives the callback.

That usually means one of these:

  • Mattermost cannot reach http://100.76.32.93:18789/...
  • Mattermost is blocking private/internal callback targets
  • firewall / routing / Tailscale path issue

Because you’re using a 100.x.x.x address, make sure Mattermost allows it via:

ServiceSettings.AllowedUntrustedInternalConnections

and include just:

100.76.32.93
#

not the full URL.

Also test from the Mattermost server itself, not another machine:

curl -i http://100.76.32.93:18789/api/channels/mattermost/command

Any real HTTP response is good, connection failure is bad.

If you do see that line

Then the callback reached OpenClaw, and we debug the response path next.

In that case, paste the log lines generated when you run /oc_status.

Very likely from your symptom

Since Mattermost says:

#

Command with a trigger of 'oc_status' failed.

and not an OpenClaw-generated message, my bet is:

Mattermost cannot successfully POST to your callback URL, most likely because of the private 100.76... address or internal-connection restrictions.

So next best step:

  1. add 100.76.32.93 to AllowedUntrustedInternalConnections
  2. run /oc_status
  3. check whether OpenClaw logs a slash command /oc_status line

If you paste that result, we can probably finish this fast.

misty moon
#

Ok the AllowedUntrustedInternalConnections helped, but now getting this

curl -q http://100.76.32.93:18789/api/channels/mattermost/command | jq
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 108 100 108 0 0 54766 0 --:--:-- --:--:-- --:--:-- 105k
{
"response_type": "ephemeral",
"text": "Slash commands are not yet initialized. Please try again in a moment."
}

#

Even though I see

command /oc_taskflow already registered (id=uxkoqxr5ppd3fqrqqqhs1tx9rh)
2026-04-18T09:29:54.778-04:00 [mattermost] command /oc_taskflow_inbox_triage already registered (id=bwzefjaambn3j8jrzurnwz3cdc)
2026-04-18T09:29:54.778-04:00 [mattermost] command /oc_ticktick already registered (id=x6qp5m7oy3f1fx5obcksx66iay)
2026-04-18T09:29:54.779-04:00 [mattermost] command /oc_tmux already registered (id=icu1gmiiybd6ijhcsqm69fyrxe)
2026-04-18T09:29:54.779-04:00 [mattermost] command /oc_weather already registered (id=4cmj5edpppr8pxr3wpnngxauro)
2026-04-18T09:29:54.780-04:00 [mattermost] command /oc_wiki_maintainer already registered (id=ih4xajrn7jb48rjuecybafkcxh)
2026-04-18T09:29:54.781-04:00 [mattermost] command /oc_analyze_logs already registered (id=z193pqin43yq5npw7atq95s7iy)
2026-04-18T09:29:54.781-04:00 [mattermost] slash commands activated for account default (31 commands)
2026-04-18T09:29:54.782-04:00 [mattermost] slash commands registered (31 commands across 1 teams, callback=http://100.76.32.93:18789/api/channels/mattermost/command)

chilly birchBOT
#

That response means the currently running OpenClaw process still has not activated Mattermost slash commands in memory.

So even though you saw:

registered command /oc_status

the gateway serving 100.76.32.93:18789 is still effectively in the pre-initialized state.

Important detail

After slash commands are really initialized, that curl should not say:

Slash commands are not yet initialized
#

It would usually return something like:

  • invalid payload
  • unauthorized / invalid token
  • etc.

So this tells us the active gateway process has not completed slash init.

What I’d do next

  1. Make sure the bot is now actually in the Mattermost team
  2. Do a full:
openclaw gateway restart
#
  1. Watch startup logs and look specifically for the final success line:
mattermost: slash commands registered (... commands across ... teams, callback=...)

Not just:

registered command /oc_status

That per-command line is good, but the real proof is the final slash commands registered summary.

If you restart and still get “not yet initialized”

Then one of these is true:

#
  • you’re hitting a different gateway instance/process than the one whose logs you’re reading
  • the gateway restarted but did not finish slash registration on that run
  • there are multiple configs / processes involved

Best next paste

Please paste, from one fresh restart, all lines from:

[mattermost] connected as ...

through every line containing:

slash
#

Also, if you can, include:

openclaw gateway status
openclaw --version

I think we’re very close, this now looks more like “wrong process / incomplete restart” than config shape.

#

Yep, that’s the same result, so the active gateway is still not initialized for Mattermost slash commands.

At this point, more curl won’t help. The next step is a fresh restart plus startup logs.

Do this next

openclaw gateway restart
openclaw gateway status
openclaw logs --follow

Then watch for a line like:

mattermost: slash commands registered (... commands across ... teams, callback=...)
#

That is the line that matters.

If you do not see that line

Paste all startup log lines containing:

  • mattermost
  • slash

Because right now the evidence says one of these is true:

  • the gateway did not restart with the config you think it did
  • slash registration still failed on startup
  • or you have a different/stale gateway process serving 100.76.32.93:18789

Quick sanity rule

  • if curl says “Slash commands are not yet initialized”, the running gateway is not ready
#
  • once it is ready, that exact curl should stop returning that message

So the next useful artifact is startup logs after a restart, not another curl output.

#

Ah, perfect, this changes the diagnosis.

Those logs prove the gateway instance in your logs is initialized correctly:

slash commands activated for account default (31 commands)
slash commands registered (31 commands across 1 teams, callback=http://100.76.32.93:18789/api/channels/mattermost/command)

So if a plain curl to that same URL still says:

Slash commands are not yet initialized

then you are almost certainly not hitting the same gateway process with curl/Mattermost that produced those logs.

#

Why I’m pretty confident

Once slash commands are activated, a bare GET to that path should not return “not yet initialized”.

It should return something more like:

  • invalid payload
  • unauthorized / invalid token

So this contradiction strongly suggests:

  • a second/stale OpenClaw gateway process
  • a reverse proxy pointing at the wrong backend
  • or 100.76.32.93:18789 is not actually the same process whose logs you’re reading

Best next check

#

From the gateway host, compare these two:

curl -q http://127.0.0.1:18789/api/channels/mattermost/command | jq
curl -q http://100.76.32.93:18789/api/channels/mattermost/command | jq

If they return different responses, that’s the smoking gun.

Also run

openclaw gateway status

I want to know what address/URL the running service thinks it owns.

#

What I suspect

Most likely:

  • 127.0.0.1:18789 is your freshly restarted, properly initialized gateway
  • 100.76.32.93:18789 is reaching something else, or an older process/path

If you paste:

  1. both curl outputs
  2. openclaw gateway status

we can probably pin this down immediately.

misty moon
#

$ curl -q http://127.0.0.1:18789/api/channels/mattermost/command | jq
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 108 100 108 0 0 47914 0 --:--:-- --:--:-- --:--:-- 54000
{
"response_type": "ephemeral",
"text": "Slash commands are not yet initialized. Please try again in a moment."
}
node@b76b8a18aff4:/app$ curl -q http://100.76.32.93:18789/api/channels/mattermost/command | jq
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 108 100 108 0 0 48824 0 --:--:-- --:--:-- --:--:-- 54000
{
"response_type": "ephemeral",
"text": "Slash commands are not yet initialized. Please try again in a moment."
}
node@b76b8a18aff4:/app$ openclaw gateway status

🦞 OpenClaw 2026.4.15 (unknown) — Shell yeah—I'm here to pinch the toil and leave you the glory.

│
â—‡
Service: systemd (disabled)
File logs: /tmp/openclaw/openclaw-2026-04-18.log

Config (cli): ~/.openclaw/openclaw.json
Config (service): ~/.openclaw/openclaw.json

Gateway: bind=loopback (127.0.0.1), port=18789 (env/config)
Probe target: ws://127.0.0.1:18789
Dashboard: http://127.0.0.1:18789/
Probe note: Loopback-only gateway; only local clients can connect.

Runtime: unknown (systemctl not available; systemd user services are required on Linux.)
RPC probe: ok

systemd user services unavailable.
systemd user services are unavailable; install/enable systemd or run the gateway under your supervisor.
If you're in a container, run the gateway in the foreground instead of openclaw gateway.

Listening: *:18789
Troubles: run openclaw status
Troubleshooting: https://docs.openclaw.ai/troubleshooting

chilly birchBOT
#

Thanks, this is the key clue.

At this point, I’m pretty sure your config is basically correct.
What you’re showing now looks like a bug / reconnect race, not a callback-url mistake.

Why:

  • these logs prove slash commands were initialized:
slash commands activated for account default (31 commands)
slash commands registered (31 commands across 1 teams, callback=http://100.76.32.93:18789/api/channels/mattermost/command)
  • but the callback route later says:
#
Slash commands are not yet initialized

Those two states should not both be true at the same time.

What that usually means

The Mattermost monitor likely:

  1. connected
  2. registered + activated slash commands
  3. then got torn down / reconnected
  4. which cleared the in-memory slash-command state again

So I’d now look for Mattermost reconnect / shutdown behavior right after that successful block.

Best next check

#

Keep logs open:

openclaw logs --follow

Then watch for:

  • another [mattermost] connected as ...
  • disconnect / reconnect lines
  • anything after the successful slash registration block

Very targeted test

After a fresh restart, the moment you see:

#
slash commands registered ...

immediately run /oc_status.

  • If it works briefly, then later breaks, that strongly confirms a reconnect/reset bug.
  • If it never works and logs show Mattermost reconnecting, same conclusion.

My honest take

This is starting to look like a real bug in 2026.4.15, not you misconfiguring it.

If you can capture the log slice from:

  • [mattermost] connected as @openclaw
  • through slash commands registered
  • through the next Mattermost-related lines after that