Back to blog
OpenClaw Troubleshooting: 'No Reply from Agent,' WORKFLOW_AUTO.md, and Silent Delivery Failures

OpenClaw Troubleshooting: 'No Reply from Agent,' WORKFLOW_AUTO.md, and Silent Delivery Failures

February 25, 2026By Alex Rezvov

After deploying OpenClaw and documenting 16 incidents in one day, I kept getting questions about specific errors. This post collects the fixes in one place. No narrative, just diagnostics.

"No reply from agent"

Symptom

The announce agent completes in under one second (typically 500-600ms) and returns an empty response. Logs show:

[announce] completed in 557ms
[announce] result: no reply from agent

The cron job runs, the summary field exists, but nothing reaches Telegram.

Root cause

The announce agent is a separate LLM call that receives the cron job's summary as input. When that summary is empty or contains only a preamble ("Let me execute the digest task..."), the announce model has nothing to forward. It finishes instantly because there's no real work to do.

The problem is upstream. The cron agent produced garbage output, and the announce agent correctly identified it as not worth sending.

Why the cron agent produces empty output

In most cases: thinking mode. OpenClaw auto-enables thinking for models that support it. With thinking: low, the model performs all its work inside the <thinking> block. RSS scanning, article filtering, summary generation, formatting: all internal. The text response comes back empty or with a fragment like "I'll start by checking the feeds..."

OpenClaw captures only the text response as the cron summary. The thinking block is discarded.

Fix

Disable thinking for cron jobs. In your OpenClaw config:

{
  "agents": {
    "defaults": {
      "heartbeat": {
        "model": "deepseek/deepseek-chat",
        "thinking": "off"
      }
    }
  }
}

The key setting is "thinking": "off". Not "low." Not "minimal." Off.

With thinking enabled, my cron jobs averaged 88 seconds and produced zero deliverable output across five test runs. With thinking off, the same job ran in 30 seconds and delivered six articles to Telegram on the first attempt.

Verification

After the fix, the announce agent should run for 5-15 seconds (actual LLM inference time) instead of <1 second. Check your logs:

[announce] completed in 7200ms    ← working
[announce] completed in 557ms     ← still broken, check summary content

WORKFLOW_AUTO.md phantom file

Symptom

Every 15 minutes, the heartbeat agent tries to read a file called WORKFLOW_AUTO.md. The file doesn't exist. Logs show repeated ENOENT errors:

[heartbeat] tool_call: read_file("WORKFLOW_AUTO.md")
[heartbeat] error: ENOENT: no such file or directory

Worse: the agent leaks its internal control tokens to Telegram. Users receive messages containing raw markup like <|tool▁calls▁begin|> and <|tool▁calls▁end|>.

Root cause

This is a DeepSeek hallucination. After several heartbeat cycles, the model starts "remembering" a workflow file that was never part of the workspace. The hallucination is persistent: once it appears, it recurs every heartbeat cycle because the model's context accumulates previous failed attempts, reinforcing the false belief that the file should exist.

The control token leak happens because OpenClaw doesn't strip model-native tokens before delivering messages. DeepSeek uses custom delimiters (<|tool▁calls▁begin|>) that differ from OpenAI-style function calling. When the model's reasoning spills into the text response, those tokens pass through to Telegram unfiltered.

Fix

Two changes are needed.

1. Use isolated sessions for heartbeat/cron.

{
  "agents": {
    "defaults": {
      "heartbeat": {
        "session": "isolated"
      }
    }
  }
}

Isolated sessions prevent context accumulation across heartbeat cycles. Each run starts fresh, so the hallucination can't compound.

2. Add explicit file constraints in SOUL.md.

## File Access Rules

Only read files that exist in the workspace root:
- HEARTBEAT.md
- SOUL.md

Do not attempt to read any other files. If a file is not listed above,
it does not exist. Do not guess filenames.

This doesn't guarantee the model won't hallucinate (no prompt does), but it reduces the frequency by giving it a concrete, short whitelist to follow.

If you already have the problem

Kill the OpenClaw process and restart with --session isolated. The accumulated context causing the loop lives in the session state. A fresh start clears it.

Cron job says "delivered: true" but Telegram is empty

Symptom

The cron job completes. Status shows delivered: true. Nothing arrives in Telegram. The system reports success for an operation that produced zero output.

{
  "status": "completed",
  "delivered": true,
  "summary": ""
}

Root cause

delivered: true means "the announce agent ran without throwing an error." It does not mean "a message was sent to Telegram." An announce agent that receives an empty summary, decides there's nothing to send, and exits cleanly is marked as delivered.

This is the same upstream issue as "no reply from agent." The delivery status reflects process completion, not message arrival.

Diagnosis

Check the cron job's summary field in logs (DEBUG level):

grep -A5 "cron.*summary" ~/.openclaw/logs/agent.log

If the summary is empty or contains only a preamble, the cron agent's thinking mode is eating your output. See the fix in the "No reply from agent" section above.

If the summary contains actual content but Telegram still receives nothing, the announce agent model may be too small to process it. The announce model is hardcoded to the primary default model. You cannot override it with agents.defaults.announce.model (that key is silently ignored). If your primary model is a small one (Mistral Small, Phi-3, etc.), it may not produce useful announce output from a long summary.

Fix

  1. Disable thinking mode on the cron agent (see above).
  2. Set a capable primary model or accept that the announce agent inherits it. If you use a small model for chat, you'll need to make the heartbeat model your primary and use a routing rule for chat instead.
  3. Don't trust the status. Verify delivery in Telegram after every config change. The only reliable delivery confirmation is the message appearing in the chat.

Dual-model configuration

Most of these problems share a root cause: using a single small model for everything. OpenClaw routes chat, heartbeat, cron, and announce through the same model by default. A model that's fine for chat will fail at scheduled tasks.

Minimum viable setup:

Agent Model Why
Chat Small (Mistral Small 3.2, 24B) Fast replies, low cost
Heartbeat / Cron Large (DeepSeek Chat v3.1, 685B MoE) Needs to follow multi-step tool pipelines
Announce Inherited from primary default Cannot be configured independently

Config:

{
  "model": "mistralai/mistral-small-3.2",
  "agents": {
    "defaults": {
      "heartbeat": {
        "model": "deepseek/deepseek-chat",
        "thinking": "off",
        "session": "isolated"
      }
    }
  }
}

Cost on OpenRouter for a daily digest: ~$0.03/day. The 24-hour deployment that produced 16 incidents cost $1.50 total, most of it from a retry loop on the small model.

Quick reference

Problem Cause Fix
"No reply from agent" Thinking mode eats cron output "thinking": "off"
WORKFLOW_AUTO.md loop DeepSeek hallucination + context accumulation "session": "isolated" + SOUL.md whitelist
delivered: true, nothing sent Status tracks process, not delivery Fix upstream (thinking off) + verify in Telegram
Control tokens in Telegram Model-native tokens not stripped Switch to isolated sessions, add SOUL.md constraints
271 spam messages No retry limits + small model in failure loop Use large model for cron + set API budget cap
Cron doesn't fire on schedule Small model can't compare timestamps Use large model for heartbeat

All issues documented with full incident logs in Deploying OpenClaw: 16 Incidents, One Day, $1.50.

Comments