#Multi-agent orchestration: Can OpenClaw coordinate multiple AI systems (Claude, Gemini, custom agent

1 messages Ā· Page 1 of 1 (latest)

river kindle
#

I'm building a JARVIS-style system with different AI agents handling
different roles:

  • One agent for emotional/frequency support (running on OpenClaw/MiniMax)
  • Claude for engineering and logic
  • Gemini for document processing and legal work

My question: Does OpenClaw support multi-agent orchestration?
Can it act as a coordinator that routes tasks to different AI systems
based on task type?

Running OpenClaw 2026.4.15 on WSL2.

quiet parrotBOT
fresh sentinelBOT
#

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

quiet parrotBOT
rigid hollow
#

It can, but it can also be a little finicky. In my experience, the model "driving" is the most decision you'll make. TL;DR: use Opus or at least Sonnet. I switched from Opus to Codex a few weeks ago because Anthropic and the drop-off has been noticeable. Regular Chatgpt 5.4 might be fine, but then you're paying for API usage so why not just use Sonnet (disclaimer, i haven't checked prices recently). But this is the one you'll be dealing with most of the time, so if you're having to make cost tradeoffs this is the place to spend more. Set up very specific instructions about how you want the work delegated. If you want to do this manually, edit the AGENTS.md file. But what I'd recommend is to have your main agent do ALL of the setup for the sub agents. If you're going as far as putting your subs on separate physical hardware then have your primary do ALL the work after you lay down the OS. The more your agent does the better they will understand the setup and how and when to use them.

solemn ospreyBOT
#

Yes, basically.

OpenClaw has 3 useful pieces for this:

  1. Multi-agent routing
    Multiple isolated agents, each with its own workspace, auth, sessions, and default model.
    Docs: https://docs.openclaw.ai/concepts/multi-agent

  2. Sub-agents
    A main agent can spawn worker agents for parallel/background work and get the result back.
    Docs: https://docs.openclaw.ai/tools/subagents

  3. ACP sessions
    For external harnesses like Claude Code, Codex, Gemini CLI, OpenClaw can route work through ACP instead of native sub-agents.
    Docs: https://docs.openclaw.ai/tools/acp-agents

So for your setup, a clean pattern is:

#
  • Coordinator agent = the one you talk to
  • Emotional/support agent = native OpenClaw agent with its own model/profile
  • Engineering agent = Claude via ACP or a separate OpenClaw agent with Anthropic model
  • Docs/legal agent = Gemini via ACP or a separate Google-backed agent

One important nuance: OpenClaw gives you the orchestration primitives, but it is not a magical built-in ā€œtask classifier/routerā€ by default.
The routing policy is usually:

  • explicit bindings by channel/thread/account, or
  • delegation rules you define in AGENTS.md / agent instructions, or
  • explicit sessions_spawn / ACP spawning from the coordinator

So the short answer is:

  • Yes, it supports multi-agent orchestration
  • Yes, it can act as a coordinator
  • But task-type routing is something you define, not fully automatic out of the box
#

Also worth knowing: this setup gets token-heavy and a bit finicky once you add lots of delegation layers, so I’d start with one coordinator + 2-3 specialized workers instead of a huge swarm.

The FAQ also answers this pretty directly: OpenClaw supports a ā€œCEO + worker agentsā€ style via multi-agent routing and sub-agents.
FAQ: https://docs.openclaw.ai/help/faq

If you want, I can sketch a minimal config shape for:

  • coordinator
  • emotion
  • claude-engineering
  • gemini-docs
river kindle
#

Yes please, sketch the minimal config for:

  • coordinator
  • emotion (MiniMax)
  • claude-engineering (Claude via ACP)
  • gemini-docs (Gemini via ACP)

Running on WSL2, OpenClaw 2026.4.15

solemn ospreyBOT
#

Yep. Here’s a minimal JSON5 sketch for ~/.openclaw/openclaw.json that makes coordinator the main routed agent, with:

  • emotion = native OpenClaw agent on MiniMax
  • claude-engineering = ACP harness agent (claude)
  • gemini-docs = ACP harness agent (gemini)
{
  acp: {
    enabled: true,
    backend: "acpx",
    allowedAgents: ["claude", "gemini"],
  },

  // Optional, but useful if you want worker sessions bound to Discord threads.
  session: {
#
    threadBindings: {
      enabled: true,
      idleHours: 24,
      maxAgeHours: 0,
    },
  },

  channels: {
    discord: {
      threadBindings: {
        enabled: true,
        spawnSubagentSessions: true,
        spawnAcpSessions: true,
      },
    },
#
  },

  agents: {
    list: [
      {
        id: "coordinator",
        default: true,
        workspace: "~/.openclaw/workspace-coordinator",
        subagents: {
          allowAgents: ["emotion", "claude-engineering", "gemini-docs"],
          requireAgentId: true,
        },
      },

      {
#
        id: "emotion",
        workspace: "~/.openclaw/workspace-emotion",

        // If you used MiniMax API-key setup:
        model: "minimax/MiniMax-M2.7",

        // If you used MiniMax OAuth instead, swap to:
        // model: "minimax-portal/MiniMax-M2.7",
      },

      {
        id: "claude-engineering",
        workspace: "~/.openclaw/workspace-claude-engineering",
        runtime: {
          type: "acp",
#
          acp: {
            agent: "claude",
            backend: "acpx",
            mode: "persistent",
            cwd: "~/Projects/your-repo",
          },
        },
      },

      {
        id: "gemini-docs",
        workspace: "~/.openclaw/workspace-gemini-docs",
        runtime: {
          type: "acp",
          acp: {
#
            agent: "gemini",
            backend: "acpx",
            mode: "persistent",
            cwd: "~/Documents/your-docs",
          },
        },
      },
    ],
  },

  bindings: [
    // Route your Discord bot traffic to the coordinator.
    {
      type: "route",
      agentId: "coordinator",
#
      match: { channel: "discord", accountId: "default" },
    },
  ],
}

A couple important notes:

  • This gives you the worker definitions, but the task-type routing logic still lives in the coordinator’s instructions (AGENTS.md in workspace-coordinator).
  • I’d tell the coordinator, explicitly:
    • emotional/support/check-in work → emotion
    • coding/debugging/architecture → claude-engineering
    • doc extraction/summarization/legal-style review → gemini-docs

Tiny coordinator rule sketch:

#
When a task is:
- emotional support, reflection, tone coaching, or check-ins: delegate to agentId "emotion"
- coding, debugging, architecture, or engineering decisions: delegate to agentId "claude-engineering"
- document parsing, long document summarization, structured extraction, or legal-style document review: delegate to agentId "gemini-docs"

Always choose an explicit agentId.
Prefer delegation for specialized work, then summarize the result back to the user.

WSL2 gotcha: for the ACP agents, Claude Code / Gemini CLI auth and installs need to exist inside WSL2, not just on Windows. First thing I’d run after setup is:

  • openclaw agents list --bindings
  • openclaw models status
  • /acp doctor

Docs:

river kindle
#

How to add claude-engineering subagent to existing single-agent setup?
Running OpenClaw 2026.4.15 on WSL2.
Currently have one agent: main (MiniMax, working fine).

I want to add claude-engineering as a subagent via ACP.
Claude Code is installed at /usr/bin/claude.

My current agents config in openclaw.json:
"agents": {
"defaults": { ... }
}

Questions:

  1. Do I replace "defaults" with "list"?
  2. What's the minimal safe config to add one ACP subagent?
  3. Any WSL2-specific gotchas?
solemn ospreyBOT
#

Yep, don’t blow away defaults šŸ˜…

1) Do you replace defaults with list?

No. Keep agents.defaults as your shared/base config, and add agents.list for concrete agents.

For a safe single-agent → multi-agent step, I’d make main explicit in agents.list and add claude-engineering there too.


2) Minimal safe config to add one ACP subagent

Assuming your existing agents.defaults already has your MiniMax setup working:

{
#
  acp: {
    enabled: true,
    backend: "acpx",
    allowedAgents: ["claude"],
  },

  agents: {
    defaults: {
      // keep your existing working defaults block here
    },

    list: [
      {
        id: "main",
        default: true,
#
        workspace: "~/.openclaw/workspace",
        agentDir: "~/.openclaw/agents/main/agent",

        // Let main explicitly spawn this worker.
        subagents: {
          allowAgents: ["claude-engineering"],
          requireAgentId: true,
        },
      },

      {
        id: "claude-engineering",
        workspace: "~/.openclaw/workspace-claude-engineering",
        agentDir: "~/.openclaw/agents/claude-engineering/agent",
        runtime: {
#
          type: "acp",
          acp: {
            agent: "claude",
            backend: "acpx",
            mode: "persistent",
            cwd: "~/Projects/your-repo",
          },
        },
      },
    ],
  }
}

A few key points:

#
  • main keeps inheriting your existing MiniMax/default model from agents.defaults
  • claude-engineering is a separate OpenClaw agent id
  • inside it, runtime.acp.agent: "claude" is the ACP harness alias
  • you do not need a bindings[] entry for claude-engineering if it’s only a spawned worker, not a directly routed chat target

3) WSL2-specific gotchas

The main ones:

  • Claude auth must work inside WSL2, where OpenClaw is running, not just on Windows.
  • Use Linux paths in cwd, not C:\...
  • First ACP use may need network/npm access for adapter/bootstrap
  • Run /acp doctor after restart

Since you already have Claude at /usr/bin/claude, that’s a good sign. If ACP still can’t launch it, the problem is usually ACP/backend wiring or auth, not agents.list.

#

Safe verification flow

After editing config:

openclaw gateway restart
openclaw agents list --bindings
openclaw models status

Then in chat:

/acp doctor
river kindle
#

Before I modify openclaw.json to add multi-agent support,
I have two questions:

  1. Is agentDir required in agents.list entries, or optional?

  2. Here's my planned config change - can you confirm it's safe
    to apply to an existing working single-agent setup?
    {
    "acp": {
    "enabled": true,
    "backend": "acpx",
    "allowedAgents": ["claude"]
    },
    "models": {
    "providers": {
    "ollama": {
    "baseUrl": "http://127.0.0.1:11434",
    "apiKey": "ollama-local",
    "models": [
    {
    "id": "qwen3-vl:4b-instruct",
    "name": "Qwen3 VL 4B",
    "input": ["text", "image"]
    }
    ]
    }
    }
    },
    "meta": {
    "lastTouchedVersion": "2026.4.15",
    "lastTouchedAt": "2026-04-21T15:08:52.086Z"
    },
    "agents": {
    "defaults": {
    "model": {
    "primary": "myclaw/minimax-m2.7"
    },
    "workspace": "/mnt/c/Users/esg05/.openclaw/workspace",
    "imageModel": {
    "primary": "ollama/qwen3-vl:4b-instruct"
    },
    "models": {
    "ollama/qwen3-vl:4b-instruct": {}
    },
    "memorySearch": {
    "provider": "local"
    }
    },
    "list": [
    {
    "id": "main",
    "default": true,
    "workspace": "/mnt/c/Users/esg05/.openclaw/workspace",
    "subagents": {
    "allowAgents": ["claude-engineering"],
    "requireAgentId": true
    }
    },
    {
    "id": "claude-engineering",
    "workspace": "/mnt/c/Users/esg05/.openclaw/workspace-claude-engineering",
    "runtime": {
    "type": "acp",
    "acp": {
    "agent": "claude",
    "backend": "acpx",
    "mode": "persistent"
    }
    }
    }
    ]
    },
    "gateway": {
    "mode": "local",
    "auth": {
    "mode": "token",
    "token": "YOUR_TOKEN_HERE"
    }
    },
    "plugins": {
    "entries": {
    "ollama": {
    "enabled": true
    }
    }
    },
    "wizard": {
    "lastRunAt": "2026-04-21T15:08:51.893Z",
    "lastRunVersion": "2026.4.15",
    "lastRunCommand": "doctor",
    "lastRunMode": "local"
    }
    }

solemn ospreyBOT
#

Yep.

1) agentDir required or optional?

Optional.
If you omit it, OpenClaw uses the per-agent default path under:

~/.openclaw/agents/<agentId>/agent

So your config is fine without agentDir.

The one hard rule is: never reuse the same agentDir across agents.


#

2) Is your planned change safe to apply?

Yes, broadly yes.
For an existing working single-agent setup, this looks like a safe multi-agent extension rather than a destructive rewrite.

Why it looks good:

  • you kept agents.defaults
  • you added agents.list with explicit main + claude-engineering
  • main is still default: true
  • main.subagents.allowAgents explicitly allows only claude-engineering
  • claude-engineering is ACP-backed and has no direct binding, so it won’t suddenly hijack your normal chat routing

A couple notes:

Good as-is

  • agentDir omission is okay
#
  • no bindings[] needed for claude-engineering if it’s only a spawned worker
  • omitting cwd is okay, ACP should inherit the target agent workspace by default

Tweaks I’d consider

  1. If you want maximum migration clarity, you can add explicit agentDir entries, but it is not required.
  2. If Claude should always start in a specific repo, add:
    "cwd": "/path/to/repo"
    
    under runtime.acp.

My short verdict

Yes, safe to apply for the multi-agent part.

#

The only caveat is the usual one: this assumes the rest of your existing config still resolves correctly, especially your already-working myclaw/minimax-m2.7 model path.


WSL2 note

Your /mnt/c/... workspaces will work, but for heavier file/code workflows, WSL usually behaves better on the Linux side (~/...) than on mounted Windows paths. Not required, just a practical heads-up.


After applying

I’d do:

openclaw gateway restart
#
openclaw agents list --bindings
openclaw models status

Then in chat:

/acp doctor

If you want, I can sanity-check the exact final JSON5 after you paste the post-edit version.

river kindle
#

After applying the multi-agent config and restarting the gateway,
how do I verify that ACP is working correctly for claude-engineering?

Specifically:

  1. What does a successful ACP connection look like in the logs?
  2. What does a failed ACP connection look like?
  3. What's the first thing to check if claude-engineering fails to connect?
solemn ospreyBOT
#

Short version: the first thing to check is /acp doctor.

1) What does a successful ACP connection look like?

The docs don’t promise one exact magic log line like ā€œClaude connectedā€. The reliable success signals are:

  • /acp doctor reports backend health/capabilities without blocking issues
  • /acp status shows backend, mode, state, runtime options, capabilities
  • once spawned, /acp status can show runtime/backend session identifiers
  • /acp spawn claude or your claude-engineering spawn is accepted
  • when available, the accepted ACP response can include a streamLogPath you can tail for full relay history

So in practice, ā€œsuccessā€ looks more like:

  • no ACP errors in openclaw logs --follow
  • /acp doctor healthy
  • /acp status shows a live session/state
#

2) What does a failed ACP connection look like?

These are the doc-backed failure signatures to look for:

  • ACP runtime backend is not configured
  • ACP is disabled by policy (acp.enabled=false)
  • ACP dispatch is disabled by policy (acp.dispatch.enabled=false)
  • ACP agent "claude" is not allowed by policy
  • AcpRuntimeError: Permission prompt unavailable in non-interactive mode
  • ā€œACP session fails early with little outputā€

Also on first use:

  • adapter fetch/bootstrap can fail if the host lacks npm/network
  • Claude can fail if Claude-side auth is missing on that WSL host
#

3) First thing to check if claude-engineering fails

First check: /acp doctor

That’s the intended ACP health check.

If it fails, check these in order:

  1. acp.enabled: true
  2. plugins.entries.acpx.enabled / backend available
  3. acp.allowedAgents includes claude
  4. Claude auth works inside WSL2
  5. gateway logs for AcpRuntimeError
    • this often means ACP hit a non-interactive permission prompt
#

That last one is a sneaky/common failure mode. ACP sessions are non-interactive, so permission prompts can kill them early.

Useful commands:

openclaw logs --follow
openclaw gateway status
openclaw doctor

And in chat:

/acp doctor
/acp status
river kindle
#

/acp doctor shows healthy but runtimeDoctorDetail shows agent=codex, not claude.

Is this expected? How do I confirm that claude-engineering
will use Claude (claude code) and not codex?

#

@solemn osprey
/acp doctor shows healthy but runtimeDoctorDetail shows agent=codex, not claude.

Is this expected? How do I confirm that claude-engineering
will use Claude (claude code) and not codex?

solemn ospreyBOT
#

Yes, that’s expected.

/acp doctor is a backend health probe, and the bundled acpx plugin defaults its probe agent to codex. That does not mean your claude-engineering agent will run Codex.

To make /acp doctor probe Claude instead:

openclaw config set plugins.entries.acpx.config.probeAgent claude
openclaw gateway restart

How to confirm claude-engineering will really use Claude:

  1. In config, make sure that agent has:
    runtime: {
    
#
     type: "acp",
     acp: {
       agent: "claude",
       backend: "acpx"
     }
   }
  1. Start/use the claude-engineering ACP session, then run:
    /acp status
    
    on that live session. /acp status is the right check for the actual session/runtime options. /acp doctor is just backend health.

So the mental model is:

#
  • /acp doctor = ā€œis ACP backend healthy?ā€
  • runtime.acp.agent: "claude" + /acp status = ā€œis this specific worker actually Claude?ā€

Docs: https://docs.openclaw.ai/tools/acp-agents

If you want, I can give you a one-minute end-to-end test for claude-engineering so you can verify it with one prompt.

river kindle
#

@solemn osprey
After setting plugins.entries.acpx.config.probeAgent to claude
and restarting gateway, /acp doctor still shows agent=codex.

Is there another config path to change the probe agent?
Or should I just proceed to test the actual claude-engineering
session directly with /acp status?

solemn ospreyBOT
#

I don’t know another documented config path for that. The docs only call out:

openclaw config set plugins.entries.acpx.config.probeAgent claude

So if /acp doctor still shows agent=codex, I’d do two quick checks:

openclaw config get plugins.entries.acpx.config.probeAgent
openclaw gateway status

Why:

  • config get confirms the value actually saved
  • gateway status helps catch ā€œgateway is running from a different config/profile than I thoughtā€
#

If config get says claude but /acp doctor still reports codex, I’d treat that as either:

  • config/profile mismatch, or
  • stale/buggy doctor reporting on 2026.4.15

So yes, I would proceed to test the real claude-engineering session directly. That’s the authoritative check anyway.

Mental model:

  • /acp doctor = backend probe
  • /acp status on the actual worker session = real runtime verification

So I’d not block on doctor here.

If you want the shortest next step, do:

  1. confirm probeAgent with openclaw config get ...
#
  1. test claude-engineering directly with /acp status

If you paste the /acp status output, I can help interpret it.

river kindle
#

@solemn osprey
Getting this error when running /acp status in chat:

ACP error (ACP_SESSION_INIT_FAILED): Session is not ACP-enabled: agent:main:main

The message suggests: "If this session is stale, recreate it with /acp spawn and rebind the thread."

Questions:

  1. How do I use /acp spawn correctly?
  2. Do I need to specify claude-engineering when spawning?
  3. After spawning, how do I verify the session is using Claude?
solemn ospreyBOT
#

Yep, that error just means you’re still in the normal main session, not an ACP one.

/acp status only works after you’ve actually created or bound an ACP session.

1) How to use /acp spawn correctly

For a quick manual test in this same thread, use:

/acp spawn claude --bind here

That tells OpenClaw:

  • start an ACP session
  • use the Claude harness
  • bind this current conversation to it
#

If you want a separate child thread instead, use --thread auto, but for testing, --bind here is the cleanest.


2) Do you need to specify claude-engineering?

For the slash command test, no, you normally specify the harness:

/acp spawn claude --bind here

So think of it like this:

  • claude = ACP harness target
  • claude-engineering = your OpenClaw agent/profile name in config
#

If your goal right now is just, ā€œdoes ACP Claude work?ā€, spawn claude directly.


3) After spawning, how do you verify it’s using Claude?

Right after /acp spawn claude --bind here, run:

/acp status

in the same bound thread/chat.

Before spawn, you got:

#
Session is not ACP-enabled: agent:main:main

After a successful bind, /acp status should report the live ACP session instead of complaining that you’re on agent:main:main.

So the flow is:

  1. /acp spawn claude --bind here
  2. /acp status

Tiny nuance

That tests the ACP Claude runtime directly.

#

If you want to test the full multi-agent path later, that’s slightly different: you’d have main delegate a trivial engineering task to your configured claude-engineering worker.

But for first verification, I’d absolutely do the direct ACP test first.

If you want, I can give you a one-line safe test prompt for Claude that makes it obvious the bind worked.

river kindle
#

@solemn osprey
Claude Code is installed and authenticated in WSL2 (/usr/bin/claude).
I logged in with my Claude Pro account successfully.

But when I try to use ACP from Telegram, I get:
ACP_TURN_FAILED: Authentication required

/acp spawn claude --bind here works in Telegram.
/acp status shows a valid session.
But sending any message through the ACP session still fails with auth error.

Question: How do I connect the Claude Code WSL2 auth to OpenClaw's ACP session?
Is there a specific command to link them?

solemn ospreyBOT
#

There isn’t a special ā€œlink Claude Code auth to ACPā€ command.

ACP Claude uses the Claude Code auth that the harness itself can see on the gateway host.
So if you’re getting:

ACP_TURN_FAILED: Authentication required

that usually means:

  • Claude is installed, and ACP can launch it
  • but the Claude process started by OpenClaw/acpx cannot see a usable Claude login

Short answer

  • No separate link command for ACP
#
  • this is usually an environment/user/auth-visibility issue, not a Telegram issue

First thing I’d check

From the same WSL user/environment that runs the gateway, test Claude non-interactively:

claude -p "say hi"

If that fails with auth, ACP will fail too.

If that works in your shell but ACP still says Authentication required, the likely problem is that the gateway/acpx process is running with a different environment, HOME, or auth-file visibility than your interactive shell.

Important distinction

This command is for OpenClaw’s Anthropic provider auth:

#
openclaw models auth login --provider anthropic --method cli --set-default

That is separate from Claude Code ACP harness auth.
Useful sometimes, but it is not the special fix for ACP Claude.

Practical checks

  1. claude -p "say hi" works in WSL
  2. gateway is running as the same user
  3. restart gateway after Claude login
  4. tail logs while sending a Telegram ACP message:
    openclaw logs --follow
    
river kindle
#

@solemn osprey
claude -p "say hi" works fine in WSL2.
But ACP still fails with ACP_TURN_FAILED: Authentication required.

Restarted gateway after Claude login, still same error.

DC mentioned: "the gateway/acpx process is running with a different
environment, HOME, or auth-file visibility than your interactive shell"

How do I check if the gateway is running with a different environment?
And how do I fix the HOME/auth-file visibility issue?

solemn ospreyBOT
#

That’s a frustrating one, but your claude -p result is actually useful, it means Claude itself is fine and the mismatch is probably the gateway/service environment.

How to check if the gateway is running with a different environment

Start with these:

openclaw gateway status
openclaw config get env.shellEnv.enabled
openclaw models status

What you’re looking for:

  • if the gateway is running as a background service on WSL2, it may not inherit your shell env
  • openclaw models status will tell you whether shell env import is on or off
  • if shell env is off, your interactive claude login environment and the gateway environment can diverge
#

How to fix the environment side

Docs-backed fixes:

  1. Enable shell env import

    openclaw config set env.shellEnv.enabled true
    openclaw gateway restart
    
  2. If any Claude-related setup depends on env vars, put them in:

    ~/.openclaw/.env
    

That said, for Claude Code auth, the bigger issue is often not PATH, it’s same user / same HOME.

#

The HOME / auth-file visibility issue

If claude -p works in your shell but ACP says Authentication required, the likely problem is:

  • you logged into Claude as your WSL user
  • but OpenClaw/acpx is running under a different user/home/service context
  • so the Claude process launched by ACP cannot see the same Claude auth files

Practical fix

Make sure the gateway runs as the same WSL user that successfully ran:

claude -p "say hi"

That’s the real requirement.

#

So the order I’d use is:

  1. confirm gateway is service-based with openclaw gateway status
  2. enable env.shellEnv.enabled
  3. restart gateway
  4. retry ACP
  5. if still broken, assume user/HOME mismatch and make sure the gateway service is running as the same WSL user who did the Claude login

Important nuance

  • ~/.openclaw/.env helps with env vars
  • it does not magically bridge Claude auth files if the gateway is running under the wrong user/home

So for your case, the most likely fix is same WSL user + restart, not a special ACP command.

Docs:

#

If you want, paste the output of:

openclaw gateway status
openclaw config get env.shellEnv.enabled
openclaw models status

and I’ll help narrow down whether this is env drift or a true auth-visibility bug.

river kindle
#

@solemn osprey
claude -p "say hi" works fine in WSL2 as the same user running the gateway.
env.shellEnv.enabled is set to true.
Gateway restarted after all changes.

But /acp spawn claude --bind here in Telegram still fails with:
ACP_TURN_FAILED: Authentication required

What else could cause Claude Code auth to be invisible to the ACP runtime,
even when claude -p works in the same user's shell?

solemn ospreyBOT
#

If all of these are true:

  • claude -p "say hi" works
  • same WSL user as the gateway
  • env.shellEnv.enabled: true
  • gateway restarted

then I’d stop blaming basic env drift. At that point the most likely causes are:

1) A stale bound ACP session

Telegram may still be hitting an older/bad ACP session state.

Try a hard reset of that bound ACP session:

/acp close
#
/acp spawn claude --bind here

I’d do that before changing more config.

2) ACP is launching a different Claude binary/path than the one you tested

claude -p proving /usr/bin/claude works does not guarantee the acpx claude harness alias is resolving to the same thing.

So the next useful check is:

openclaw logs --follow

Then trigger the Telegram /acp spawn claude --bind here again and look for clues about:

#
  • which command/path is being launched
  • whether a different Claude install/shim is being used
  • whether the adapter is returning the auth error directly

3) Claude CLI auth works for -p, but the ACP adapter path is still failing

This is the annoying one, but it’s real.

claude -p and ā€œClaude running under ACP via acpxā€ are close, but not identical execution paths. If the normal CLI works and ACP still throws:

ACP_TURN_FAILED: Authentication required

then this starts to smell like:

  • a Claude ACP adapter issue
  • a WSL2-specific quirk
#
  • or a stale/runtime-side auth lookup bug

What I would not chase yet

I would not change permission settings unless logs show:

AcpRuntimeError: Permission prompt unavailable in non-interactive mode

That’s a different failure mode than plain auth failure.


My recommended next step

Do these in order:

#
  1. /acp close
  2. /acp spawn claude --bind here
  3. if it still fails, run:
    openclaw logs --follow
    
    and capture the ACP-related lines from the failed Telegram spawn

If the logs still just show Claude-side auth failure even after a fresh /acp close, I’d treat it as likely acpx/Claude-on-WSL2 bug territory rather than user misconfig.

If you paste the ACP log snippet, I can help read it. If this fixed it, please right-click the solution message → Apps → āœ… Mark Solution so Answer Overflow can index it. šŸŽ‰

river kindle
#

Gateway logs show no ACP-related entries when /acp spawn is called.
Also seeing repeated: Unknown model: myclaw/minimax-m2.7

Could the myclaw model connection failure be causing ACP to fail?
How do I check if myclaw is properly connected?

solemn ospreyBOT
#

Probably not the direct cause of the Claude ACP auth failure, but yes, it’s a real problem and worth fixing first.

ACP_TURN_FAILED: Authentication required is a Claude/ACP-side failure.
Unknown model: myclaw/minimax-m2.7 is a normal model resolution failure.

So I’d treat them as two separate issues, with one caveat: if your main route is broken, it can definitely make the whole setup harder to reason about.

The big clue

myclaw/minimax-m2.7 is not a standard built-in MiniMax model ref in the docs.

Built-in MiniMax refs are:

  • minimax/MiniMax-M2.7 for API-key setup
  • minimax-portal/MiniMax-M2.7 for OAuth setup

So unless you intentionally created a custom provider named myclaw, that model id looks wrong.

#

How to check whether myclaw is actually connected

Run:

openclaw models status
openclaw models status --probe
openclaw models list

What to look for:

  • whether myclaw appears as a real provider/model source
  • whether MiniMax auth is present
  • whether the model resolves at all

If myclaw does not show up there, then OpenClaw does not know that provider.

#

What the docs say about ā€œUnknown model: minimax/MiniMax-M2.7ā€

That error means the provider isn’t configured, so the model can’t be resolved.

For MiniMax, the docs’ fix path is:

  1. make sure MiniMax auth/config exists
  2. use the exact model id for the auth path
  3. verify with openclaw models list

Docs:

My recommendation

#

If you intended the built-in MiniMax provider, change the model ref away from:

myclaw/minimax-m2.7

to one of these exact refs:

minimax/MiniMax-M2.7

or

minimax-portal/MiniMax-M2.7
#

depending on whether you’re using API key or OAuth.

If myclaw is intentional, then the next question is: where is that custom provider defined?
If it’s missing from models.providers, that explains the error.

If you paste the output of:

openclaw models status --probe
openclaw models list

I can tell pretty quickly whether myclaw is real or just a bad model ref.

mellow gust
#

Hi Benson you figure it out I'm in the same situation, triyng to use openclaw as main and codex as sub agent in persistent conf

solemn ospreyBOT
#

Benson hasn’t fully nailed the Claude auth bit yet, but the multi-agent pattern itself is supported.

For OpenClaw main + Codex subagent, the clean setup is:

  • main = your normal/default agent
  • codex-worker = ACP-backed worker
  • no binding for codex-worker if it should only run as a spawned subagent
  • let main delegate explicitly to it

Minimal shape:

{
  agents: {
    defaults: {
      // your normal main model setup here
#
    },
    list: [
      {
        id: "main",
        default: true,
        subagents: {
          allowAgents: ["codex-worker"],
          requireAgentId: true
        }
      },
      {
        id: "codex-worker",
        runtime: {
          type: "acp",
          acp: {
#
            agent: "codex",
            backend: "acpx",
            mode: "persistent"
          }
        }
      }
    ]
  }
}

Then delegation is explicit, for example via subagent spawning, instead of binding Codex directly to the chat.

A couple of important bits:

  • don’t reuse the same agentDir across agents
river kindle
#

@solemn osprey My Telegram session is stuck in an ACP session that keeps returning:
ACP_TURN_FAILED: Authentication required

I've tried /acp close, /acp cancel - both don't work.
Gateway has been restarted multiple times.

How do I force-clear a stuck ACP session from the server side?
Is there a way to delete the session from the session store?

solemn ospreyBOT
#

Yeah, there is server-side session state, and at this point I’d treat it as a stuck session-store/binding problem, not just a Claude auth problem.

Short answer

  • Normal path: /acp close
  • If that fails: there is not a documented ā€œforce purge this one ACP sessionā€ slash command
  • Last-resort reset: clear the agent’s sessions store on disk, then restart the gateway

Important first check

If you created a persistent config binding like:

bindings: [{ type: "acp", ... }]

for that Telegram chat/topic, clearing the session store alone won’t help much, because OpenClaw will just rebind on the next message.

#

So first make sure this stuck ACP session came from:

/acp spawn ... --bind here

and not a permanent bindings[] rule.

Where the server-side session state lives

Docs say the per-agent session store is here:

~/.openclaw/agents/<agentId>/sessions/sessions.json
~/.openclaw/agents/<agentId>/sessions/*.jsonl
#

Usually in your case that’s probably:

~/.openclaw/agents/main/sessions/

How I’d force-clear it

First inspect what stores exist:

openclaw sessions --all-agents --json

Then, as a recoverable reset, move the stuck agent’s sessions folder aside and restart:

#
mv ~/.openclaw/agents/main/sessions ~/.openclaw/agents/main/sessions.bak.$(date +%s)
openclaw gateway restart

That is safer than editing sessions.json by hand.

Why this works

Docs explicitly note that if you want to reset sessions, clearing:

agents/<agentId>/sessions/

resets session history/state, while keeping auth if you leave:

#
agents/<agentId>/agent/auth-profiles.json
credentials/

alone.

What I would not do

I would not manually edit sessions.json unless you really know the store format. Easy to make it worse.

Also useful

openclaw sessions cleanup is maintenance, but it is not really the ā€œdelete this stuck bound ACP session nowā€ tool.

Docs:

river kindle
#

@solemn osprey After moving sessions folder aside and restarting gateway,
Telegram still shows ACP_TURN_FAILED: Authentication required

I only used /acp spawn --bind here, no permanent bindings[] in config.

Is the ACP binding stored somewhere else besides the sessions folder?
How do I completely remove the ACP binding from this Telegram chat?

solemn ospreyBOT
#

Yes, that’s the missing piece.

/acp spawn --bind here does not only live in the agent sessions folder.
The docs say generic current-conversation binds use the shared OpenClaw binding store and survive restarts, and in current source that store is:

<stateDir>/bindings/current-conversations.json

With the default state dir, that’s usually:

~/.openclaw/bindings/current-conversations.json

So moving only:

#
~/.openclaw/agents/<agentId>/sessions/

would not remove the Telegram conversation bind.

How to completely remove the bind

If you want the blunt, recoverable reset, move that bindings file aside and restart:

mv ~/.openclaw/bindings/current-conversations.json ~/.openclaw/bindings/current-conversations.json.bak.$(date +%s)
openclaw gateway restart

If you have lots of other active conversation binds and want to preserve them, you can instead back up the file and remove just the Telegram entry from it.

#

One more in-chat option

There’s also a general binding command:

/unfocus

That is meant to remove the current binding. If Telegram conversation binding features are active, it’s worth trying, but since /acp close already failed, I’d trust the server-side file reset more.

Why this matches your symptoms

  • no permanent bindings[]
  • moving agents/.../sessions/ didn’t help
  • restart didn’t help
  • same Telegram chat still routes straight back into ACP
#

That is exactly what I’d expect from a surviving entry in:

~/.openclaw/bindings/current-conversations.json

If clearing that file still doesn’t detach the chat, then I’d start suspecting either:

  1. a second non-default state dir/profile, or
  2. Telegram thread/topic-specific binding state using a different conversation id than expected.

If you want, I can help you sanity-check the exact file/path next.

river kindle
#

@solemn osprey current-conversations.json doesn't exist at ~/.openclaw/bindings/
Gateway restarted, sessions folder moved aside.
Telegram still shows ACP_TURN_FAILED: Authentication required on every message.

Where else could the ACP binding be stored?
Is there a way to list all active ACP bindings?

solemn ospreyBOT
#

If ~/.openclaw/bindings/current-conversations.json does not exist, then a surviving generic --bind here record is a lot less likely.

At that point I’d check a different possibility:

Most likely remaining cause

Your Telegram chat may be routing to an agent that is itself ACP-backed, so every message goes into ACP even without a current-conversation bind file.

That can happen through:

  1. top-level bindings[]
  2. a normal route binding to an agent whose runtime.type is "acp"
  3. Telegram topic/chat config with agentId pointing at an ACP agent
  4. the default agent itself being ACP-backed

Best ways to inspect it

#

1) List configured routing bindings

openclaw agents list --bindings
openclaw agents bindings

2) Inspect ACP sessions

/acp sessions

3) Inspect the relevant config

Look for:

  • top-level bindings[]
  • agents.list[].runtime.type
  • agents.list[].runtime.acp
#
  • Telegram topic overrides like:
    channels.telegram.groups.<chatId>.topics.<threadId>.agentId
    

If you’re comfortable with CLI config reads:

openclaw config get bindings
openclaw config get agents.list

Is there a command to list all active ACP bindings?

Not a clean documented global one that I could find.

Closest things are:

#
  • openclaw agents bindings → configured routing rules
  • /acp sessions → existing ACP sessions
  • /agents → current-session thread binding state, not a global ACP binding dump

So if the bind-store file is absent, I’d stop chasing hidden bind files and start checking whether Telegram is simply routed to an ACP agent by config.

If you paste the output of:

openclaw agents list --bindings
openclaw config get bindings
openclaw config get agents.list

I can usually spot the culprit pretty fast.

river kindle
#

@solemn osprey
agents list --bindings shows only main agent, no ACP routing rules.
config get bindings → not found
config get agents.list → not found

But Telegram still shows ACP_TURN_FAILED on every message.

Could the ACP binding be stored on the Telegram bot side?
Is there a way to check what session the Telegram chat is bound to?
Or is this a cached state in the Telegram client itself?

#

@solemn osprey
agents list --bindings shows only main agent, no ACP routing rules.
config get bindings → not found
config get agents.list → not found

But Telegram still shows ACP_TURN_FAILED on every message.

Could the ACP binding be stored on the Telegram bot side?
Is there a way to check what session the Telegram chat is bound to?
Or is this a cached state in the Telegram client itself?

solemn ospreyBOT
#

No, I would not blame the Telegram bot side or the Telegram client cache.

Telegram is basically just the transport here. The session/binding state lives on the OpenClaw gateway side.

Given everything you’ve checked, the strongest remaining explanation is:

You are inspecting the wrong gateway/profile/state dir

This fits really well with your symptoms:

  • Telegram still replies
  • but your local logs, bindings, sessions, and config get don’t line up
  • no ACP entries where you expect them
  • no current-conversations.json
  • no visible ACP bindings in the config you’re reading

That usually means the Telegram bot is talking to a different OpenClaw service/profile/state dir than the one your CLI is inspecting.

#

What to check next

openclaw gateway status --deep
openclaw status
openclaw channels status
openclaw sessions --all-agents --json

What I’d look for

  • Config (cli) vs Config (service) mismatch
  • different profile / state dir
  • ā€œother gateway-like services detectedā€
  • whether this instance even shows the Telegram channel/account you expect
  • whether this instance has any agent:main:telegram:... session keys
#

Docs-backed clue

The FAQ explicitly calls out:

if Config (cli) and Config (service) differ, you’re editing one config while the service is running another, often a --profile / OPENCLAW_STATE_DIR mismatch.

If that’s what you see, the docs fix is:

openclaw gateway install --force

Run that from the same profile/environment you actually want the Telegram service to use.

Can you check what session the Telegram chat is bound to?

Yes, indirectly, by looking for Telegram session keys in:

#
openclaw sessions --all-agents --json

You’re looking for entries like:

agent:<agentId>:telegram:direct:<chatId>
agent:<agentId>:telegram:group:<chatId>
agent:<agentId>:telegram:group:<chatId>:topic:<threadId>

If this CLI instance shows none of the Telegram sessions you know are active, that’s basically confirmation you’re looking at the wrong gateway/profile.

So, short version:

  • not Telegram client cache
#
  • not likely Telegram bot-side storage
  • most likely wrong OpenClaw service/profile/state dir

If you paste the output of openclaw gateway status --deep, I can help read it.

river kindle
#

@solemn osprey openclaw sessions --all-agents --json shows count: 0, sessions: []
Config (cli) and Config (service) are the same file.
No bindings, no agents.list, no ACP routing rules.

But Telegram still returns ACP_TURN_FAILED on every message.

Could this be a stuck state in the OpenClaw Telegram plugin/channel itself?
Is there a way to reset the Telegram channel state?

solemn ospreyBOT
#

At this point, I really don’t think this is Telegram client cache, and I also don’t think ā€œresetting Telegram channel stateā€ is the main fix.

Why:

  • openclaw sessions --all-agents --json shows 0 sessions
  • no bindings
  • no ACP routing config
  • same config file for CLI and service

If this gateway were actually handling those Telegram messages, I’d expect to see some Telegram session activity.

What this points to instead

The most likely explanation now is:

another process / another OpenClaw instance is the one actually connected to that Telegram bot token, and that instance is returning the stale ACP error.

#

On WSL2, I’d be especially suspicious of:

  • another OpenClaw running on the Windows host
  • another WSL distro
  • an old service/profile using the same Telegram bot token

Best check now

Run:

openclaw channels status
openclaw channels logs --channel telegram

Then send a fresh Telegram message.

#

What to look for

  • If no Telegram log activity appears on this instance when you message the bot, this is not the gateway answering you
  • that would make the ACP error come from some other process using the same bot token

So, is it stuck Telegram plugin state?

I’d say very unlikely.

The Telegram plugin does transport and channel handling. It does not magically cache ACP routing forever with:

  • no sessions
  • no bindings
  • no visible ACP state

That combination screams wrong process / duplicate bot consumer, not channel cache.

#

If you want a decisive test

The cleanest proof is to temporarily use a fresh Telegram bot token on this known instance.

  • if the fresh bot behaves normally, the old bot token is still being consumed somewhere else
  • if the fresh bot shows the same weird behavior, then we’d revisit plugin/channel state

So my recommendation is:

  1. openclaw channels status
  2. openclaw channels logs --channel telegram
  3. send a Telegram message
  4. if nothing shows up, hunt for the other process using that bot token

If you paste openclaw channels status, I can help interpret it.

river kindle
#

@solemn osprey Windows-side OpenClaw gateway restarted.
Sessions folder renamed/cleared.
But Telegram still shows ACP_TURN_FAILED: Authentication required.

The sessions.json showed:

  • "status": "running"
  • "providerOverride": "google-gemini-cli"
  • "fallbackNoticeReason": "auth"

Is there another place where a stuck ACP session can persist
besides the sessions folder?
Could the bindings folder on Windows side have something?

Windows config: C:\Users\esg05.openclaw\openclaw.json

solemn ospreyBOT
#

Yep, the Windows-side bindings folder is exactly what I’d check next.

The current-conversation bind store path from source is:

C:\Users\esg05\.openclaw\bindings\current-conversations.json

So on Windows, the two main persistence places to check are:

  1. session store

    C:\Users\esg05\.openclaw\agents\<agentId>\sessions\
    
  2. shared current-conversation binding store

#
   C:\Users\esg05\.openclaw\bindings\current-conversations.json

What your sessions.json clue means

These fields:

  • status: "running"
  • providerOverride: "google-gemini-cli"
  • fallbackNoticeReason: "auth"

strongly suggest you were finally looking at the live gateway-side state, not Telegram cache.

So no, this really does not look like Telegram client-side memory. It still looks like OpenClaw-side persisted state.

What I’d do next

#

If that file exists on Windows:

C:\Users\esg05\.openclaw\bindings\current-conversations.json

back it up / move it aside, then restart the Windows gateway.

If it does not exist, then the remaining suspects are:

  • another Windows/OpenClaw profile (.openclaw-*)
  • another agent store / state dir
  • another gateway instance still using the same Telegram token

Important boundary

At this point, I would not look for a special Telegram-side ACP cache.

#

The evidence is pointing at OpenClaw state on the Windows host.

So yes, bindings folder on Windows side absolutely could be it.

If you want, paste whether this file exists:

C:\Users\esg05\.openclaw\bindings\current-conversations.json

and I can help you narrow the next step fast.

river kindle
#

@solemn osprey Windows-side:

  • Sessions folder cleared/renamed āœ“
  • bindings folder does not exist āœ“
  • Gateway restarted āœ“
  • Telegram still returns ACP_TURN_FAILED

sessions.json showed providerOverride: google-gemini-cli
Could there be another openclaw profile or state dir on Windows?

What other locations should I check?
ls C:\Users\esg05 | grep openclaw

solemn ospreyBOT
#

Yep, I’d absolutely check for another Windows profile/state dir now.

Docs-backed places to look:

1) Default + profile state dirs under your Windows home

OpenClaw uses:

  • default:
    C:\Users\esg05\.openclaw
  • named profiles:
    C:\Users\esg05\.openclaw-<profile>

So on Windows, I’d list all .openclaw* dirs.

PowerShell

#
Get-ChildItem -Force $env:USERPROFILE | Where-Object Name -like ".openclaw*"

If you’re in Git Bash instead:

ls -la /c/Users/esg05 | grep openclaw

2) Environment overrides

Check whether the Windows-side gateway is using:

  • OPENCLAW_STATE_DIR
  • OPENCLAW_PROFILE
#

PowerShell

Get-ChildItem Env:OPENCLAW*

3) Extra Windows gateway tasks/services

On Windows, extra profiles/gateways usually show up as separate scheduled tasks.

schtasks /Query /FO LIST /V | findstr /I "OpenClaw Gateway"

That can reveal another task/profile you’re not resetting.

4) Legacy paths inside the state dir

#

Docs also mention old migrated single-agent paths. So inside the active state dir, also check for:

  • C:\Users\esg05\.openclaw\agent\
  • C:\Users\esg05\.openclaw\sessions\

Those are legacy, but if something old survived there, I’d want eyes on it.

Why I think this matters

That providerOverride: google-gemini-cli clue still feels like live gateway state from somewhere, not Telegram caching.

So the most likely remaining explanation is still:

  • another .openclaw-* profile dir, or
  • OPENCLAW_STATE_DIR override, or
  • another Windows Scheduled Task using the same Telegram bot token
#

If you paste the output of:

Get-ChildItem -Force $env:USERPROFILE | Where-Object Name -like ".openclaw*"
Get-ChildItem Env:OPENCLAW*
schtasks /Query /FO LIST /V | findstr /I "OpenClaw Gateway"

I can help narrow it down fast.

river kindle
#

@solemn osprey
Summary of what we found and tried today:

  • Two OpenClaw instances: Windows (C:\Users\esg05.openclaw) and WSL2
  • Telegram was connected to Windows-side
  • sessions.json showed stuck ACP session with providerOverride: google-gemini-cli
  • Cleared sessions folder, no bindings folder exists
  • Restarted Windows Gateway
  • New Gateway log shows: agent model: ollama/qwen3-vl:4b-instruct
  • But Telegram channel NOT showing in new Gateway log
  • Telegram still returns ACP_TURN_FAILED on every message
  • No scheduled tasks, no other .openclaw profiles, only one node process

Question: Where is the process that's still answering Telegram messages?

solemn ospreyBOT
#

If there’s truly no other local process, then the thing still answering Telegram is almost certainly not on that Windows box.

At this point I’d narrow it to two real possibilities:

  1. another machine/container is using the same Telegram bot token
  2. Telegram is in webhook mode, and updates are being delivered to some remote webhook URL

OpenClaw’s Telegram docs say:

  • long polling is the default
  • webhook mode is optional

So if silent local logs + live Telegram replies continue, webhook/external-consumer is the next thing I’d suspect.

What to check next

1) Check whether this Telegram setup is polling or webhook

#
openclaw channels status

If Telegram shows webhook mode, that’s your answer immediately.

2) Check config for webhook mode

Look for:

channels.telegram.webhookUrl
channels.telegram.webhookSecret
channels.telegram.webhookPath

If webhookUrl is set, Telegram may be sending updates somewhere else entirely.

#

3) Verify Telegram’s live webhook target

If you want the direct Telegram-side truth, inspect the bot’s webhook info.

That tells you whether Telegram is currently pointing at a webhook URL, which would explain why no local OpenClaw logs are seeing the traffic.

So, where is the responder likely running?

Given your summary, my best guess is:

  • a remote webhook endpoint, or
  • another host using the same bot token

not Telegram client cache, and not some magical hidden ACP store inside the Telegram plugin.

Short version

If:

#
  • sessions are gone
  • bindings are gone
  • no extra profiles
  • one node process
  • no Telegram activity in the new gateway logs

then the process answering Telegram is almost certainly outside the instance you’re inspecting.

If you paste openclaw channels status and whether channels.telegram.webhookUrl is set, I can tell you which branch you’re in pretty quickly.

river kindle
#

@solemn osprey
Telegram config is not found in any .json file under C:\Users\esg05.openclaw
Only reference is in sessions.bak (old cleared session).

The Telegram channel was originally set up through the OpenClaw dashboard UI.
Where does OpenClaw store Telegram bot token when configured via dashboard?
Is it stored in a database file, or somewhere outside the .openclaw folder?

#

@solemn osprey
Telegram config is not found in any .json file under C:\Users\esg05.openclaw
Only reference is in sessions.bak (old cleared session).

The Telegram channel was originally set up through the OpenClaw dashboard UI.
Where does OpenClaw store Telegram bot token when configured via dashboard?
Is it stored in a database file, or somewhere outside the .openclaw folder?

solemn ospreyBOT
#

I would not expect a separate hidden database for the Telegram bot token.

Docs point to these normal places instead:

Most likely locations

  1. $OPENCLAW_STATE_DIR/openclaw.json
    Most typical. The wizard/dashboard path usually writes:
channels.telegram.botToken
  1. $OPENCLAW_STATE_DIR/openclaw.json with a SecretRef or file ref
    So you might see not the raw token, but one of these instead:
  • channels.telegram.botToken as a SecretRef object
#
  • channels.telegram.tokenFile pointing to another file
  • channels.telegram.accounts.<id>.botToken for multi-account config
  1. $OPENCLAW_STATE_DIR/secrets.json
    Only if SecretRef file-backed storage was used.

  2. Environment variable
    For default account Telegram can come from:

TELEGRAM_BOT_TOKEN

In that case, OpenClaw may not store the token on disk at all.

What I do not think

#

I do not think there’s some special Telegram-only DB outside .openclaw by default.

The docs keep pointing back to:

  • openclaw.json
  • secrets.json
  • env vars
  • tokenFile

Best next check

This command should tell you where OpenClaw thinks the Telegram token is coming from:

openclaw channels status --probe --json
#

Look for fields like:

  • botTokenSource
  • botTokenStatus

That’s the cleanest way to distinguish:

  • config
  • env
  • token file
  • unresolved SecretRef

So for your case, I’d check in this order

  • C:\Users\esg05\.openclaw\openclaw.json
  • C:\Users\esg05\.openclaw\secrets.json
  • any tokenFile path referenced from config
#
  • Windows env vars, especially TELEGRAM_BOT_TOKEN

If you want, paste the Telegram section from openclaw channels status --probe --json and I’ll help interpret it.

#

Short version: no, I would not expect a hidden Telegram database outside .openclaw.

When configured through the dashboard/setup flow, the Telegram bot token should normally end up in one of these places:

  • C:\Users\esg05\.openclaw\openclaw.json

    • channels.telegram.botToken
    • or channels.telegram.accounts.<id>.botToken
    • or a SecretRef instead of plaintext
    • or channels.telegram.tokenFile
  • C:\Users\esg05\.openclaw\secrets.json

    • only if file-backed SecretRef storage was used
  • Windows env var:

    • TELEGRAM_BOT_TOKEN

So the likely cases are:

#
  1. stored in openclaw.json
  2. stored indirectly via SecretRef
  3. stored in a separate token file referenced by tokenFile
  4. not stored on disk at all, because it’s coming from TELEGRAM_BOT_TOKEN

I do not think there’s a normal ā€œdashboard databaseā€ that hides the Telegram token somewhere else by default.

Best way to prove where it’s coming from

Run:

openclaw channels status --probe --json

Then check the Telegram section for:

#
  • botTokenSource
  • botTokenStatus

That should tell you whether the live gateway sees the token from:

  • config
  • env
  • token file
  • SecretRef

If you paste just that Telegram block, I can help read it.

river kindle
#

@solemn osprey
openclaw channels status --probe --json shows "channels": {}
No Telegram channel configured in current Windows Gateway.

But Telegram messages were being received and answered before.
The original setup was done through OpenClaw dashboard UI.

Is it possible the Telegram bot token and channel config was stored
in the OpenClaw dashboard/cloud, not locally?
Or could it be stored in a different agent dir?

Also: where exactly does the dashboard write Telegram config when
you set it up through the UI?

solemn ospreyBOT
#

No, I do not think the Telegram bot token was stored in some OpenClaw cloud/dashboard backend.

What the docs point to is:

  • channel config lives in the gateway state dir
  • typically in $OPENCLAW_STATE_DIR/openclaw.json
  • secrets may be indirect via secrets.json, tokenFile, or env
  • per-agent dirs are for agent auth/sessions, not top-level Telegram channel config

So:

Where the dashboard writes it

When you set Telegram up through the UI, the write target should still be the local gateway config surface, typically:

#
$OPENCLAW_STATE_DIR/openclaw.json

with fields like:

channels.telegram.botToken
channels.telegram.accounts.<id>.botToken
channels.telegram.tokenFile

If SecretRef/file-backed secrets were used, then the secret payload may be in:

$OPENCLAW_STATE_DIR/secrets.json
#

What it should not be

It should not normally be:

  • stored in an agent dir
  • stored only in sessions.json
  • stored in some remote OpenClaw cloud account

What channels: {} means

That’s the big clue.

If openclaw channels status --probe --json returns:

{ "channels": {} }
#

then the currently running Windows gateway has no Telegram channel configured at all.

So the practical conclusion is:

you are still not looking at the gateway instance that used to answer Telegram

Either:

  1. the dashboard was connected to a different gateway/state dir when Telegram was configured, or
  2. another machine/process still has that Telegram bot token and is the real responder

Important distinction

  • agent dir = agent auth + sessions
  • state dir / openclaw.json = channel config like Telegram

So I would stop looking in agent dirs for Telegram config.

#

My honest best guess now

If the UI definitely showed Telegram before, then that UI session was probably connected to a different gateway than the one you’re probing now.

That fits all your evidence way better than ā€œhidden DBā€ does.

If you want, I can help you make a very short checklist to prove which gateway the dashboard was actually connected to.

river kindle
#

@solemn osprey
I'm using MyClaw (myclaw.ai) as my main agent platform (cloud-based).
I also have OpenClaw running on WSL2 locally.

Can MyClaw agents communicate with WSL2 OpenClaw via ACP?
Or are these two completely separate systems that can't be bridged?

quiet parrotBOT