OpenClaw handles inbound messages through a pipeline of session resolution, queueing, streaming, tool execution, and reasoning visibility. This page maps the path from inbound message to reply.Documentation Index
Fetch the complete documentation index at: https://docs2.openclaw.ai/llms.txt
Use this file to discover all available pages before exploring further.
Message flow (high level)
messages.*for prefixes, queueing, and group behavior.agents.defaults.*for block streaming and chunking defaults.- Channel overrides (
channels.whatsapp.*,channels.telegram.*, etc.) for caps and streaming toggles.
Inbound dedupe
Channels can redeliver the same message after reconnects. OpenClaw keeps a short-lived cache keyed by channel/account/peer/session/message id so duplicate deliveries do not trigger another agent run.Inbound debouncing
Rapid consecutive messages from the same sender can be batched into a single agent turn viamessages.inbound. Debouncing is scoped per channel + conversation
and uses the most recent message for reply threading/IDs.
Config (global default + per-channel overrides):
- Debounce applies to text-only messages; media/attachments flush immediately.
- Control commands bypass debouncing so they remain standalone. Channels that explicitly opt in to same-sender DM coalescing can keep DM commands inside the debounce window so a split-send payload can join the same agent turn.
Sessions and devices
Sessions are owned by the gateway, not by clients.- Direct chats collapse into the agent main session key.
- Groups/channels get their own session keys.
- The session store and transcripts live on the gateway host.
Tool result metadata
Tool resultcontent is the model-visible result. Tool result details is
runtime metadata for UI rendering, diagnostics, media delivery, and plugins.
OpenClaw keeps that boundary explicit:
toolResult.detailsis stripped before provider replay and compaction input.- Persisted session transcripts keep only bounded
details; oversized metadata is replaced with a compact summary markedpersistedDetailsTruncated: true. - Plugins and tools should put text the model must read in
content, not only indetails.
Inbound bodies and history context
OpenClaw separates the prompt body from the command body:BodyForAgent: primary model-facing text for the current message. Channel plugins should keep this focused on the sender’s current prompt-bearing text.Body: legacy prompt fallback. This may include channel envelopes and optional history wrappers, but current channels should not rely on it as the primary model input whenBodyForAgentis available.CommandBody: raw user text for directive/command parsing.RawBody: legacy alias forCommandBody(kept for compatibility).
[Chat messages since your last reply - for context][Current message - respond to this]
CommandBody (or
RawBody) to the original message text and keep Body as the combined prompt.
Structured history, reply, forwarded, and channel metadata are rendered as
user-role untrusted context blocks during prompt assembly.
History buffers are configurable via messages.groupChat.historyLimit (global
default) and per-channel overrides like channels.slack.historyLimit or
channels.telegram.accounts.<id>.historyLimit (set 0 to disable).
Queueing and followups
If a run is already active, inbound messages are steered into the current run by default.messages.queue selects whether active-run messages steer, queue for
later, collect into one later turn, or interrupt the active run.
- Configure via
messages.queue(andmessages.queue.byChannel). - Default mode is
steer, with a 500ms debounce for Codex steering batches and followup/collect queues. - Modes:
steer,followup,collect, andinterrupt.
Channel run ownership
Channel plugins may preserve ordering, debounce input, and apply transport backpressure before a message enters the session queue. They should not impose a separate timeout around the agent turn itself. Once a message is routed to a session, long-running work is governed by the session, tool, and runtime lifecycle so all channels report and recover from slow turns consistently.Streaming, chunking, and batching
Block streaming sends partial replies as the model produces text blocks. Chunking respects channel text limits and avoids splitting fenced code. Key settings:agents.defaults.blockStreamingDefault(on|off, default off)agents.defaults.blockStreamingBreak(text_end|message_end)agents.defaults.blockStreamingChunk(minChars|maxChars|breakPreference)agents.defaults.blockStreamingCoalesce(idle-based batching)agents.defaults.humanDelay(human-like pause between block replies)- Channel overrides:
*.blockStreamingand*.blockStreamingCoalesce(non-Telegram channels require explicit*.blockStreaming: true)
Reasoning visibility and tokens
OpenClaw can expose or hide model reasoning:/reasoning on|off|streamcontrols visibility.- Reasoning content still counts toward token usage when produced by the model.
- Telegram supports reasoning stream into a transient draft bubble that is deleted after final delivery; use
/reasoning onfor persistent reasoning output.
Prefixes, threading, and replies
Outbound message formatting is centralized inmessages:
messages.responsePrefix,channels.<channel>.responsePrefix, andchannels.<channel>.accounts.<id>.responsePrefix(outbound prefix cascade), pluschannels.whatsapp.messagePrefix(WhatsApp inbound prefix)- Reply threading via
replyToModeand per-channel defaults
Silent replies
The exact silent tokenNO_REPLY / no_reply means “do not deliver a user-visible reply”.
When a turn also has pending tool media, such as generated TTS audio, OpenClaw
strips the silent text but still delivers the media attachment.
OpenClaw resolves that behavior by conversation type:
- Direct conversations never receive
NO_REPLYprompt guidance. If a direct run accidentally returns a bare silent token, OpenClaw suppresses it instead of rewriting or delivering it. - Groups/channels allow silence by default only for automatic group replies.
In
message_toolvisible-reply mode, silence means the model does not callmessage(action=send). - Internal orchestration allows silence by default.
/verbose full is enabled.
Defaults live under agents.defaults.silentReply; surfaces.<id>.silentReply
can override group/internal policy per surface.
Bare silent replies are dropped on all surfaces, so parent sessions stay quiet
instead of rewriting sentinel text into fallback chatter.
Related
- Message lifecycle refactor - target durable send and receive design
- Streaming — real-time message delivery
- Retry — message delivery retry behavior
- Queue — message processing queue
- Channels — messaging platform integrations