#what's wrong

1 messages · Page 1 of 1 (latest)

somber parcelBOT
#

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

zealous iglooBOT
#

Can you paste the full openclaw.json (redact API keys/tokens) and the exact error/output you’re seeing? Right now I only see “openclaw.json …” with no details.

To debug fast, please include:

  1. openclaw --version
  2. What command you ran (e.g. openclaw gateway start, openclaw status, etc.)
  3. The error text (copy/paste)
  4. A short log snippet around the failure:
    • openclaw gateway logs --tail 200 (or whatever you used to view logs)

If it’s a config issue, also tell me:

  • OS (macOS/Linux/Windows) + how you installed (npm global / from source)
  • Whether this is running as a service (launchd/systemd) or in a terminal
#

Two things in your JSON jump out as schema-wrong (will either be ignored or can hard-fail validation):

  1. channels.telegram.groupPolicy doesn’t exist in current OpenClaw config.
    Telegram group allow/deny is controlled by channels.telegram.groups (a map). If you set groups, it also acts as an allowlist (put "*" to allow all groups).

  2. plugins.entries.telegram isn’t needed (Telegram is a built-in channel transport, not a plugin). Safer: remove the whole plugins section unless you’re actually loading an extension plugin.

Also: your Ollama model entry is missing some fields that the schema/examples expect (reasoning, input, cost). Add them, or use Ollama auto-discovery (easier).

Here’s a “clean / schema-aligned” version of what you’re trying to do (JSON5 is OK; plain JSON also works):

{
  meta: {
    lastTouchedVersion: "2026.2.6-3",
    lastTouchedAt: "2026-02-09T17:30:00Z",
#
  },

  wizard: {
    lastRunAt: "2026-02-09T16:49:49.099Z",
    lastRunVersion: "2026.2.6-3",
    lastRunCommand: "doctor",
    lastRunMode: "local",
  },

  gateway: {
    mode: "local",
    auth: {
      mode: "token",
      token: "YOUR_GATEWAY_TOKEN",
    },
#
  },

  models: {
    // optional but usually what you want when adding providers
    mode: "merge",
    providers: {
      ollama: {
        baseUrl: "http://127.0.0.1:11434/v1",
        apiKey: "ollama-local",
        api: "openai-completions",
        models: [
          {
            id: "qwen2.5:3b-instruct",
            name: "Qwen2.5 3B Instruct Local",
            reasoning: false,
#
            input: ["text"],
            cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
            contextWindow: 32768,
            maxTokens: 8192,
          },
        ],
      },
    },
  },

  agents: {
    defaults: {
      workspace: "~/.openclaw/workspace",
      model: {
        primary: "ollama/qwen2.5:3b-instruct",
#
      },
    },
  },

  channels: {
    telegram: {
      enabled: true,
      botToken: "YOUR_TELEGRAM_BOT_TOKEN",

      dmPolicy: "pairing", // pairing | allowlist | open | disabled
      // allowFrom is optional in pairing mode.
      // If you only want *you* to DM it, switch to:
      // dmPolicy: "allowlist",
      // allowFrom: ["tg:123456789"],
#

If you paste the actual error message you get when starting the gateway (or openclaw doctor output), I can tell you exactly which key is failing.

#

That error means your config has a bad value for gateway.bind.

gateway.bind is not an IP address and not "localhost" — it must be one of these strings:

  • "loopback" (127.0.0.1, local-only)
  • "lan" (0.0.0.0, reachable on your LAN)
  • "tailnet" (bind to Tailscale IP only)
  • "auto"

So fix it by either:

Option A (recommended): delete gateway.bind

If you remove it, it defaults to loopback.

Option B: set it to a valid value

Example:

#

One more important thing: your error path is /root/.openclaw/openclaw.json → you’re running as root. Make sure you always run OpenClaw as the same user, otherwise you’ll end up editing the wrong config (root vs your normal user).

#

Here’s a copy/paste openclaw.json that matches what you asked for:

  • Ollama primary (your qwen2.5:3b-instruct)
  • Moonshot (Kimi) fallback (moonshot/kimi-k2.5)
  • Telegram enabled
  • Fixes your recurring config error by using a valid gateway.bind value

Replace the PUT_..._HERE placeholders.

{
  // Optional, just nice metadata
  meta: {
    lastTouchedVersion: "2026.2.6-3",
    lastTouchedAt: "2026-02-09T17:30:00Z",
  },
#

  // Gateway must be local to actually run the server
  gateway: {
    mode: "local",
    port: 18789,

    // IMPORTANT: bind must be one of: "loopback" | "lan" | "tailnet" | "auto"
    // Use "loopback" for most setups (works fine for Telegram).
    bind: "loopback",

    auth: {
      mode: "token",
      token: "PUT_A_GATEWAY_TOKEN_HERE",
    },
  },
#

  // Put keys here (or set them as real env vars on the machine)
  env: {
    OLLAMA_API_KEY: "ollama-local",          // any value works for local ollama
    MOONSHOT_API_KEY: "PUT_MOONSHOT_KEY_HERE"
  },

  logging: {
    level: "info",
    redactSensitive: "tools",
  },

  // Helps when people spam messages quickly; OpenClaw will batch/summarize
  routing: {
    queue: {
#
      mode: "collect",
      debounceMs: 900,
      cap: 20,
      drop: "summarize",
    },
  },

  // Safer DM isolation (recommended even if you *think* you’re the only user)
  session: {
    scope: "per-sender",
    dmScope: "per-channel-peer",
    resetByType: {
      dm: { mode: "idle", idleMinutes: 240 },
      group: { mode: "idle", idleMinutes: 120 },
    },
#
    resetTriggers: ["/new", "/reset"],
  },

  models: {
    mode: "merge",
    providers: {
      ollama: {
        baseUrl: "http://127.0.0.1:11434/v1",
        apiKey: "${OLLAMA_API_KEY}",
        api: "openai-completions",
        models: [
          {
            id: "qwen2.5:3b-instruct",
            name: "Qwen2.5 3B Instruct (Ollama)",
            reasoning: false,
#
            input: ["text"],
            cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
            contextWindow: 32768,
            maxTokens: 8192,
          },
        ],
      },

      // Moonshot (Kimi) fallback provider
      moonshot: {
        // International endpoint:
        baseUrl: "https://api.moonshot.ai/v1",
        // If you’re in China, use:
        // baseUrl: "https://api.moonshot.cn/v1",
#
        apiKey: "${MOONSHOT_API_KEY}",
        api: "openai-completions",
        models: [
          {
            id: "kimi-k2.5",
            name: "Kimi K2.5 (Moonshot)",
            reasoning: false,
            input: ["text"],
            cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
            contextWindow: 256000,
            maxTokens: 8192,
          },
        ],
      },
    },
#
  },

  agents: {
    defaults: {
      workspace: "~/.openclaw/workspace",
      timeoutSeconds: 600,

      // Primary local model, fallback to Moonshot if local fails / times out / etc.
      model: {
        primary: "ollama/qwen2.5:3b-instruct",
        fallbacks: ["moonshot/kimi-k2.5"],
      },

      // Optional aliases so you can quickly switch with /model (or /kimi etc)
      models: {
#
        "ollama/qwen2.5:3b-instruct": { alias: "qwen3b" },
        "moonshot/kimi-k2.5": { alias: "kimi" },
      },
    },
  },

  channels: {
    telegram: {
      enabled: true,
      botToken: "PUT_TELEGRAM_BOT_TOKEN_HERE",

      dmPolicy: "pairing", // pairing | allowlist | open | disabled

      // Group config is done with `groups` (NOT groupPolicy)
      // - If you want to allow ALL groups: keep "*"
#
      // - If you want allowlist-only: remove "*" and add specific group ids
      groups: {
        "*": { requireMention: true },
      },

      streamMode: "partial",
    },
  },
}

After you paste this into /root/.openclaw/openclaw.json (since you’re running as root), run:

openclaw doctor
#
openclaw gateway restart

If you want, paste your current gateway.bind line (or the whole gateway block) — that “Invalid input” error usually means it’s set to something like "localhost" or an IP, which won’t validate.

#

That output is actually good news: your config now parses and OpenClaw is running — this is a security audit report, not a crash.

Why you’re seeing CRITICAL/WARN

  • CRITICAL: qwen2.5:3b is a small model. Small models are much easier to prompt-inject into doing dumb stuff, especially if web_fetch/browser are enabled.
  • WARN: it also detected your Telegram DMs still share one “main” session (dmScope: "main"), which can leak context if more than one person ever DMs your bot.

Fix the WARN (DM leakage) — do this regardless

Add this to your config:

session: {
  dmScope: "per-channel-peer",
}
#

Your audit still says dmScope: main, so you either:

  • didn’t paste it into the actual config file the gateway is using, or
  • didn’t restart.

Run (safe to share output):

openclaw status --all

It will show which config path the service is reading.


Fix the CRITICAL (small model + web tools)

You have two valid “best” options. Pick one:

Option A (recommended, easiest + safest): Moonshot primary, Ollama fallback

This keeps web tools available without having to set up Docker sandboxing.

#
agents: {
  defaults: {
    model: {
      primary: "moonshot/kimi-k2.5",
      fallbacks: ["ollama/qwen2.5:3b-instruct"],
    },
  },
}

Option B (keep Ollama primary): disable web/browser tools (and ideally enable sandbox)

If you insist on Ollama 3B as primary, turn off the risky tools:

tools: {
#
  deny: ["group:web", "browser"], // group:web = web_search + web_fetch
},
session: {
  dmScope: "per-channel-peer",
},

This will stop the audit complaining about “Uncontrolled input tools allowed”.

If you want the audit fully happy with small models, you also need Docker sandboxing:

agents: {
  defaults: {
    sandbox: { mode: "all" },
#

It applies safe defaults + permission tightening. After that:

openclaw gateway restart
openclaw security audit --deep

If you paste your current gateway { ... }, agents.defaults, tools, and session blocks, I’ll rewrite them into one clean “final” config that matches Option A or Option B exactly.

#

Do this in 3 parts: (1) fix the config error, (2) fix the DM leak warning, (3) fix the “small model + web tools” critical. Then restart + verify.


1) Paste this working openclaw.json (recommended: Moonshot primary, Ollama fallback)

This removes the CRITICAL (because a strong hosted model is primary), keeps Ollama as fallback, and fixes the dmScope warning.

Copy/paste into /root/.openclaw/openclaw.json (your logs show you’re running as root), then fill tokens:

{
  gateway: {
    mode: "local",
    port: 18789,
    bind: "loopback", // valid: loopback | lan | tailnet | auto
#
    auth: { mode: "token", token: "PUT_A_GATEWAY_TOKEN_HERE" },
  },

  env: {
    OLLAMA_API_KEY: "ollama-local",          // any value works
    MOONSHOT_API_KEY: "PUT_MOONSHOT_KEY_HERE"
  },

  session: {
    scope: "per-sender",
    dmScope: "per-channel-peer", // fixes Telegram DM context leakage warning
    resetTriggers: ["/new", "/reset"],
  },

  // Optional: reduces chaos if you spam messages; it batches them
#
  routing: {
    queue: { mode: "collect", debounceMs: 900, cap: 20, drop: "summarize" },
  },

  models: {
    mode: "merge",
    providers: {
      ollama: {
        baseUrl: "http://127.0.0.1:11434/v1",
        apiKey: "${OLLAMA_API_KEY}",
        api: "openai-completions",
        models: [
          {
            id: "qwen2.5:3b-instruct",
            name: "Qwen2.5 3B Instruct (Ollama)",
#
            reasoning: false,
            input: ["text"],
            cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
            contextWindow: 32768,
            maxTokens: 8192,
          },
        ],
      },

      moonshot: {
        baseUrl: "https://api.moonshot.ai/v1",
        apiKey: "${MOONSHOT_API_KEY}",
        api: "openai-completions",
        models: [
          {
#
            id: "kimi-k2.5",
            name: "Kimi K2.5 (Moonshot)",
            reasoning: false,
            input: ["text"],
            cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
            contextWindow: 256000,
            maxTokens: 8192,
          },
        ],
      },
    },
  },

  agents: {
    defaults: {
#
      workspace: "~/.openclaw/workspace",
      model: {
        primary: "moonshot/kimi-k2.5",
        fallbacks: ["ollama/qwen2.5:3b-instruct"],
      },
    },
  },

  channels: {
    telegram: {
      enabled: true,
      botToken: "PUT_TELEGRAM_BOT_TOKEN_HERE",
      dmPolicy: "pairing",
      groups: {
        "*": { requireMention: true },
#
openclaw gateway restart
openclaw status --all
openclaw security audit --deep

If status --all shows a different config path than /root/.openclaw/openclaw.json, you were editing the wrong file.


3) If you INSIST on Ollama 3B as primary (alternative “all-local” solution)

Then you must remove the CRITICAL by disabling web/browser tools (and ideally use sandboxing):

agents: {
  defaults: {
#
    model: {
      primary: "ollama/qwen2.5:3b-instruct",
      fallbacks: ["moonshot/kimi-k2.5"],
    },
    // best-practice for small models:
    // sandbox: { mode: "all" },
  },
},
tools: {
  deny: ["group:web", "browser"], // group:web = web_search + web_fetch
},
session: { dmScope: "per-channel-peer" },

(That’s exactly what your audit told you: small model + web tools = risky.)

#

If you paste your current /root/.openclaw/openclaw.json (redact tokens), I’ll point out the exact lines you still need to change so the audit goes clean.

#

You’re very close. Your current file has 3 real problems + 1 security choice:

Fixes you need

  1. Delete channels.telegram.groupPolicy
    That key is invalid. Group control is done only via channels.telegram.groups.

  2. Delete the whole plugins block
    Telegram is not a plugin. Having plugins.entries.telegram is unnecessary and can confuse things.

  3. Add secure DM mode (fixes your WARN):

"session": { "dmScope": "per-channel-peer" }
  1. Your CRITICAL security audit happens because your PRIMARY model is a small local model (3B) and web tools are enabled.
    Best solution: make Moonshot primary and keep Ollama as fallback.
#

Also: you pasted real tokens/keys in a public chat. Rotate/revoke them now (Moonshot key + gateway token + Telegram bot token).


✅ Best working config (Moonshot primary, Ollama fallback) — copy/paste

(plain JSON, no comments)

{
  "meta": {
    "lastTouchedVersion": "2026.2.6-3",
    "lastTouchedAt": "2026-02-09T17:40:00Z"
  },
  "wizard": {
    "lastRunAt": "2026-02-09T17:37:21.748Z",
    "lastRunVersion": "2026.2.6-3",
#
    "lastRunCommand": "doctor",
    "lastRunMode": "local"
  },
  "env": {
    "OLLAMA_API_KEY": "ollama-local",
    "MOONSHOT_API_KEY": "PUT_MOONSHOT_KEY_HERE"
  },
  "gateway": {
    "mode": "local",
    "port": 18789,
    "bind": "loopback",
    "auth": {
      "mode": "token",
      "token": "PUT_GATEWAY_TOKEN_HERE"
    }
#
  },
  "session": {
    "scope": "per-sender",
    "dmScope": "per-channel-peer",
    "resetTriggers": ["/new", "/reset"]
  },
  "models": {
    "mode": "merge",
    "providers": {
      "ollama": {
        "baseUrl": "http://127.0.0.1:11434/v1",
        "apiKey": "${OLLAMA_API_KEY}",
        "api": "openai-completions",
        "models": [
          {
#
            "id": "qwen2.5:3b-instruct",
            "name": "Qwen2.5 3B Instruct (Ollama)",
            "reasoning": false,
            "input": ["text"],
            "cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 },
            "contextWindow": 32768,
            "maxTokens": 8192
          }
        ]
      },
      "moonshot": {
        "baseUrl": "https://api.moonshot.ai/v1",
        "apiKey": "${MOONSHOT_API_KEY}",
        "api": "openai-completions",
        "models": [
#
          {
            "id": "kimi-k2.5",
            "name": "Kimi K2.5 (Moonshot)",
            "reasoning": false,
            "input": ["text"],
            "cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 },
            "contextWindow": 256000,
            "maxTokens": 8192
          }
        ]
      }
    }
  },
  "agents": {
    "defaults": {
#
      "workspace": "~/.openclaw/workspace",
      "model": {
        "primary": "moonshot/kimi-k2.5",
        "fallbacks": ["ollama/qwen2.5:3b-instruct"]
      }
    }
  },
  "channels": {
    "telegram": {
      "enabled": true,
      "botToken": "PUT_TELEGRAM_BOT_TOKEN_HERE",
      "dmPolicy": "pairing",
      "groups": {
        "*": { "requireMention": true }
      },
#
      "streamMode": "partial"
    }
  }
}

Apply it

After saving:

openclaw gateway restart
openclaw security audit --deep
#

If you still want Ollama as primary, tell me and I’ll give you the “all-local” version (it must disable web_fetch/browser or enable sandboxing to clear the CRITICAL).

#

That audit is being conservative on purpose: it will flag a small model even if it’s only in fallbacks, because an attacker can sometimes force failover (timeouts / rate limits) and then your bot would run on the small model with web_fetch/browser still enabled.

You have 2 real “complete solutions” — pick the one you want:


Solution A (clean audit, no Docker needed): remove the small-model fallback

If you want to keep web_fetch/browser available, then don’t keep a 3B model in fallbacks.

Set:

"agents": {
  "defaults": {
    "model": {
      "primary": "moonshot/kimi-k2.5",
#
      "fallbacks": []
    }
  }
}

Restart:

openclaw gateway restart
openclaw security audit --deep

Solution B (keep Ollama fallback): disable web tools + browser (and ideally sandbox)

If you insist on keeping ollama/qwen2.5:3b-instruct as a fallback, then to satisfy the audit you must deny web tools + browser (because those are the “uncontrolled input” tools):

#

Add this at top-level:

"tools": {
  "deny": ["group:web", "browser"]
}

That alone will clear the “web=[web_fetch,browser]” part.

Optional but recommended if you’re using small models at all (requires Docker + sandbox image):

"agents": {
  "defaults": {
    "sandbox": { "mode": "all" }
  }
#
}

Restart:

openclaw gateway restart
openclaw security audit --deep

About the WARN: gateway.trustedProxies

You can ignore this unless you’re putting the Control UI behind nginx/caddy/traefik/etc.

  • If you are using a reverse proxy, add something like:
#
  "gateway": {
    "trustedProxies": ["127.0.0.1"]
  }

(or the proxy’s real IP if it’s on another machine/container network)

  • If you are not using a reverse proxy, leave it as-is.

If you tell me which you want:

  1. Keep web_fetch/browser (then you must use Solution A), or
  2. Keep Ollama fallback (Solution B, web tools off),

…I’ll paste the exact final full JSON with your current values merged.

#

D’accord — tu veux Ollama en premier, Kimi (Moonshot) en fallback, avec sandbox activé, et web tools + browser désactivés pour que l’audit sécurité arrête de crier. Voici la config complète + les commandes.

Important (sécurité) : tu as posté des tokens dans le chat. Révoque/regen :

  • MOONSHOT_API_KEY
  • le gateway.auth.token
  • le telegram.botToken

1) openclaw.json complet (copy/paste)

Colle ça dans /root/.openclaw/openclaw.json (vu que tu lances OpenClaw en root), puis remplace les PUT_..._HERE.

{
  "meta": {
#
    "lastTouchedVersion": "2026.2.6-3",
    "lastTouchedAt": "2026-02-09T17:40:00Z"
  },
  "wizard": {
    "lastRunAt": "2026-02-09T17:37:21.748Z",
    "lastRunVersion": "2026.2.6-3",
    "lastRunCommand": "doctor",
    "lastRunMode": "local"
  },

  "env": {
    "OLLAMA_API_KEY": "ollama-local",
    "MOONSHOT_API_KEY": "PUT_MOONSHOT_KEY_HERE"
  },
#
  "gateway": {
    "mode": "local",
    "port": 18789,
    "bind": "loopback",
    "trustedProxies": ["127.0.0.1"],
    "auth": {
      "mode": "token",
      "token": "PUT_GATEWAY_TOKEN_HERE"
    }
  },

  "session": {
    "scope": "per-sender",
    "dmScope": "per-channel-peer",
    "resetTriggers": ["/new", "/reset"]
#
  },

  "routing": {
    "queue": {
      "mode": "collect",
      "debounceMs": 900,
      "cap": 20,
      "drop": "summarize"
    }
  },

  "tools": {
    "deny": ["group:web", "browser"]
  },
#
  "browser": {
    "enabled": false
  },

  "models": {
    "mode": "merge",
    "providers": {
      "ollama": {
        "baseUrl": "http://127.0.0.1:11434/v1",
        "apiKey": "${OLLAMA_API_KEY}",
        "api": "openai-completions",
        "models": [
          {
            "id": "qwen2.5:3b-instruct",
            "name": "Qwen2.5 3B Instruct (Ollama)",
#
            "reasoning": false,
            "input": ["text"],
            "cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 },
            "contextWindow": 32768,
            "maxTokens": 8192
          }
        ]
      },
      "moonshot": {
        "baseUrl": "https://api.moonshot.ai/v1",
        "apiKey": "${MOONSHOT_API_KEY}",
        "api": "openai-completions",
        "models": [
          {
            "id": "kimi-k2.5",
#
            "name": "Kimi K2.5 (Moonshot)",
            "reasoning": false,
            "input": ["text"],
            "cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 },
            "contextWindow": 256000,
            "maxTokens": 8192
          }
        ]
      }
    }
  },

  "agents": {
    "defaults": {
      "workspace": "~/.openclaw/workspace",
#

      "sandbox": {
        "mode": "all",
        "scope": "session",
        "workspaceAccess": "rw"
      },

      "model": {
        "primary": "ollama/qwen2.5:3b-instruct",
        "fallbacks": ["moonshot/kimi-k2.5"]
      }
    }
  },

  "channels": {
#
    "telegram": {
      "enabled": true,
      "botToken": "PUT_TELEGRAM_BOT_TOKEN_HERE",
      "dmPolicy": "pairing",
      "groups": {
        "*": { "requireMention": true }
      },
      "streamMode": "partial"
    }
  }
}

Ce que ça règle :

  • plus de groupPolicy (clé invalide) ni de plugins.telegram
  • dmScope isolé par sender
#
  • sandbox ON partout
  • web_fetch/web_search + browser OFF
  • Ollama primary, Kimi fallback

2) Commandes à taper

A) Redémarrer le gateway

openclaw gateway restart

B) Vérifier que tu modifies le bon fichier

openclaw status --all
#

Regarde la ligne “Config path”/“Config (service)” : il faut que ça pointe bien sur /root/.openclaw/openclaw.json.

C) Relancer l’audit

openclaw security audit --deep

3) Sandbox Docker : build de l’image (si OpenClaw te dit “image missing”)

Le sandbox utilise Docker. Il faut builder l’image openclaw-sandbox:bookworm-slim une fois.

  1. Installer Docker (selon ta distro), puis vérifier :
docker --version
#
  1. Avoir un checkout git d’OpenClaw (juste pour avoir les scripts) :
git clone https://github.com/openclaw/openclaw.git ~/openclaw
cd ~/openclaw
./scripts/sandbox-setup.sh
  1. Puis :
openclaw gateway restart
openclaw security audit --deep

Docs sandbox : https://docs.openclaw.ai/gateway/sandboxing


#

Si tu veux “Kimi pour les tâches complexes” sans attendre un failover, dis-moi sur quel channel tu l’utilises (Telegram DM uniquement ?) et je te donne la config avec alias modèle + comment switcher proprement (commande /model) sans casser l’audit.

#

Colle ce fichier tel quel (en remplaçant les PUT_..._HERE) dans /root/.openclaw/openclaw.json.
Il fait exactement ce que tu demandes : Ollama en primary, Kimi (Moonshot) en fallback, sandbox ON, web tools + browser OFF (pour satisfaire l’audit).

openclaw.json (complet, prêt à copier/coller)

{
  "env": {
    "OLLAMA_API_KEY": "ollama-local",
    "MOONSHOT_API_KEY": "PUT_MOONSHOT_KEY_HERE"
  },

  "gateway": {
    "mode": "local",
    "port": 18789,
    "bind": "loopback",
    "auth": {
#
      "mode": "token",
      "token": "PUT_GATEWAY_TOKEN_HERE"
    }
  },

  "session": {
    "scope": "per-sender",
    "dmScope": "per-channel-peer",
    "resetTriggers": ["/new", "/reset"]
  },

  "routing": {
    "queue": { "mode": "collect", "debounceMs": 900, "cap": 20, "drop": "summarize" }
  },
#
  "tools": {
    "deny": ["group:web", "browser"],
    "elevated": { "enabled": false }
  },

  "browser": { "enabled": false },

  "models": {
    "mode": "merge",
    "providers": {
      "ollama": {
        "baseUrl": "http://127.0.0.1:11434/v1",
        "apiKey": "${OLLAMA_API_KEY}",
        "api": "openai-completions",
        "models": [
#
          {
            "id": "qwen2.5:3b-instruct",
            "name": "Qwen2.5 3B Instruct (Ollama)",
            "reasoning": false,
            "input": ["text"],
            "cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 },
            "contextWindow": 32768,
            "maxTokens": 8192
          }
        ]
      },
      "moonshot": {
        "baseUrl": "https://api.moonshot.ai/v1",
        "apiKey": "${MOONSHOT_API_KEY}",
        "api": "openai-completions",
#
        "models": [
          {
            "id": "kimi-k2.5",
            "name": "Kimi K2.5 (Moonshot)",
            "reasoning": false,
            "input": ["text"],
            "cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 },
            "contextWindow": 256000,
            "maxTokens": 8192
          }
        ]
      }
    }
  },
#
  "agents": {
    "defaults": {
      "workspace": "~/.openclaw/workspace",

      "sandbox": {
        "mode": "all",
        "scope": "session",
        "workspaceAccess": "none"
      },

      "model": {
        "primary": "ollama/qwen2.5:3b-instruct",
        "fallbacks": ["moonshot/kimi-k2.5"]
      },
#
      "models": {
        "ollama/qwen2.5:3b-instruct": { "alias": "ollama" },
        "moonshot/kimi-k2.5": { "alias": "kimi" }
      }
    }
  },

  "channels": {
    "telegram": {
      "enabled": true,
      "botToken": "PUT_TELEGRAM_BOT_TOKEN_HERE",
      "dmPolicy": "pairing",
      "groups": { "*": { "requireMention": true } },
      "streamMode": "partial"
    }
#
  }
}

Commandes à taper (dans l’ordre)

1) Redémarrer

openclaw gateway restart

2) Vérifier que le service lit bien /root/.openclaw/openclaw.json

#
openclaw status --all

3) Refaire l’audit

openclaw security audit --deep

Sandbox Docker (obligatoire si tu veux que le CRITICAL disparaisse)

Si l’audit continue à dire “sandbox=off” ou si le gateway log dit que l’image manque, il faut Docker + l’image sandbox.

  1. Vérifie Docker :
#
docker --version
  1. Build l’image sandbox (une fois) :
git clone https://github.com/openclaw/openclaw.git ~/openclaw
cd ~/openclaw
./scripts/sandbox-setup.sh

Puis :

openclaw gateway restart
openclaw security audit --deep
#

Utiliser Kimi “pour les tâches complexes”

Dans Telegram, tu peux switcher dans la session :

  • /model kimi
    ou
  • /model moonshot/kimi-k2.5

Et revenir sur Ollama :

  • /model ollama

Si tu me colles le résultat de openclaw status --all (juste la partie config path + gateway), je te dis direct si tu modifies le bon fichier et si le sandbox est bien activé.

#

Parfait — là c’est réglé.

  • 0 critical / 0 warn = ta config est OK.
  • Le bloc “models.small_params …” est maintenant en INFO (normal) parce que tu utilises un modèle 3B, mais il confirme que c’est OK chez toi : sandbox=all et web=[off].

Seul truc à corriger encore (si tu veux être cohérent avec l’audit)

Ton audit dit encore :

tools.elevated: enabled

Dans le JSON que je t’ai donné je l’avais mis à false, donc soit :

  • tu n’as pas appliqué cette partie, soit
  • tu as une autre config/service qui override.

Si tu veux le mode “super safe” (recommandé avec un petit modèle), mets ça :

#
"tools": {
  "deny": ["group:web", "browser"],
  "elevated": { "enabled": false }
}

Puis :

openclaw gateway restart
openclaw security audit --deep

Pour utiliser Kimi quand tu veux (tâches complexes)

Dans Telegram :

  • passer sur Kimi : /model kimi (ou /model moonshot/kimi-k2.5)
  • revenir sur Ollama : /model ollama
#

Si ça t’a débloqué: dans Discord, pense à marquer la solution (clic droit sur le message → Apps → ✅ Mark Solution) pour Answer Overflow.

#

Nickel — tout est clean maintenant.

Ces logs veulent juste dire :

  • Telegram démarre OK
  • le Gateway s’annonce en mDNS/Bonjour sur le LAN (openclaw.local, port 18789)
  • audit sécurité OK : elevated disabled, browser disabled, pas de warnings.

Tu peux tester tout de suite :

  1. DM ton bot Telegram → il doit répondre (pairing si activé).
  2. Pour forcer Kimi sur une tâche : /model kimi
    Pour revenir à Ollama : /model ollama

Si ça marche, pense à marquer la solution (clic droit sur le message → Apps → ✅ Mark Solution) pour que ça soit indexé sur Answer Overflow.

#

Oui c’est normal — ce n’est pas une erreur, c’est un message INFO de l’audit.

Il te dit exactement :

  • modèle petit détecté ✅
  • sandbox=all
  • web tools off + browser off
  • donc c’est OK (“ok; sandbox=all; web=[off]”)

Ils ajoutent juste la phrase “Small models are not recommended…” comme rappel général.

Si tu veux ne plus le voir du tout, il n’y a que 2 options :

  1. ne plus utiliser un petit modèle (mettre Kimi en primary), ou
  2. baisser le niveau de logs/audit (mais perso je te conseille de le garder, c’est utile).

Les lignes lane enqueue/dequeue + embedded run start indiquent que ton message Telegram a bien déclenché un run agent, donc ça tourne.

#

Ces lignes-là ne sont pas une erreur “grave”, c’est surtout du debug.

1) Removed orphaned user message to prevent consecutive user turns

Ça arrive quand OpenClaw retrouve dans l’historique un message user “orphelin” (un message utilisateur précédent qui n’a pas eu de réponse assistant, typiquement à cause d’un restart, d’un abort, ou de plusieurs messages envoyés très vite).

OpenClaw supprime alors l’ancien message orphelin pour éviter d’envoyer au modèle une séquence invalide du style user → user (certains providers/tooling détestent ça).

Ce que tu peux faire :

  • Dans Telegram, envoie /reset (ou /new) pour repartir sur un historique propre.
  • Évite d’envoyer 3–4 messages d’un coup, attends la réponse.

2) sessionKey=unknown

C’est juste une ligne de diagnostic en mode debug. Si tout répond correctement sur Telegram, tu peux l’ignorer.

3) Est-ce que tu reçois bien une réponse sur Telegram ?

  • Si oui → tout est OK, c’est juste du bruit de logs (tu peux baisser les logs à info si tu veux).
  • Si non (pas de réponse Telegram) → lance ces commandes et colle la sortie :
#
  openclaw channels status --probe
  openclaw logs --follow

Et vérifie aussi le pairing (si dmPolicy=pairing) :

openclaw pairing list telegram

Dis-moi juste: le bot répond dans Telegram ou pas ? (et à quel message tu l’as testé).

#

Ces lignes veulent juste dire :

  • le run a bien démarré sur Telegram (provider=ollama … messageChannel=telegram)
  • il a bien fini (run_completed, aborted=false, ~1.1s)
  • puis un 2e run a redémarré tout de suite après → donc OpenClaw a reçu un autre event/message dans le même DM (souvent: tu as envoyé 2 messages très vite, ou Telegram a envoyé un update “annexe”).

Le seul “suspect” dans ce que tu as montré plus haut, c’est :

Removed orphaned user message to prevent consecutive user turns

Ça arrive après un restart / coupure: il y avait un ancien message utilisateur dans l’historique sans réponse assistant, OpenClaw le retire pour éviter user → user. Solution simple : reset la session Telegram.

Fais ça (dans Telegram DM au bot)

  1. Envoie :
  • /reset (ou /new)
  1. Puis envoie un test simple :
  • ping
#

Si le bot NE répond toujours pas

Alors le run se fait, mais l’envoi Telegram échoue ou est bloqué. Lance et colle la sortie :

openclaw channels status --probe
openclaw logs --follow

Et si tu es en dmPolicy: pairing, vérifie/valide le pairing :

openclaw pairing list telegram
openclaw pairing approve telegram <CODE>

Dis-moi juste un truc : dans Telegram, tu vois une réponse du bot ou rien du tout ?

#

Rien de “cassé” dans ce que tu as collé : tes logs montrent que le bot reçoit bien le message Telegram, lance un run, et le run se termine sans abort. Le seul truc “bizarre” est ce warning :

Removed orphaned user message to prevent consecutive user turns

Ça arrive après un restart / coupure / plusieurs messages envoyés trop vite : il restait un ancien message “user” sans réponse, et OpenClaw le supprime pour éviter un historique invalide user → user.

Pour réparer / nettoyer (2 minutes)

A) Reset la conversation côté Telegram

Dans le DM Telegram avec le bot, envoie :

  • /reset (ou /new)
    Puis envoie un test simple :
  • ping

B) Si tu ne reçois toujours AUCUNE réponse sur Telegram

  1. Vérifie le pairing (si dmPolicy: "pairing") :
#
openclaw pairing list telegram
openclaw pairing approve telegram <CODE>
  1. Vérifie l’état du channel Telegram :
openclaw channels status --probe
  1. Et suis les logs pendant que tu envoies un message Telegram :
openclaw logs --follow

Dis-moi juste : tu reçois une réponse du bot dans Telegram après /reset + ping, oui ou non ? Si non, colle la sortie de openclaw channels status --probe (ça pointe direct la cause).

#

Ces logs ne montrent pas une erreur — ils montrent juste que :

  • le message Telegram est bien reçu,
  • un run agent démarre (embedded run start … provider=ollama … messageChannel=telegram),
  • et pendant que ça tourne, d’autres messages arrivent → ils partent dans la file (queueSize=2).

Tu as copié les logs en plein milieu du run, donc c’est normal que tu ne voies pas encore run_completed / sendMessage.

La seule vraie question

Est‑ce que tu reçois une réponse dans Telegram ou rien du tout ?


Si tu reçois une réponse (même lente)

Rien à réparer : ton modèle Ollama 3B est juste lent (CPU) et la queue monte si tu renvoies des messages pendant qu’il répond.
Conseils :

  • attends la réponse avant d’envoyer un 2e message
#
  • ou bascule sur Kimi quand tu veux vite : /model kimi

Si tu ne reçois AUCUNE réponse dans Telegram

Alors ça se joue entre (a) Ollama qui hang, (b) envoi Telegram qui fail.

1) Vérifie Ollama

curl http://127.0.0.1:11434/api/tags
ollama ps || true

2) Vérifie Telegram (probe)

openclaw channels status --probe
#

3) Suis les logs au moment exact où tu envoies “ping” sur Telegram

openclaw logs --follow

Et cherche une ligne d’erreur du style telegram sendMessage failed ou ollama ... connection refused/timeout.

4) Nettoie la session (si tu vois encore des “orphaned user message”)

Dans Telegram DM : /reset puis ping.

Colle ici la sortie de openclaw channels status --probe si ça ne répond toujours pas — c’est le plus diagnostique.

#

Tes logs montrent que Telegram → Gateway → run agent marche (le run démarre bien sur messageChannel=telegram). Là où ça coince (si tu ne vois rien dans Telegram), c’est la phase “envoi de la réponse” ou le pairing.

Comme tu n’as pas collé la sortie de openclaw channels status --probe, on va faire un test qui isole le problème en 30 secondes.

1) Test “Telegram peut-il envoyer ?” (sans passer par le modèle)

Tu as déjà ton user id dans les logs : telegram:dm:5084819981.

Lance :

openclaw message send --channel telegram --target 5084819981 --message "TEST: message envoyé par la CLI"

Résultat attendu

  • Si tu reçois ce message dans Telegram → l’envoi Telegram fonctionne, donc le souci est côté agent/modèle/session.
  • Si tu ne reçois rien → souci token Telegram / réseau vers api.telegram.org / permissions.

2) Vérifie le pairing (car dmPolicy=pairing)

#

Même si les runs démarrent, si tu n’es pas “approved” proprement tu peux avoir un comportement bizarre.

openclaw pairing list telegram

S’il y a un code en attente :

openclaw pairing approve telegram <CODE>

3) Colle la sortie de channels status --probe

Relance et colle tout ce que ça affiche :

openclaw channels status --probe
#

4) Bonus (très probable sur un VPS) : IPv6 / DNS Telegram

Si le probe/logs montre des erreurs réseau vers Telegram, teste vite :

curl -I https://api.telegram.org

Réponds juste avec :

  1. Est-ce que openclaw message send … arrive dans Telegram ? (oui/non)
  2. La sortie de openclaw channels status --probe

et je te dis exactement quoi changer.

#

Ton channels status --probe dit clairement :

Telegram … running … token:config, works

Donc Telegram n’est pas le problème. Les logs que tu colles montrent surtout 3 choses normales :

  1. Le run agent démarre bien (donc le message arrive bien au Gateway)
  2. queueSize=2 = tu as envoyé plusieurs messages (ou plusieurs events) pendant qu’il traite → ils sont mis en file
  3. embedded run tool start … tool=write = le modèle a utilisé l’outil write dans le sandbox (normal, et ça ne bloque pas l’envoi Telegram)

Ce que tu veux “réparer”, c’est probablement : “je ne vois pas la réponse dans Telegram” ou “ça spam de logs debug”.


A) Si tu ne reçois PAS de réponse dans Telegram (le plus probable)

Je te conseille de désactiver le draft streaming Telegram pour éliminer toute bizarrerie de sendMessageDraft.

#

Dans openclaw.json, mets :

"channels": {
  "telegram": {
    "streamMode": "off"
  }
}

Puis :

openclaw gateway restart

Et teste dans Telegram DM : /reset puis ping.

#

B) Test “envoi Telegram” (isole le problème en 10 secondes)

Tu as ton chat id DM : 5084819981. Envoie un message direct via la CLI :

openclaw message send --channel telegram --target 5084819981 --message "TEST CLI -> Telegram"
  • Si tu le reçois → Telegram envoie OK, donc le souci (si souci) est côté modèle/run/historique.
  • Si tu ne le reçois pas → là ce serait réseau/bot token (mais ton probe dit “works”, donc je parie que tu vas le recevoir).

C) Si tu veux arrêter le spam de logs debug

Baisse le niveau de logs :

#
"logging": { "level": "info" }

puis :

openclaw gateway restart

Dis-moi juste 2 trucs :

  1. Tu reçois “TEST CLI -> Telegram” ou pas ?
  2. Tu reçois une réponse après /reset + ping ou pas ?
#

Parfait — donc Telegram envoi/réception = OK. Le problème est dans le run agent (modèle Ollama / historique / streaming), pas dans Telegram.

On fait les fixes dans l’ordre le plus efficace :

1) Coupe le streaming Telegram (ça évite des cas où le draft n’apparaît pas / bug)

Dans ton openclaw.json :

"channels": {
  "telegram": {
    "streamMode": "off"
  }
}

Puis :

#
openclaw gateway restart

2) Reset la session Telegram (nettoie les “orphaned user message”)

Dans le DM Telegram avec le bot :

  • /reset
  • puis ping

3) Vérifie si Ollama répond vraiment (indépendant d’OpenClaw)

Sur le serveur :

ollama run qwen2.5:3b-instruct "Dis juste: OK"

Si ça met 2 minutes, c’est normal que le bot paraisse “muet”.

#

4) Si tu veux que ça réponde vite (recommandé sur VPS CPU)

Passe ton primary à un modèle plus costaud local (tu l’as déjà) :

  • qwen2.5:7b-instruct ou llama3:8b

Exemple :

"agents": {
  "defaults": {
    "model": {
      "primary": "ollama/qwen2.5:7b-instruct",
      "fallbacks": ["moonshot/kimi-k2.5"]
    }
  }
}

Puis :

#
openclaw gateway restart

5) Dis-moi le résultat

Après (1)+(2), est-ce que le bot répond à ping dans Telegram, oui/non ?

#

Si ollama run llama3:8b "Dis juste: OK" reste sur le spinner longtemps, ce n’est pas OpenClaw : c’est Ollama qui galère (CPU trop lent, ou surtout pas assez de RAM → swap/thrashing).

1) Stoppe le test et vérifie si ta machine swap

Sur le serveur :

# stoppe le run ollama si besoin
# (Ctrl+C)

free -h
uptime
lscpu | head

Repères :

  • Si free -h montre très peu de RAM libre et/ou du swap utilisé, llama3:8b sera inutilisable (même pour “OK”).
  • Sur un VPS CPU “petit”, 8B peut être très lent. Un 3B/4B est souvent déjà limite.
#

2) Teste un modèle plus léger (vraiment)

ollama run qwen2.5:3b-instruct "Réponds juste: OK"
# ou
ollama run phi3:mini "Réponds juste: OK"

Si même ça est lent, alors ton VPS est juste trop faible pour du local “confortable”.

3) Côté OpenClaw : fais en sorte que ça “failover” vite sur Kimi

OpenClaw ne sait pas basculer “selon la complexité”, il bascule surtout sur erreur/timeout. Donc baisse le timeout pour ne pas rester muet trop longtemps :

Dans openclaw.json :

"agents": {
#
  "defaults": {
    "timeoutSeconds": 45,
    "model": {
      "primary": "ollama/qwen2.5:3b-instruct",
      "fallbacks": ["moonshot/kimi-k2.5"]
    }
  }
}

Puis :

openclaw gateway restart

4) Si tu veux juste que Telegram arrête d’être “bizarre” visuellement

#

Désactive le streaming draft :

"channels": { "telegram": { "streamMode": "off" } }

Dis-moi ce que donne free -h (RAM + swap) et combien de vCPU tu as (ligne lscpu | head), et je te dis quel modèle Ollama de ta liste a le plus de chances d’être “réactif” sur ce VPS.

#

Ça, c’est Ollama qui te répond (HTTP 400) : phi3:mini ne supporte pas les “tools” (function calling).

OpenClaw envoie un schéma d’outils au modèle (même si tu as déjà désactivé web/browser), donc si le modèle Ollama ne gère pas tools, Ollama refuse la requête.

Solutions (choisis)

Option 1 (recommandé) : n’utilise pas phi3:mini avec OpenClaw “agentic”

Garde un modèle Ollama qui supporte les tools (ex: ton qwen2.5:3b-instruct qui, lui, marche).

Ensuite tu peux utiliser Kimi pour le lourd via /model kimi.

Option 2 : laisse OpenClaw auto-détecter uniquement les modèles Ollama “tool-capable”

Le plus simple pour éviter de tomber sur des modèles incompatibles :

  1. Supprime le bloc models.providers.ollama de ton openclaw.json (tout le provider ollama).
  2. Garde env.OLLAMA_API_KEY (n’importe quelle valeur).
  3. Restart :
#
openclaw gateway restart
openclaw models list

OpenClaw va auto-découvrir Ollama et ne garder que les modèles qui annoncent tools.

(Ref: https://docs.openclaw.ai/providers/ollama )

Option 3 : tu veux absolument phi3:mini → alors tu dois passer en “chat only” (zéro tools)

Dans ce cas, tu dois désactiver tous les tools pour que OpenClaw n’envoie aucun schéma d’outils :

"tools": { "deny": ["*"] }

Mais attention : ça veut dire plus de read/write/exec, donc OpenClaw devient un bot de chat “simple”.

#

Si tu me dis quel modèle tu veux utiliser en local (dans ta liste: gemma2, qwen2.5:3b, qwen2.5:7b, llama3:8b, etc.), je te dis lequel a le plus de chances d’être tool-compatible et rapide sur ton VPS (RAM/CPU).

#

Non, pas avec phi3:mini sur Ollama.

Le message que tu as eu (“does not support tools”) veut dire exactement ça : phi3:mini ne sait pas faire du tool-calling, donc il ne peut pas :

  • appeler sessions_spawn (sub-agents),
  • utiliser des outils OpenClaw (même read/write, etc.),
  • “router” automatiquement vers Moonshot/Kimi.

Donc phi3:mini ne peut pas être un “agent routeur/orchestrateur” dans OpenClaw.

Ce que tu peux faire à la place (2 options)

Option 1 (recommandée) : garder un routeur local tool-capable (Qwen), et déléguer à Kimi via sub-agents

Tu gardes ton setup sécurisé (sandbox + web off), et tu ajoutes juste des subagents sur Kimi.

Ajoute ça dans ton openclaw.json (dans agents.defaults) :

#
"agents": {
  "defaults": {
    "model": {
      "primary": "ollama/qwen2.5:3b-instruct",
      "fallbacks": ["moonshot/kimi-k2.5"]
    },
    "subagents": {
      "model": "moonshot/kimi-k2.5",
      "maxConcurrent": 2,
      "archiveAfterMinutes": 60
    }
  }
}

Ensuite, dans Telegram, demande explicitement :

#

“Si c’est complexe, spawn un sub-agent sur Kimi et reviens avec un résumé.”

Tu peux vérifier que ça a spawn avec :

  • /subagents list

(Si le routeur n’en spawn jamais, on pourra lui donner une règle simple dans ton AGENTS.md du workspace, mais déjà teste comme ça.)

Option 2 : utiliser phi3:mini, mais chat-only (pas d’agent, pas de délégation)

Si tu veux absolument phi3:mini, alors tu dois accepter qu’il ne fera aucun outil. Donc pas de redistribution automatique.

Config minimale (phi3 chat-only) :

"agents": { "defaults": { "model": { "primary": "ollama/phi3:mini" } } },
"tools": { "deny": ["*"] }

Et quand tu veux du “complexe”, tu switches manuellement :

#
  • /model kimi

Si tu veux, dis-moi ce que tu préfères :

  1. “délégation automatique” → on part sur Option 1 (Qwen routeur + subagents Kimi)
  2. “phi3 à tout prix” → Option 2 (chat-only + /model kimi manuel)

et je te donne le openclaw.json final complet correspondant (sans approximation).

#

Ces logs sont normaux et plutôt “bons” :

  • signal SIGTERM received → ton service systemd a demandé l’arrêt (souvent à cause d’un restart).
  • Puis ça redémarre proprement :
    • agent model: ollama/qwen2.5:3b-instruct
    • listening on ws://127.0.0.1:18789 ✅ (bind loopback)
    • cron: started, heartbeat: started, Telegram démarre ✅
    • log file /tmp/openclaw/openclaw-2026-02-09.log

Donc rien à réparer ici : c’est juste le cycle normal “stop → start”.

Si ton souci est “pourquoi ça s’arrête tout seul ?”

Les causes typiques :

  1. tu as fait openclaw gateway restart (ou systemd a redémarré le service)
  2. tu as modifié openclaw.json et ton setup a déclenché un restart (certaines sections demandent un restart complet)
  3. tu as lancé systemctl restart openclaw-gateway.service
#

Tu peux confirmer avec :

systemctl status openclaw-gateway.service --no-pager
journalctl -u openclaw-gateway.service -n 80 --no-pager

Si ton souci est “je veux phi3 routeur”

Rappel: phi3:mini ne supporte pas tools, donc il ne peut pas orchestrer. Le bon pattern reste :

  • qwen 3b (tool-capable) = routeur local
  • Kimi = sub-agent pour les tâches dures

Si tu veux, je te donne le bloc exact à ajouter pour que le routeur utilise Kimi via /subagents (et comment le déclencher depuis Telegram).

#

Tu as 2 sujets différents ici :

1) systemctl status openclaw-gateway.service → “Unit could not be found”

Ça veut dire : il n’existe pas de service systemd “system” nommé openclaw-gateway.service sur ta machine.

Sur Linux, OpenClaw installe par défaut un service systemd user (pas system). Donc les commandes correctes sont plutôt :

# Voir si un service user existe (à lancer avec le même user qui fait tourner OpenClaw)
systemctl --user list-unit-files | grep -i openclaw
systemctl --user status openclaw-gateway.service --no-pager
journalctl --user -u openclaw-gateway.service -n 200 --no-pager

Si tu es connecté en root, attention : les “user services” root sont souvent pas utilisés (et parfois il n’y a même pas de session user systemd). Sur un VPS, le plus propre est :

  • créer un user dédié (ex: openclaw)
#
  • installer le gateway sous ce user
  • activer le linger : sudo loginctl enable-linger openclaw
  • puis systemctl --user enable --now openclaw-gateway.service

Sinon, alternative: installer un system service (dans /etc/systemd/system/...) — c’est expliqué dans la doc Gateway (section “Alternative (system service)”).

Le check le plus simple (sans systemctl) :

openclaw gateway status

Ça te dit clairement si OpenClaw est supervisé par systemd/launchd/etc ou juste lancé “à la main”.

Et pour les logs, même sans systemd :

  • openclaw logs --follow
  • ou fichier: /tmp/openclaw/openclaw-YYYY-MM-DD.log

(Ref doc: “Linux systemd (if installed): journalctl --user -u openclaw-gateway[-<profile>].service …”)

#

2) La “réponse du bot” sur “forbidden / find a way around…”

Ça, c’est juste une réponse du modèle (hallucination / confusion), pas un message système fiable.

Ne cherche surtout pas à “trouver un moyen de contourner une restriction”. Si tu veux diagnostiquer OpenClaw, fais-le côté serveur avec les commandes CLI (openclaw gateway status, openclaw channels status --probe, openclaw logs --follow), pas en demandant au modèle.


Si tu me colles la sortie de :

openclaw gateway status

je te dis exactement si tu es en mode “service systemd user”, “service systemd system”, ou “process lancé à la main”, et quel nom d’unité systemd il faut utiliser (s’il y en a une).

#

Voilà, c’est clair maintenant :

  • Tu as bien un service systemd USER (pas system) :
    • Service file: ~/.config/systemd/user/openclaw-gateway.service
    • Runtime: running (pid 1327)
    • RPC probe: ok

Donc tes commandes précédentes échouaient parce que tu utilisais le mauvais “scope”.

Commandes correctes (service USER)

Voir le status

systemctl --user status openclaw-gateway.service --no-pager

Voir les logs systemd (user)

#
journalctl --user -u openclaw-gateway.service -n 200 --no-pager

Suivre les logs OpenClaw (recommandé)

openclaw logs --follow

(et sinon fichier: /tmp/openclaw/openclaw-2026-02-09.log)

Pourquoi journalctl -u ... donnait “No entries”

Parce que tu étais en root et tu regardais les logs system. Ton gateway est un service user, donc il faut --user et être dans la bonne session user (ou préciser l’utilisateur).

Si tu es root et tu veux quand même voir les logs du user qui run OpenClaw :

sudo -u <TON_USER> journalctl --user -u openclaw-gateway.service -n 200 --no-pager
#

Note importante (réseau)

Ton gateway est en :

bind=loopback (127.0.0.1)
Donc c’est normal que seuls les clients sur la machine puissent se connecter au dashboard/WS. Telegram fonctionne quand même (c’est le serveur qui sort vers Telegram).

Si tu veux accéder au dashboard depuis ton PC :

  • soit tunnel SSH :
    ssh -N -L 18789:127.0.0.1:18789 root@srv1346862
    
    puis ouvre http://127.0.0.1:18789/ sur ton PC
  • soit gateway.bind: "lan" + token (mais c’est moins safe)

Là honnêtement : tout marche. Tu peux rester comme ça.

Si ça t’a débloqué, pense à Mark Solution sur le message qui t’a aidé (clic droit → Apps → ✅ Mark Solution).

#

Ton service est nickel (active/running) — les lignes “bizarres” dans systemctl --user status sont toutes explicables et, dans ton cas, pas bloquantes :

1) Removed orphaned user message to prevent consecutive user turns

Normal après un restart / coupure / spam de messages. Il y avait un ancien message “user” sans réponse “assistant” dans l’historique, OpenClaw le retire pour éviter un historique invalide (user → user).

Fix simple (dans Telegram DM) :

  • /reset
  • puis ping

2) typing TTL reached (2m); stopping typing indicator

Juste l’indicateur “typing…” Telegram qui s’arrête au bout de 2 minutes si le modèle met trop longtemps.
Si tu vois ça souvent, c’est que Ollama est lent sur ton VPS → utilise /model kimi pour les réponses rapides, ou baisse timeoutSeconds pour forcer le failover plus vite.

3) sessions.resolve … No session found with label: :telefon:

Ça vient du Control UI / d’un client qui a demandé “résous-moi une session qui s’appelle :telefon:”, mais ce label n’existe pas. Ça ne casse rien.

Tu peux l’ignorer. Si tu veux vérifier les sessions existantes côté CLI :

#
openclaw sessions --active 120

4) Le message du bot “forbidden / find a way around…”

C’était juste une réponse du modèle (pas un vrai diagnostic système). À ignorer.


En résumé : quoi faire maintenant

  1. Dans Telegram : /reset puis ping
  2. Si Ollama est trop lent : /model kimi pour les tâches “complexes/rapides”
  3. (Option) Forcer le failover plus vite en config :
"agents": { "defaults": { "timeoutSeconds": 45 } }

puis openclaw gateway restart

#

Si après /reset + ping tu n’as toujours pas de vraie réponse Telegram, colle juste 20–30 lignes de openclaw logs --follow autour du moment où tu envoies ping.

#

Tout ce que tu montres ici indique que rien n’est “wrong” côté service :

  • Active: active (running)
  • listening on ws://127.0.0.1:18789
  • Telegram “works” (tu l’avais déjà avec channels status --probe) ✅

La ligne :

Troubles: run openclaw status

…c’est juste un message “help” générique que le CLI affiche à la fin, pas une alerte.

Ce qu’on doit clarifier maintenant

Ton problème réel c’est lequel ?

  1. Le bot ne répond pas dans Telegram ?
  2. Il répond mais c’est trop lent ?
#
  1. Tu veux juste enlever les logs / warnings ?

Si c’est (1) “pas de réponse Telegram”

Fais ces 2 tests et dis-moi le résultat :

A) Test direct (tu as déjà confirmé que ça marche)

openclaw message send --channel telegram --target 5084819981 --message "TEST"

B) Test via agent (dans Telegram DM)

Envoie :

  • /reset
  • puis ping
#

Et sur le serveur, regarde les erreurs d’envoi au même moment :

openclaw logs --follow

Si c’est (2) “trop lent”

C’est normal sur VPS CPU avec Ollama. Tu as 3 leviers :

  • utiliser un modèle plus léger (3B) et accepter que ça reste “ok-ish”
  • ou utiliser Kimi pour les réponses rapides : /model kimi
  • ou forcer le failover vite :

Dans openclaw.json :

#
"agents": { "defaults": { "timeoutSeconds": 45 } }

puis :

openclaw gateway restart

Si c’est (3) “trop de logs”

Dans openclaw.json :

"logging": { "level": "info" }

puis restart.

#

Dis-moi juste : dans Telegram, après /reset + ping, tu reçois une réponse oui/non ? (et si non, colle 20 lignes de openclaw logs --follow autour du moment où tu envoies ping).

#

Là on voit enfin le vrai problème dans tes logs :

embedded run timeout … timeoutMs=600000
FailoverError: LLM request timed out.

Donc le bot reçoit bien le message Telegram, mais le LLM (Ollama) ne répond pas avant le timeout (10 minutes), et la requête finit en timeout. Ce n’est pas Telegram.

Et ton autre erreur :

phi3:mini … does not support tools

=> ça confirme que phi3:mini ne peut pas être un “agent routeur/orchestrateur” (pas de tool-calling, donc pas de subagents/skills/outils).

1) Ce que tu veux (phi3 routeur) n’est pas possible avec phi3:mini

Si tu veux un “agent qui délègue”, il te faut un modèle local tool-capable (ex: qwen2.5:3b-instruct), puis déléguer à Kimi avec sessions_spawn.

#

Dans tes logs on a la preuve : Ollama time out (10 minutes), donc le bot reste “typing…” puis échoue. La solution est de forcer un failover rapide vers Kimi.

Fais exactement ça :

1) Modifie ton openclaw.json

Ajoute dans agents.defaults :

"agents": {
  "defaults": {
    "timeoutSeconds": 45,
    "model": {
      "primary": "ollama/qwen2.5:3b-instruct",
      "fallbacks": ["moonshot/kimi-k2.5"]
    }
  }
#

Le “problème” là, ce n’est plus OpenClaw ni Telegram : c’est Ollama qui met trop longtemps (ou hang) → du coup le bot reste en “typing…”, puis timeout, et tu as l’impression qu’il “répond plus”.

Tu as déjà eu dans tes logs :

  • embedded run timeout …
  • FailoverError: LLM request timed out.

Donc on fait un fix simple : arrêter le run bloqué + forcer le fallback Kimi rapidement + réduire le tool schema (sinon un petit modèle rame).


1) Débloque tout de suite (dans Telegram)

Envoie au bot :

  1. /stop
  2. /reset
  3. /model kimi
  4. puis ping
#

Si là il répond, c’est confirmé : le local (Ollama) est trop lent, Kimi marche.


2) Fix durable : failover rapide vers Kimi (sinon ça “freeze”)

Dans ton openclaw.json, mets/valide ça :

"agents": {
  "defaults": {
    "timeoutSeconds": 45,
    "model": {
      "primary": "ollama/qwen2.5:3b-instruct",
      "fallbacks": ["moonshot/kimi-k2.5"]
    }
  }
#
}

Puis redémarre :

openclaw gateway restart

Comme ça, si Ollama rame, au bout de 45s max ça bascule sur Kimi au lieu d’attendre 10 minutes puis mourir.


3) Fix important : réduire les outils visibles (sinon le 3B se noie)

Pour un petit modèle, laisse uniquement le minimum (et garde web/browser off) :

#
"tools": {
  "allow": ["sessions_spawn", "session_status"],
  "deny": ["group:web", "browser"],
  "elevated": { "enabled": false }
}

Redémarre ensuite :

openclaw gateway restart

4) Vérifie dans les logs que le fallback Moonshot part bien

Pendant que tu envoies ping dans Telegram :

#
openclaw logs --follow

Si tu vois encore un timeout sans qu’il essaye Moonshot, colle ici les lignes autour du timeout (20–40 lignes) et je te dis exactement quoi manque dans la config.

Question rapide : après /model kimi + ping, il répond bien (oui/non) ?

#

Phi3 peut seulement servir en “chat simple” (sans outils) + tu switches manuellement sur Kimi avec /model kimi.

2) Pourquoi ton setup actuel “ne répond pas”

Parce que qwen2.5:3b-instruct (sur ton VPS) met trop longtemps et finit en timeout.

Fix principal : réduire le timeout pour forcer le fallback Kimi rapidement

Dans openclaw.json, ajoute/ajuste :

"agents": {
  "defaults": {
    "timeoutSeconds": 45,
    "model": {
      "primary": "ollama/qwen2.5:3b-instruct",
      "fallbacks": ["moonshot/kimi-k2.5"]
    }
#
}

2) Redémarre

openclaw gateway restart

3) Test dans Telegram

  • /reset
  • ping

Résultat attendu

  • Si Ollama est lent → au bout de ~45s max, ça bascule sur Kimi et tu reçois une réponse.

4) (Optionnel mais utile) Test direct Kimi

#
  }
}

Puis :

openclaw gateway restart

Test dans Telegram :

  • /reset
  • puis ping

Si Ollama est lent, au bout de ~45s ça bascule sur Kimi au lieu de rester “typing…” puis mourir à 10 min.

3) (Très recommandé) Réduire les outils exposés au modèle local

#

Dans Telegram :

  • /model kimi
  • ping

Réponds-moi avec juste : est-ce que ping répond maintenant (oui/non) ? Si non, colle 20–30 lignes de openclaw logs --follow au moment du test.

#

Même avec web/browser off, tu peux encore réduire la “surface” (et le prompt) pour aider un petit modèle :

"tools": {
  "allow": ["sessions_spawn", "session_status"],
  "deny": ["group:web", "browser"],
  "elevated": { "enabled": false }
}

(Ça garde juste ce qu’il faut pour déléguer à un sub-agent, et enlève le reste.)

4) Vérifie que Kimi marche bien

Dans Telegram :

  • /model kimi
  • ping
#

Si ça répond vite, ton fallback est bon.


Si tu me dis juste : après avoir mis timeoutSeconds: 45, est-ce que ping répond (oui/non) ?
Si non, colle 30 lignes de openclaw logs --follow autour du timeout (on verra si Ollama hang ou si le fallback Moonshot échoue aussi).

#

Le problème, c’est simplement : ton modèle local Ollama (qwen2.5:3b) ne répond pas assez vite sur ton VPS, donc OpenClaw reste en “typing…”, puis finit par :

  • typing TTL reached (2m)
  • puis timeout : embedded run timeout … FailoverError: LLM request timed out. (chez toi c’était 600s = 10 minutes)

Telegram est OK (tu reçois le “TEST CLI”), donc ce n’est pas le bot Telegram.

Fix “propre” (local d’abord, mais fallback Kimi rapide)

  1. Dans ~/.openclaw/openclaw.json, mets un timeout court pour forcer le fallback :
{
  "agents": {
    "defaults": {
      "timeoutSeconds": 45,
      "model": {
#
        "primary": "ollama/qwen2.5:3b-instruct",
        "fallbacks": ["moonshot/kimi-k2.5"]
      }
    }
  }
}
  1. Redémarre :
openclaw gateway restart
  1. Dans Telegram (DM au bot) :
  • /stop
  • /reset
#
  • puis ping

Résultat attendu : si Ollama rame, au bout de ~45s max ça bascule sur Kimi et tu as une réponse (au lieu d’attendre 10 min puis timeout).


Fix “stabilité” (important avec un petit modèle) : réduire la taille des tools

Même si tu as désactivé web/browser, le schéma d’outils peut rester énorme et faire “noyer” un 3B.

Mets un allowlist minimal (routeur + statut), comme ça Qwen a moins à gérer :

{
  "tools": {
    "allow": ["sessions_spawn", "session_status"],
    "deny": ["group:web", "browser"],
#
    "elevated": { "enabled": false }
  }
}

Puis :

openclaw gateway restart

À savoir : phi3:mini “routeur” automatique = impossible

Tu as vu l’erreur Ollama : phi3:mini ne supporte pas tools. Donc il ne peut pas appeler sessions_spawn → il ne peut pas déléguer automatiquement à Kimi.


#

Dis-moi juste ceci

Après avoir mis timeoutSeconds: 45 :

  1. Est-ce que ping répond dans Telegram (oui/non) ?
  2. Si non, colle 20 lignes de openclaw logs --follow autour du moment où tu envoies ping (on verra si Moonshot est bien tenté ou si c’est aussi lui qui échoue).
#

Ton fichier que tu as collé est incomplet (il s’arrête après "models": {...} et il y a une virgule , juste avant la fin). Du coup, si tu l’as vraiment comme ça sur le serveur, ce n’est pas du JSON valide et OpenClaw peut faire n’importe quoi / ignorer des morceaux.

Et surtout : le vrai souci qu’on a vu dans tes logs, c’est Ollama qui time-out. Donc il faut :

  • forcer un failover rapide vers Kimi
  • réduire le “tool schema” (sinon un 3B rame)
  • garder sandbox + web/browser off (déjà OK chez toi)

Voici un openclaw.json complet (JSON valide) que tu peux copier/coller en remplacement. Remplace juste les tokens.

~/.openclaw/openclaw.json (complet, prêt à coller)

{
  "meta": {
    "lastTouchedVersion": "2026.2.6-3",
    "lastTouchedAt": "2026-02-09T19:35:00Z"
#
  },

  "wizard": {
    "lastRunAt": "2026-02-09T18:51:08.683Z",
    "lastRunVersion": "2026.2.6-3",
    "lastRunCommand": "doctor",
    "lastRunMode": "local"
  },

  "env": {
    "OLLAMA_API_KEY": "ollama-local",
    "MOONSHOT_API_KEY": "PUT_MOONSHOT_KEY_HERE"
  },

  "gateway": {
#

Voici le openclaw.json complet, JSON valide, exactement pour ton usage :

  • Ollama (qwen2.5:3b-instruct) en premier
  • Moonshot / Kimi en fallback
  • Sandbox ON (all)
  • web tools + browser désactivés
  • timeout court (45s) pour éviter “typing… puis plus rien”
  • Telegram OK, streaming OFF (plus stable)
  • outils visibles du petit modèle réduits (important)

Copie/colle tel quel dans ~/.openclaw/openclaw.json (chez toi c’est /root/.openclaw/openclaw.json), puis remplace les PUT_..._HERE.

{
  "meta": {
    "lastTouchedVersion": "2026.2.6-3",
#
    "mode": "local",
    "port": 18789,
    "bind": "loopback",
    "auth": {
      "mode": "token",
      "token": "PUT_GATEWAY_TOKEN_HERE"
    }
  },

  "logging": {
    "level": "info",
    "redactSensitive": "tools"
  },

  "browser": { "enabled": false },
#
    "lastTouchedAt": "2026-02-09T19:36:00Z"
  },

  "env": {
    "OLLAMA_API_KEY": "ollama-local",
    "MOONSHOT_API_KEY": "PUT_MOONSHOT_KEY_HERE"
  },

  "gateway": {
    "mode": "local",
    "port": 18789,
    "bind": "loopback",
    "auth": {
      "mode": "token",
      "token": "PUT_GATEWAY_TOKEN_HERE"
#

  "routing": {
    "queue": { "mode": "collect", "debounceMs": 900, "cap": 20, "drop": "summarize" }
  },

  "session": {
    "scope": "per-sender",
    "dmScope": "per-channel-peer",
    "resetTriggers": ["/new", "/reset"]
  },

  "tools": {
    "allow": ["sessions_spawn", "session_status"],
    "deny": ["group:web", "browser"],
    "elevated": { "enabled": false }
#
    }
  },

  "logging": {
    "level": "info",
    "redactSensitive": "tools"
  },

  "browser": { "enabled": false },

  "session": {
    "scope": "per-sender",
    "dmScope": "per-channel-peer",
    "resetTriggers": ["/new", "/reset"]
  },
#
  },

  "models": {
    "mode": "merge",
    "providers": {
      "ollama": {
        "baseUrl": "http://127.0.0.1:11434/v1",
        "apiKey": "${OLLAMA_API_KEY}",
        "api": "openai-completions",
        "models": [
          {
            "id": "qwen2.5:3b-instruct",
            "name": "Qwen2.5 3B Instruct (Ollama)",
            "reasoning": false,
            "input": ["text"],
#

  "routing": {
    "queue": {
      "mode": "collect",
      "debounceMs": 900,
      "cap": 20,
      "drop": "summarize"
    }
  },

  "tools": {
    "allow": ["sessions_spawn", "session_status"],
    "deny": ["group:web", "browser"],
    "elevated": { "enabled": false }
  },
#
            "cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 },
            "contextWindow": 32768,
            "maxTokens": 8192
          }
        ]
      },

      "moonshot": {
        "baseUrl": "https://api.moonshot.ai/v1",
        "apiKey": "${MOONSHOT_API_KEY}",
        "api": "openai-completions",
        "models": [
          {
            "id": "kimi-k2.5",
            "name": "Kimi K2.5 (Moonshot)",
#

  "models": {
    "mode": "merge",
    "providers": {
      "ollama": {
        "baseUrl": "http://127.0.0.1:11434/v1",
        "apiKey": "${OLLAMA_API_KEY}",
        "api": "openai-completions",
        "models": [
          {
            "id": "qwen2.5:3b-instruct",
            "name": "Qwen2.5 3B Instruct (Ollama)",
            "reasoning": false,
            "input": ["text"],
            "cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 },
#
            "reasoning": false,
            "input": ["text"],
            "cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 },
            "contextWindow": 256000,
            "maxTokens": 8192
          }
        ]
      }
    }
  },

  "agents": {
    "defaults": {
      "workspace": "~/.openclaw/workspace",
#
            "contextWindow": 32768,
            "maxTokens": 8192
          }
        ]
      },

      "moonshot": {
        "baseUrl": "https://api.moonshot.ai/v1",
        "apiKey": "${MOONSHOT_API_KEY}",
        "api": "openai-completions",
        "models": [
          {
            "id": "kimi-k2.5",
            "name": "Kimi K2.5 (Moonshot)",
            "reasoning": false,
#
      "sandbox": {
        "mode": "all",
        "scope": "session",
        "workspaceAccess": "none"
      },

      "timeoutSeconds": 45,

      "model": {
        "primary": "ollama/qwen2.5:3b-instruct",
        "fallbacks": ["moonshot/kimi-k2.5"]
      },

      "subagents": {
        "model": "moonshot/kimi-k2.5",
#
            "input": ["text"],
            "cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 },
            "contextWindow": 256000,
            "maxTokens": 8192
          }
        ]
      }
    }
  },

  "agents": {
    "defaults": {
      "workspace": "~/.openclaw/workspace",

      "sandbox": {
#
        "maxConcurrent": 2,
        "archiveAfterMinutes": 60
      },

      "models": {
        "ollama/qwen2.5:3b-instruct": { "alias": "ollama" },
        "moonshot/kimi-k2.5": { "alias": "kimi" }
      }
    }
  },

  "channels": {
    "telegram": {
      "enabled": true,
      "botToken": "PUT_TELEGRAM_BOT_TOKEN_HERE",
#
        "mode": "all",
        "scope": "session",
        "workspaceAccess": "none"
      },

      "timeoutSeconds": 45,

      "model": {
        "primary": "ollama/qwen2.5:3b-instruct",
        "fallbacks": ["moonshot/kimi-k2.5"]
      },

      "subagents": {
        "model": "moonshot/kimi-k2.5",
        "maxConcurrent": 2,
#
      "dmPolicy": "pairing",
      "groups": { "*": { "requireMention": true } },
      "streamMode": "off"
    }
  }
}

Pourquoi ça règle ton “il répond une fois puis plus”

  • Si Ollama rame/hang, OpenClaw n’attend plus 10 minutes : au bout de 45s il peut failover sur Kimi (au lieu de rester en typing puis timeout).
  • Le modèle local voit beaucoup moins d’outils (juste sessions_spawn + session_status), donc il est moins “noyé”.

Commandes à taper après avoir collé le fichier

openclaw gateway restart
#
        "archiveAfterMinutes": 60
      },

      "models": {
        "ollama/qwen2.5:3b-instruct": { "alias": "ollama" },
        "moonshot/kimi-k2.5": { "alias": "kimi" }
      }
    }
  },

  "channels": {
    "telegram": {
      "enabled": true,
      "botToken": "PUT_TELEGRAM_BOT_TOKEN_HERE",
      "dmPolicy": "pairing",
#
openclaw security audit --deep
openclaw channels status --probe

Et dans Telegram :

  • /stop
  • /reset
  • ping
  • (si besoin) /model kimi

Si après ça il ne répond toujours pas, colle 30 lignes de openclaw logs --follow juste au moment où tu envoies ping (on verra si le failover Moonshot est bien tenté ou si c’est Moonshot qui bloque).

#
      "groups": { "*": { "requireMention": true } },
      "streamMode": "off"
    }
  }
}

Commandes après collage

openclaw gateway restart
openclaw security audit --deep
openclaw channels status --probe

Test dans Telegram

  • /stop
#
  • /reset
  • ping
  • (si tu veux forcer Kimi) /model kimi

Si tu veux, colle ensuite le résultat de openclaw logs --follow pendant un ping si ça ne répond pas — mais avec timeoutSeconds: 45 tu ne devrais plus rester bloqué.

#

Tu peux faire “Qwen d’abord” + “Kimi si c’est trop lent/complexe”, mais il y a une limite importante :

  • “si Qwen dit ‘c’est complexe’ alors switch” n’existe pas comme règle automatique côté config.
    Ça doit être fait par instruction (Qwen appelle sessions_spawn pour lancer Kimi), ou bien tu switches toi-même avec /model kimi.

Par contre, “si Qwen ne répond pas / time out → fallback Kimi” oui, ça se fait via fallbacks + timeout.

Ci‑dessous, le JSON complet (valide) pour ton usage, avec :

  • Ollama/Qwen en primary
  • Moonshot/Kimi en fallback
  • sandbox=all
  • web + browser OFF
  • timeout global 120s (et on guide Qwen à escalader vers Kimi dès que c’est “complexe” ou s’il pense dépasser ~60s)

Remplace les tokens.


#

1) ~/.openclaw/openclaw.json (complet)

{
  "meta": {
    "lastTouchedVersion": "2026.2.6-3",
    "lastTouchedAt": "2026-02-09T19:40:00Z"
  },

  "env": {
    "OLLAMA_API_KEY": "ollama-local",
    "MOONSHOT_API_KEY": "PUT_MOONSHOT_KEY_HERE"
  },

  "gateway": {
    "mode": "local",
#
    "port": 18789,
    "bind": "loopback",
    "auth": {
      "mode": "token",
      "token": "PUT_GATEWAY_TOKEN_HERE"
    }
  },

  "logging": {
    "level": "info",
    "redactSensitive": "tools"
  },

  "browser": { "enabled": false },
#
  "session": {
    "scope": "per-sender",
    "dmScope": "per-channel-peer",
    "resetTriggers": ["/new", "/reset"]
  },

  "routing": {
    "queue": { "mode": "collect", "debounceMs": 900, "cap": 20, "drop": "summarize" }
  },

  "tools": {
    "allow": ["sessions_spawn", "session_status"],
    "deny": ["group:web", "browser"],
    "elevated": { "enabled": false }
  },
#

  "models": {
    "mode": "merge",
    "providers": {
      "ollama": {
        "baseUrl": "http://127.0.0.1:11434/v1",
        "apiKey": "${OLLAMA_API_KEY}",
        "api": "openai-completions",
        "models": [
          {
            "id": "qwen2.5:3b-instruct",
            "name": "Qwen2.5 3B Instruct (Ollama)",
            "reasoning": false,
            "input": ["text"],
            "cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 },
#
            "contextWindow": 32768,
            "maxTokens": 2048
          }
        ]
      },

      "moonshot": {
        "baseUrl": "https://api.moonshot.ai/v1",
        "apiKey": "${MOONSHOT_API_KEY}",
        "api": "openai-completions",
        "models": [
          {
            "id": "kimi-k2.5",
            "name": "Kimi K2.5 (Moonshot)",
            "reasoning": false,
#
            "input": ["text"],
            "cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 },
            "contextWindow": 256000,
            "maxTokens": 8192
          }
        ]
      }
    }
  },

  "agents": {
    "defaults": {
      "workspace": "~/.openclaw/workspace",

      "sandbox": {
#
        "mode": "all",
        "scope": "session",
        "workspaceAccess": "none"
      },

      "timeoutSeconds": 120,

      "model": {
        "primary": "ollama/qwen2.5:3b-instruct",
        "fallbacks": ["moonshot/kimi-k2.5"]
      },

      "subagents": {
        "model": "moonshot/kimi-k2.5",
        "maxConcurrent": 2,
#
        "archiveAfterMinutes": 60
      },

      "models": {
        "ollama/qwen2.5:3b-instruct": { "alias": "ollama" },
        "moonshot/kimi-k2.5": { "alias": "kimi" }
      }
    }
  },

  "channels": {
    "telegram": {
      "enabled": true,
      "botToken": "PUT_TELEGRAM_BOT_TOKEN_HERE",
      "dmPolicy": "pairing",
#
      "groups": { "*": { "requireMention": true } },
      "streamMode": "off"
    }
  }
}

Pourquoi timeoutSeconds: 120 et pas 60 ?

  • Si tu mets 60, tu risques de couper tout le run avant que le fallback Kimi ait le temps de répondre.
  • Avec 120s, Qwen a “sa chance”, et si ça bloque, le fallback peut encore répondre.

2) Instruction pour le “si c’est complexe → utilise Kimi”

Ça se fait via ton workspace (AGENTS.md), pas via un switch magique.

#

Crée/édite : ~/.openclaw/workspace/AGENTS.md et mets un bloc comme ça :

# Routing rule (IMPORTANT)

You are running on a small local model (Qwen 3B). Keep replies short.

If the user request is complex (multi-step reasoning, long code, debugging, research, or you feel unsure),
DO NOT struggle locally.
Instead, immediately spawn a sub-agent on Moonshot Kimi K2.5 and ask it to produce the final answer.

When spawning, include the full user request and any key context.

(Qwen suivra ça “au mieux” — c’est de l’obéissance au prompt, pas une règle hard.)


#

3) Commandes à taper

Après avoir collé le JSON :

openclaw gateway restart
openclaw security audit --deep
openclaw channels status --probe

Test dans Telegram :

  • /reset
  • ping

Et pour forcer Kimi manuellement à tout moment :

  • /model kimi

#

Si tu veux vraiment “60 secondes pile pour Qwen puis switch automatique”, le plus fiable n’est pas un fallback : c’est que Qwen spawn Kimi dès qu’il estime dépasser 60s (via la règle AGENTS.md).

zealous iglooBOT
#

Ça, c’est juste l’état de la file d’attente (queue) d’OpenClaw — comment il gère quand tu envoies plusieurs messages pendant qu’il est déjà en train de répondre.

Ce que ça veut dire chez toi

  • mode=collect : si tu envoies plusieurs messages à la suite, OpenClaw les regroupe en un seul “paquet” avant de lancer le modèle (au lieu de lancer 5 runs).
  • debounce=900ms : il attend ~0,9s après le dernier message avant de “figer” le paquet et démarrer le run.
  • cap=20 : au max, il garde 20 messages dans ce paquet.
  • drop=summarize : si tu dépasses le cap, il ne jette pas brutalement : il résume l’excès (pour éviter de perdre l’info).

Si tu veux changer

Tu peux envoyer la commande dans Telegram/Discord :

  • Plus réactif (moins d’attente) :
    • /queue debounce:200ms
  • Si tu veux qu’il traite chaque message séparément (pas conseillé si tu spam) :
    • /queue mode=interrupt
  • Si tu veux juste voir/valider :
    • /queue
#

En général, collect + summarize est le meilleur réglage pour éviter que le bot “s’étouffe” quand tu envoies plusieurs messages.

#

Ça veut dire que ta config utilise une clé legacy :

  • Ancien : routing.queue
  • Nouveau : messages.queue

OpenClaw arrive à l’auto-migrer en mémoire, mais il te prévient quand même et peut marquer la config “invalid” tant que tu n’as pas mis à jour le fichier.

Fix (à faire dans ~/.openclaw/openclaw.json)

1) Supprime / retire ce bloc (ou au moins queue)

"routing": {
  "queue": {
    "mode": "collect",
    "debounceMs": 900,
    "cap": 20,
#
    "drop": "summarize"
  }
}

2) Mets-le à la place sous messages.queue

Exemple (reprend exactement tes valeurs) :

"messages": {
  "queue": {
    "mode": "collect",
    "debounceMs": 900,
    "cap": 20,
    "drop": "summarize"
#
  }
}

Si tu as déjà un bloc "messages": { ... }, ajoute juste queue dedans (ne le duplique pas).

Puis redémarre

openclaw gateway restart

Et tu peux vérifier avec :

  • /queue dans le chat (ou)
openclaw status
#

Si tu colles ton bloc actuel "routing": { ... } + "messages": { ... } (2 blocs seulement, sans tokens), je te renvoie la version exacte “avant → après” sans rien casser.

#

Ça veut dire que tu utilises une ancienne clé de config.

Avant, la queue était sous :

  • routing.queue

Maintenant, elle est sous :

  • messages.queue

OpenClaw arrive à auto‑migrer en mémoire (donc ça marche), mais il te prévient et peut marquer la config “invalid” tant que le fichier n’est pas mis à jour.

Fix rapide (recommandé) — en CLI

Ça va supprimer l’ancienne clé et écrire la nouvelle au bon endroit :

#
openclaw config unset routing.queue
openclaw config set messages.queue '{mode:"collect",debounceMs:900,cap:20,drop:"summarize"}' --json
openclaw gateway restart

Ensuite vérifie :

  • dans le chat : /queue
  • ou en shell : openclaw status

C’est quoi “queue” concrètement ?

C’est la règle qui dit quoi faire si tu envoies plusieurs messages pendant que le bot répond :

  • mode=collect = regroupe les messages
  • debounceMs=900 = attend ~0,9s pour regrouper
  • cap=20 = max 20 messages
  • drop=summarize = si ça dépasse, il résume au lieu de jeter
#

Si tu veux, colle ton bloc actuel "routing": {...} et "messages": {...} (sans tokens) et je te le corrige proprement sans perdre d’autres options.

#

C’est OK. Il ne te reste qu’un seul WARN, et il n’empêche rien de fonctionner.

Pourquoi tu as ce WARN gateway.trustedProxies_missing

Tu as :

  • gateway.bind = loopback (127.0.0.1)
  • gateway.trustedProxies vide

Donc OpenClaw dit : “si jamais tu mets le Control UI derrière un reverse proxy (nginx/caddy/traefik), alors il faut déclarer les proxies ‘trusted’, sinon les headers x-forwarded-for etc. pourraient être spoofés”.

Dois-tu le corriger ?

  • Si tu n’utilises PAS de reverse proxy (tu accèdes via SSH tunnel ou uniquement local) → ignore, c’est normal.
  • Si tu utilises un reverse proxy (nginx/caddy) → mets l’IP de ton proxy.

Fix simple (si tu veux faire disparaître le WARN)

Ajoute dans ton openclaw.json :

#
"gateway": {
  "trustedProxies": ["127.0.0.1"]
}

(ou l’IP réelle du proxy si c’est un autre host / un container réseau)

Puis :

openclaw gateway restart
openclaw security audit

Le reste de l’audit

  • models.small_params … ok; sandbox=all; web=[off] = parfait, c’est juste un rappel.
  • tools.elevated: disabled, browser control: disabled = nickel.
#

Si tu me dis comment tu accèdes au dashboard (SSH tunnel ? nginx ?), je te donne la valeur exacte de trustedProxies.

#

Oui, comme ça c’est bon.

Deux mini-notes :

  1. trustedProxies: ["127.0.0.1"] est utile si tu as un reverse proxy qui tourne sur la même machine (nginx/caddy) et qui forward vers OpenClaw en local.
    Si tu n’as pas de reverse proxy, ça ne change rien (mais ça ne casse rien non plus).

  2. Après modification, n’oublie pas :

openclaw gateway restart
openclaw security audit

Si le WARN disparaît, c’est réglé.

#

Tes logs montrent un truc très simple :

  • Qwen (Ollama) ne répond pas avant le timeout
    embedded run timeout … timeoutMs=120000 → puis FailoverError: LLM request timed out.

Donc le bot “ne répond plus” parce que le run expire, pas parce que Telegram est cassé.

Point important (honnêteté)

OpenClaw n’a pas un switch magique “si Qwen dit c’est complexe alors bascule sur Kimi” uniquement via JSON.
Ce que tu peux faire de façon fiable en config, c’est :

  1. Essayer Qwen, et si timeout/erreur → fallback Kimi (ça oui)
  2. Réduire la charge sur Qwen (moins d’historique, moins de tokens) pour qu’il ait une chance de répondre en < 60s
  3. (Optionnel) ajouter une règle dans AGENTS.md pour que Qwen spawn Kimi quand c’est complexe — mais ça dépend du modèle (s’il est déjà bloqué, il ne spawn rien).

#

JSON complet “Qwen 60s max puis Kimi” (approche la plus stable)

  • timeout global = 180s (laisse le temps au fallback de répondre)
  • Qwen output maxTokens = 256 (répond vite ou échoue vite)
  • DM history limité (sinon Qwen 3B s’étouffe)
  • outils minimaux (pour pas noyer Qwen)
  • web/browser OFF + sandbox ON (comme tu veux)

Copie/colle ce fichier (et remplace les tokens) :

{
  "env": {
    "OLLAMA_API_KEY": "ollama-local",
    "MOONSHOT_API_KEY": "PUT_MOONSHOT_KEY_HERE"
  },
#

  "gateway": {
    "mode": "local",
    "port": 18789,
    "bind": "loopback",
    "trustedProxies": ["127.0.0.1"],
    "auth": { "mode": "token", "token": "PUT_GATEWAY_TOKEN_HERE" }
  },

  "logging": { "level": "info", "redactSensitive": "tools" },
  "browser": { "enabled": false },

  "messages": {
    "queue": { "mode": "collect", "debounceMs": 900, "cap": 20, "drop": "summarize" }
  },
#

  "session": {
    "scope": "per-sender",
    "dmScope": "per-channel-peer",
    "resetTriggers": ["/new", "/reset"]
  },

  "tools": {
    "allow": ["sessions_spawn", "session_status"],
    "deny": ["group:web", "browser"],
    "elevated": { "enabled": false }
  },

  "models": {
    "mode": "merge",
#
    "providers": {
      "ollama": {
        "baseUrl": "http://127.0.0.1:11434/v1",
        "apiKey": "${OLLAMA_API_KEY}",
        "api": "openai-completions",
        "models": [
          {
            "id": "qwen2.5:3b-instruct",
            "name": "Qwen2.5 3B Instruct (Ollama)",
            "reasoning": false,
            "input": ["text"],
            "cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 },
            "contextWindow": 32768,
            "maxTokens": 256
          }
#
        ]
      },
      "moonshot": {
        "baseUrl": "https://api.moonshot.ai/v1",
        "apiKey": "${MOONSHOT_API_KEY}",
        "api": "openai-completions",
        "models": [
          {
            "id": "kimi-k2.5",
            "name": "Kimi K2.5 (Moonshot)",
            "reasoning": false,
            "input": ["text"],
            "cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 },
            "contextWindow": 256000,
            "maxTokens": 8192
#
          }
        ]
      }
    }
  },

  "agents": {
    "defaults": {
      "workspace": "~/.openclaw/workspace",

      "sandbox": { "mode": "all", "scope": "session", "workspaceAccess": "none" },

      "timeoutSeconds": 180,

      "model": {
#
        "primary": "ollama/qwen2.5:3b-instruct",
        "fallbacks": ["moonshot/kimi-k2.5"]
      },

      "subagents": {
        "model": "moonshot/kimi-k2.5",
        "maxConcurrent": 2,
        "archiveAfterMinutes": 60
      },

      "models": {
        "ollama/qwen2.5:3b-instruct": {
          "alias": "ollama",
          "params": { "maxTokens": 256 }
        },
#
        "moonshot/kimi-k2.5": { "alias": "kimi" }
      }
    }
  },

  "channels": {
    "telegram": {
      "enabled": true,
      "botToken": "PUT_TELEGRAM_BOT_TOKEN_HERE",
      "dmPolicy": "pairing",
      "streamMode": "off",
      "dmHistoryLimit": 10,
      "groups": { "*": { "requireMention": true } }
    }
  }
#
}

Pourquoi timeoutSeconds = 180 et pas 60 ?

Parce que sinon tu tues le run avant que Kimi ait le temps de répondre.
Le “60 secondes max pour Qwen” on l’obtient surtout en limitant maxTokens + l’historique, ce qui rend Qwen beaucoup plus “rapide”.


À faire après

openclaw gateway restart

Dans Telegram :

  • /stop
#
  • /reset
  • envoie un message test

Et si tu veux forcer Kimi à la main quand ça t’énerve :

  • /model kimi

Si malgré ça tu vois encore FailoverError: LLM request timed out., colle 15–30 lignes de openclaw logs --follow autour du timeout : on vérifiera si Moonshot est bien tenté ou si c’est Qwen qui monopolise tout le budget.

#

Dans ce log, on voit un truc très important :

embedded run start … provider=moonshot model=kimi-k2.5 …
… agent end … durationMs=3060

Donc le failover vers Kimi a bien eu lieu et Kimi a répondu en ~3 secondes. Si tu ne vois toujours pas la réponse dans Telegram, alors le problème n’est plus “le modèle ne répond pas” mais plutôt la livraison du message (envoyer la réponse dans Telegram) ou un /send off.

1) Vérifie que l’envoi n’est pas désactivé dans la session Telegram

Dans Telegram (DM au bot), envoie :

  • /send

Si ça te dit off, fais :

  • /send on

Puis :

#
  • /reset
  • ping

(Ça arrive vite de couper /send par accident.)

2) Regarde dans les logs si OpenClaw essaie d’envoyer la réponse Telegram

Sur le serveur, fais un test propre :

  1. Dans un terminal :
openclaw logs --follow
  1. Dans Telegram, envoie ping

  2. Dans les logs, cherche une ligne du style telegram … sendMessage (succès/erreur).
    Si tu préfères grep direct dans le fichier log :

#
grep -n "runId=00df2d60" /tmp/openclaw/openclaw-2026-02-09.log | tail -n 80
grep -n "telegram" /tmp/openclaw/openclaw-2026-02-09.log | tail -n 80

3) Question rapide (pour arrêter de tourner en rond)

Tu confirmes : dans Telegram, tu as reçu une réponse de Kimi pour ce run-là (oui/non) ?

  • Si oui → tout marche, c’était juste Qwen/Ollama trop lent.
  • Si non → colle les ~30 lignes après embedded run prompt end (la partie “send”), et on voit exactement pourquoi ça ne se poste pas.
#

Dans ce que tu viens de coller, le run Moonshot (Kimi) se termine bien (run_completed, aborted=false, ~3.3s). Donc si tu ne vois aucune réponse dans Telegram, le souci n’est plus “le modèle ne répond pas”, c’est la livraison du message (réponse bloquée/supprimée) ou un réglage /send.

Les 2 causes les plus fréquentes :

1) /send est sur OFF dans ta session Telegram

Dans le DM Telegram avec le bot, envoie :

  • /send (ça affiche l’état)
  • si c’est off → /send on
  • puis /reset et ping

2) Erreur d’envoi Telegram (sendMessage) dans les logs, mais tu ne l’as pas copiée

Tes logs montrent le run, mais pas la partie “telegram sendMessage”.

Fais un grep ciblé dans le fichier log autour de 20:39 :

#
grep -n "20:39" /tmp/openclaw/openclaw-2026-02-09.log | tail -n 200
grep -n "sendMessage\\|telegram.*send" /tmp/openclaw/openclaw-2026-02-09.log | tail -n 200

Ou en live :

openclaw logs --follow

…puis tu envoies ping dans Telegram et tu copies les lignes où il tente d’envoyer.


Note

À 20:39:28 on voit un nouveau run qui démarre sur Ollama → ça veut juste dire que tu as renvoyé un message après, et il repart avec le modèle par défaut (Qwen).

#

Dis-moi juste :

  1. Dans Telegram, /send te dit quoi ? (on/off)
  2. Est-ce que tu as reçu une réponse à 20:39:06 (le run Kimi) oui/non ?
#

Dans ces logs, il n’y a pas “un nouveau bug” : tu vois juste le failover en action.

Ce qui se passe exactement à 20:41

  1. Qwen (Ollama) démarre à 20:39:28
  2. Timeout Qwen à 20:41:28 (timeoutMs=120000) → ça log :
    • FailoverError: LLM request timed out.
      C’est le signal interne qui dit “on abandonne ce modèle et on essaye le fallback”.
  3. Kimi (Moonshot) démarre immédiatement à 20:41:28
  4. Kimi finit en ~2s à 20:41:30 (aborted=false)

Donc : le fallback marche, et Kimi répond vite.


1) Tu veux “tester Qwen 60 secondes puis passer à Kimi”

C’est simple : mets juste le timeout à 60s (ça s’applique au modèle tenté, puis fallback part après).

#

Dans openclaw.json :

"agents": {
  "defaults": {
    "timeoutSeconds": 60,
    "model": {
      "primary": "ollama/qwen2.5:3b-instruct",
      "fallbacks": ["moonshot/kimi-k2.5"]
    }
  }
}

Puis :

#
openclaw gateway restart

2) Si tu ne VOIS PAS la réponse dans Telegram (alors que Kimi “end”)

Là, le souci est côté envoi du message ou /send off.

A) Vérifie /send

Dans Telegram DM au bot :

  • /send
    Si c’est off :
  • /send on
    Puis /reset et ping.

B) Cherche l’erreur d’envoi Telegram dans les logs

#

Tu dois voir un sendMessage ou une erreur Telegram autour de 20:41:30.

grep -n "20:41:3" /tmp/openclaw/openclaw-2026-02-09.log | tail -n 200
grep -n "telegram.*send\\|sendMessage\\|HttpError" /tmp/openclaw/openclaw-2026-02-09.log | tail -n 200

Colle-moi ce que ça sort, et je te dirai exactement pourquoi ça ne “deliver” pas.


Question rapide : dans Telegram, tu as reçu une réponse après 20:41:30 (oui/non) ?

#

Tes logs montrent 2 choses en même temps :

  1. Qwen/Ollama time out (normal sur un VPS CPU)
  2. Le fallback Kimi/Moonshot marche (il démarre et finit en ~2–3s)

Exemple chez toi :

  • timeoutMs=120000 → Qwen a expiré
  • juste après : provider=moonshot model=kimi-k2.5
  • puis : durationMs=2205 aborted=false

Donc le “bot répond plus” = tu attends Qwen, il time out, puis Kimi répond… mais si tu ne vois rien dans Telegram, c’est un souci de livraison (send) ou tu spams trop vite.

1) Vérifie que l’envoi n’est pas coupé dans ta session Telegram

Dans Telegram DM au bot, envoie :

  • /send
#

Si ça affiche off :

  • /send on

Puis :

  • /reset
  • ping

2) Ton grep est trop court (tu ne regardes pas la partie “sendMessage”)

Le fichier /tmp/openclaw/openclaw-2026-02-09.log est du JSONL, et ton grep "20:41:3" ne montre que quelques lignes.

Cherche explicitement l’envoi Telegram :

rg -n "sendMessage|sendMessageDraft|telegram.*send|HttpError" /tmp/openclaw/openclaw-2026-02-09.log | tail -n 200

S’il y a une erreur d’envoi, elle sera là.

#

3) “Qwen 60 secondes puis Kimi” : ce que tu peux faire vraiment

Le switch “si Qwen dit que c’est complexe alors passe à Kimi” ne peut pas être un automatisme 100% fiable via JSON.
Ce que tu peux faire de fiable :

  • si Qwen ne répond pas → fallback Kimi via timeout + fallbacks.

Mais attention : timeoutSeconds est le timeout du run. Si tu mets 60s, tu risques de couper trop agressivement. Perso je conseille :

  • timeoutSeconds: 120 (ce que tu as déjà)
  • et réduire la “charge” sur Qwen (historique + maxTokens)

Tu veux quand même 60s ? OK, mets :

"agents": { "defaults": { "timeoutSeconds": 60 } }

puis :

#
openclaw gateway restart

4) Important : arrête d’envoyer plusieurs messages pendant qu’il “typing”

Quand tu spam, tu crées une file (queueSize monte) et tu as l’impression qu’il ignore. Envoie un message, attends.


Question directe : dans Telegram, après /send on + /reset + ping, tu reçois une réponse oui/non ?
Si non, colle la sortie de la commande rg ... sendMessage ... (celle du point 2).

#

Tes logs prouvent 2 trucs :

  1. Qwen/Ollama timeout (normal sur ton VPS)
  2. Le fallback Kimi/Moonshot marche (il démarre et finit en ~2s)

Donc si tu “ne vois pas de réponse” dans Telegram alors que Kimi finit, le souci est presque toujours la livraison bloquée, pas le modèle.

1) Vérifie tout de suite que /send n’est pas OFF

Dans le DM Telegram avec le bot, envoie :

  • /send

Si ça répond off :

  • /send on

Puis :

  • /reset
#
  • ping

2) Ton log ne montre AUCUNE ligne d’envoi Telegram

Dans ce que tu as collé, on voit agent end / run done, mais pas de telegram sendMessage / erreur HttpError. Il faut chercher ça explicitement dans le fichier log JSONL.

Sur le serveur, lance :

rg -n "sendMessage|sendMessageDraft|telegram.*send|HttpError|sendPolicy|NO_REPLY" /tmp/openclaw/openclaw-2026-02-09.log | tail -n 200
  • Si tu vois NO_REPLY → le modèle a répondu “ne rien envoyer”.
  • Si tu vois une erreur HttpError/sendMessage failed → on corrige le transport.
  • Si tu ne vois rien du tout → c’est souvent /send off.

Colle-moi la sortie de cette commande.

#

3) Pour “tester Qwen 60 secondes puis passer à Kimi”

Mets simplement :

"agents": { "defaults": { "timeoutSeconds": 60 } }

et garde :

"model": { "primary": "ollama/qwen2.5:3b-instruct", "fallbacks": ["moonshot/kimi-k2.5"] }

Puis :

openclaw gateway restart
#

Ça fera : Qwen max 60s, sinon Kimi.

Dis-moi juste : après /send on + /reset + ping, tu reçois une réponse Telegram oui/non ? Et colle la sortie du rg ... sendMessage ... si non.

zealous iglooBOT
#

Oui, OpenClaw peut t’aider à modifier/optimiser openclaw.json, mais il y a 3 nuances importantes :

1) “Il le fait parfaitement tout seul” → pas garanti

Il peut proposer des changements très corrects, mais :

  • il peut se tromper (surtout sur des configs complexes),
  • et il ne doit pas “inventer” des plugins/modèles.
    Donc : tu le laisses proposer, et toi tu valide/appliques (ou tu lui donnes le droit d’écrire via les commandes ci‑dessous).

2) Il peut écrire la config, mais seulement si tu actives les commandes de config

Il y a deux façons propres de modifier la config :

A) Via le CLI (le plus fiable)

Depuis le serveur :

openclaw config set messages.queue.mode "collect"
openclaw config unset routing.queue
#
openclaw gateway restart

B) Via chat avec /config … (si activé)

Les commandes /config set|unset sont désactivées par défaut.
Pour les activer, ajoute dans openclaw.json :

{
  "commands": {
    "config": true
  }
}

Puis :

#
openclaw gateway restart

Ensuite dans Telegram tu peux faire :

  • /config show
  • /config set agents.defaults.timeoutSeconds 60
  • /config unset routing.queue

(Attention aussi à channels.telegram.configWrites: false si tu l’as mis : ça bloque les écritures config depuis Telegram.)

3) “clawrouter / autres plugins”

Je ne connais pas de plugin officiel nommé clawrouter. Tu veux dire :

  • OpenRouter (provider de modèles) ? → ça se configure dans models/providers + OPENROUTER_API_KEY, pas besoin de plugin.
  • ou tu as vraiment un plugin installé qui s’appelle comme ça ? → montre-moi :
#
openclaw plugins list

Bonus : optimisation automatique “safe”

Pour du durci simple (permissions + réglages safe), tu as :

openclaw security audit --fix
openclaw gateway restart

Si tu me dis ce que tu veux “optimiser” exactement (latence, coût, stabilité, sécurité, routing Qwen→Kimi…), je te donne une checklist + les 3–5 changements config les plus utiles, sans casser ton setup.

#

Ça peut t’aider énormément, mais “parfaitement tout seul” → non garanti.

Ce qu’il faut comprendre :

1) ClawRouter ≠ édition automatique de openclaw.json

D’après tes logs, ClawRouter fonctionne et route bien vers deepseek/deepseek-reasoner.
Mais ça veut surtout dire : au moment d’un run, il choisit un modèle. Ça ne veut pas forcément dire qu’il va réécrire ton fichier de config sur disque.

Pour que le bot modifie réellement openclaw.json, il faut passer par un mécanisme d’écriture de config :

Option A (recommandé) : toi tu appliques via CLI

Le bot te dit quoi changer, et toi tu exécutes :

openclaw config set ...
openclaw config unset ...
openclaw gateway restart
#

Je vois. Ces logs disent surtout 3 choses :

  1. ClawRouter est bien actif
    Il “score” ton message (ici score=0.324…) et extrait des signaux du prompt : long, code, technical, multi-step, etc.

  2. Tu as demandé un modèle "auto"

    Received model: "auto" -> normalized: "auto", isAuto: true
    Donc ce n’est pas toi qui choisis ollama/... ou moonshot/... à la main : tu laisses le routeur décider.

  3. Dans ton cas, ClawRouter choisit deepseek/deepseek-reasoner (model 1/3) et ça marche :

    Success with model: deepseek/deepseek-reasoner

Donc : rien n’est “cassé”. C’est juste que ton routeur envoie tes requêtes vers DeepSeek au lieu de Qwen/Kimi.


Ce que ça implique par rapport à ce que tu voulais

#

Option B : permettre /config set|unset en chat (écrit sur disque)

Ajoute dans openclaw.json :

{
  "commands": { "config": true }
}

Puis restart. Ensuite tu peux faire /config set ... depuis Telegram/Discord (si autorisé).

2) “Optimiser via plugins” : oui, mais tu dois définir l’objectif

Le bot peut optimiser selon un objectif clair, ex :

  • “répondre vite” (timeout court + fallback rapide)
  • “coût minimal” (router vers modèles moins chers)
  • “stabilité” (désactiver certains tools, réduire queue, réduire contexte)
  • “sécurité” (sandbox, deny web/browser, elevated off, etc.)

Sans objectif, il va “optimiser” au hasard.

#

Tu voulais : Qwen local d’abord (60s), puis Kimi si complexe.

Or là, ton setup actuel fait plutôt : Auto → DeepSeek reasoner.

Si tu veux vraiment “Qwen → Kimi”, il faut soit :

  • désactiver ClawRouter (et revenir à agents.defaults.model.primary = "ollama/qwen..." + fallbacks = ["moonshot/kimi..."] + timeoutSeconds=60),
    ou
  • configurer ClawRouter pour que ses “3 modèles” soient (dans l’ordre) : Qwen → Kimi → (optionnel un autre), et avec un timeout/règle de switch.

Je ne peux pas te donner les clés exactes de config ClawRouter sans voir comment il se configure chez toi (sinon je risque d’inventer).


Ce que j’ai besoin que tu colles (2 commandes)

Sur ton serveur :

#

3) Ce que tes logs ClawRouter veulent dire

Tu as :

  • Received model: "auto" -> normalized: "auto", isAuto: true
  • puis il choisit deepseek/deepseek-reasoner

Donc tu utilises probablement un mode “model=auto” et ClawRouter décide derrière. C’est OK.

4) Workflow safe (pour éviter de casser)

  1. Backup avant :
cp ~/.openclaw/openclaw.json ~/.openclaw/openclaw.json.bak.$(date +%s)
  1. Appliquer les changements
  2. Vérifier :
openclaw doctor
#
openclaw plugins list
openclaw config get agents.defaults.model

Et aussi le bloc plugins de ton ~/.openclaw/openclaw.json (juste cette section, sans tokens).

Avec ça, je te dis exactement :

  • comment forcer ClawRouter à router vers moonshot/kimi-k2.5 quand c’est complexe,
  • ou comment revenir au mode Qwen 60s → fallback Kimi sans routeur.
#
openclaw security audit --deep
openclaw status --all

Si tu veux que je te dise “oui tu peux lui faire confiance pour X”, dis-moi juste :

  1. tu veux optimiser quoi (vitesse / coût / stabilité / sécurité) ?
  2. colle le résultat de :
openclaw plugins list

(et si possible le bloc plugins de ton openclaw.json, sans tokens)

#

Oui, OpenClaw peut t’aider à optimiser et modifier openclaw.json, mais il y a 2 conditions + 1 gros piège (que tu touches en plein avec ClawRouter).

1) Est-ce qu’OpenClaw peut modifier openclaw.json “tout seul” ?

Il peut le faire si tu l’autorises, mais ce n’est jamais “parfait garanti”.

Tu as 2 façons propres :

A) Toi tu appliques (le plus fiable)

Le bot te dit quoi changer, et toi tu exécutes :

openclaw config set ...
openclaw config unset ...
openclaw gateway restart

B) Depuis le chat avec /config … (écrit sur disque)

Il faut activer :

#
"commands": { "config": true }

puis openclaw gateway restart.

Ensuite tu peux faire /config set ... dans Telegram.

2) ClawRouter “optimise” quoi exactement ?

ClawRouter ne “répare” pas la config : il choisit un modèle au moment du run (auto routing).
Donc oui, il peut “optimiser” la latence/coût/qualité via routing — MAIS seulement si les providers ciblés acceptent le format de requête qu’il envoie.

3) Ton erreur ClawRouter avec Moonshot/Kimi : c’est un problème de format (pas ta config)

Tu as vu :

  • Non-provider error from moonshot/kimi-k2.5: Invalid request body … invalid_value … values ["system","user","assist…"]

Ça ressemble très fort à : Moonshot n’accepte pas un rôle type developer (il veut system/user/assistant), alors que ClawRouter (ou l’API qu’il utilise) envoie parfois developer.

#

Résultat : DeepSeek marche, Moonshot casse, tant que ClawRouter ne “downgrade” pas le format pour Moonshot.

Ce que tu peux faire maintenant

  1. Voir la vraie erreur complète dans le fichier log (pour confirmer le rôle interdit) :
rg -n "Invalid request body|invalid_value|moonshot/kimi-k2.5" /tmp/openclaw/openclaw-2026-02-09.log | tail -n 50
  1. Me coller :
openclaw plugins list
openclaw plugins info clawrouter

(+ la section plugins de ton openclaw.json, sans tokens)

Avec ça, je te dis exactement :

  • si ClawRouter a une option du style “map developer->system” / “force chat-completions”,
#
  • ou si c’est un bug du plugin (auquel cas la solution propre est : ne pas router Moonshot via ClawRouter, et garder ton fallback OpenClaw ollama -> moonshot).

Solution pratique (si tu veux que ça marche tout de suite)

  • Garde ton failover OpenClaw : ollama/qwen… → fallback moonshot/kimi… (ça on a déjà prouvé que ça marche).
  • Utilise ClawRouter seulement pour les modèles qui acceptent son format (DeepSeek etc.).
  • Et quand tu veux Kimi : /model kimi ou laisse le failover le prendre.

Colle-moi les sorties plugins info clawrouter + le rg … Invalid request body … et on fixe ClawRouter proprement.

#

Ne fais pas ce cp /root/.openclaw/openclaw-fixed-format.json … “les yeux fermés”.

Le message que tu as reçu ressemble à une réponse d’IA qui hallucine un plan d’action (et en plus elle parle de “curl avec ta clé API” → mauvais réflexe, risque de fuite). Et le chemin tail -30 /var/log/openclaw.log est très probablement faux chez toi : tes logs OpenClaw sont plutôt dans :

  • /tmp/openclaw/openclaw-YYYY-MM-DD.log (tu l’as vu dans openclaw gateway status)
  • ou via openclaw logs --follow
  • ou via journalctl --user -u openclaw-gateway.service …

Procédure SAFE (2 minutes)

0) Backup avant toute modif

cp /root/.openclaw/openclaw.json /root/.openclaw/openclaw.json.bak.$(date +%s)

1) Vérifie que le fichier “fixed-format” existe vraiment (et regarde ce qu’il contient)

#
ls -la /root/.openclaw/openclaw-fixed-format.json
head -60 /root/.openclaw/openclaw-fixed-format.json

(Ne poste pas les tokens.)

2) Compare avec ta config actuelle

diff -u /root/.openclaw/openclaw.json /root/.openclaw/openclaw-fixed-format.json | head -200

3) Si tu veux vraiment l’appliquer, fais-le ensuite + redémarre

cp /root/.openclaw/openclaw-fixed-format.json /root/.openclaw/openclaw.json
openclaw gateway restart
openclaw status --all
#

À propos de ton erreur Moonshot/Kimi avec ClawRouter

Le log que tu avais (Invalid request body … invalid_value … ["system","user","assist…"]) indique presque sûrement un problème de format côté ClawRouter/plugin (rôles/messages), pas un simple champ dans openclaw.json.

Donc la prochaine étape utile c’est de me montrer :

openclaw plugins list
openclaw plugins info clawrouter

Et pour voir l’erreur complète :

openclaw logs --limit 300 | rg -n "ClawRouter|moonshot|kimi|Invalid request body|invalid_value" | tail -n 80

Colle ces sorties (en masquant les clés), et je te dirai exactement si :

  • il faut configurer ClawRouter pour Moonshot,
  • ou juste empêcher ClawRouter de router vers Moonshot (et garder Moonshot uniquement comme fallback OpenClaw, ce qui marchait chez toi).