OpenClaw / ClawdBot Architecture — How a Telegram AI Bot Actually Works
8th March 2026
OpenClaw (ClawdBot) is a Telegram bot powered by Claude Opus that delivers daily AI news digests, runs scheduled jobs, and maintains persistent conversations. Here’s the full architecture — how every piece connects.
High-Level Architecture
YOU (Phone/Desktop)
|
v
+--------------+ Telegram Bot API +----------------------+
| | <-------------------------------> | |
| TELEGRAM | Bot Token: 8641... | OPENCLAW DAEMON |
| SERVERS | Polls for updates | (Main Process) |
| | Sends responses | |
+--------------+ | +----------------+ |
| | GATEWAY | |
| | (port 18789) | |
| +-------+--------+ |
+---------+------------+
|
+---------------------------------+--------------+
| | |
v v v
+-----------------+ +------------------+ +-----------+
| AGENT (main) | | CRON SCHEDULER | | HEARTBEAT |
| | | (0 7 * * * ET) | | POLLER |
| Telegram DM | | | | |
+--------+--------+ +--------+---------+ +-----------+
| |
| | Spawns isolated sessions
v v
+------------------------------------------------------+
| LLM (Claude Opus) |
| |
| Available Tools: |
| +------------+ +------------+ +------------------+ |
| | web_search | | web_fetch | | read/write/exec | |
| | (Brave API)| | (fetch URL)| | (filesystem/bash)| |
| +------------+ +------------+ +------------------+ |
+------------------------------------------------------+
|
v
+------------------------------------------+
| DELIVERY SYSTEM |
| |
| delivery-queue/ ---> Telegram channel |
| |
| mode: "announce" = send to chat ID |
| channel: "telegram" |
| to: "8559341998" (your chat ID) |
+------------------------------------------+
The Session Model: Main vs Cron
This is the most important concept to understand. There is one agent (“main”), but it runs in many sessions.
Main Session (Persistent)
- Your Telegram DM conversation
- Maintains full chat history across messages
- Shared with heartbeat poller
- History accumulates and gets compacted when large
- Remembers context from previous conversations
Cron Sessions (Isolated, Throwaway)
- Each scheduled job run creates a brand new session with a unique UUID
- Fresh context window — zero chat history
- Only sees: system prompt (SOUL.md, AGENTS.md, etc.) + the one message from jobs.json
- One-shot: prompt in → response out → deliver → done
- Today’s AI news run has NO idea what yesterday’s run produced
MAIN SESSION CRON SESSION
+-------------------------+ +-------------------------+
| System: SOUL.md etc. | | System: SOUL.md etc. |
| User: "hey whats up" | | User: "Create digest.." |
| Asst: "not much, u?" | | Asst: (response) |
| User: "check schedule" | | |
| Asst: "here it is..." | | <-- THAT'S IT. ONE TURN.|
| User: "fix the prompts" | +-------------------------+
| Asst: "done..." |
| (compacted when large) | Next run = completely new
+-------------------------+ session, new UUID, fresh
context window, no memory
PERSISTENT - remembers context of previous runs
SHARED - TG msgs + heartbeats
GROWS - history accumulates
Session Key Anatomy
cron-main-30288e86-f628eeb9
| | | |
type name job ID unique run ID
(which (NEW every execution)
cron)
Each run = new UUID = new session = new context window
Example - daily-ai-news ran 4 times, each was a fresh session:
Run 1: session f628eeb9 (said "no tools available")
Run 2: session 8bb085c5 (hallucinated tool_call XML)
Run 3: session 4aa0f35e (generated clean digest from memory)
Run 4: session 5683d110 (hallucinated fake URLs)
None of these sessions knew about each other!
Cron Job Flow
7:00 AM ET daily
|
v
+-------------+ +-------------+ +-------------+ +------------+
| daily-ai | |daily-phys- | |daily-heart- | | gajanan- |
| news | |ai-news | |health-news | | granth |
+------+------+ +------+------+ +------+------+ +------+-----+
v v v v
+------------------------------------------------------------------+
| ISOLATED SESSION (fresh, no history) |
| |
| 1. Receives prompt from jobs.json "message" field |
| 2. Claude generates response (SHOULD use web_search tool, |
| but currently just generates from training knowledge) |
| 3. Response captured as "summary" |
| 4. Run logged to cron/runs/<job-id>.jsonl |
+------------------------------+-----------------------------------+
v
+-----------------+
| DELIVERY QUEUE |
| |
| mode: announce |
| channel: tg |
| to: 8559341998 |
+--------+--------+
v
+-----------------+
| YOUR TELEGRAM | <-- You see the digest here
+-----------------+
The Tool Bug
EXPECTED: WHAT ACTUALLY HAPPENED:
Prompt --> Claude --> web_search Prompt --> Claude --> prints
(tool call) | "<tool_call>..." as
v plain text (never
Brave Search API executed!)
| |
v v
Real results Hallucinated results
| + fake URLs
v + raw XML garbage
Clean digest |
| v
v Messy output --> Telegram
Telegram
FIX APPLIED: Prompts now say "don't use tools, don't include URLs"
File Structure
.openclaw/
|-- openclaw.json ----------- Master config (tools, channels, auth)
|-- credentials/ ------------ API keys (Anthropic)
|-- agents/
| +-- main/
| |-- config.json ----- Agent config (model, system prompt refs)
| +-- sessions/ ------- Session transcripts
|-- cron/
| |-- jobs.json ----------- 4 scheduled jobs (AI news, Physical AI,
| | Heart Health, Granth)
| +-- runs/ --------------- Run logs per job (status, summary, etc.)
|-- workspace/
| |-- SOUL.md ------------- Bot personality & values
| |-- AGENTS.md ----------- Operating manual (how to behave)
| |-- USER.md ------------- Info about you
| |-- IDENTITY.md --------- Bot name/vibe/emoji
| +-- projects/
| +-- gajanan-granth/ - Granth chapters (adhyay_01..21.txt)
|-- telegram/ --------------- Telegram polling state
|-- devices/ ---------------- Paired devices
|-- delivery-queue/ --------- Outbound message queue
+-- identity/ --------------- Device auth & identity
Key Components Summary
| Component | Role |
|---|---|
| Openclaw Daemon | Main process running on the server, manages everything |
| Gateway (port 18789) | Local HTTP API for internal communication |
| Telegram Channel | Polls Telegram servers for messages, sends responses back via Bot API |
| Agent (main) | Your direct chat session, maintains conversation history |
| Cron Scheduler | Triggers jobs on schedule, spawns isolated sessions |
| LLM (Claude Opus) | The brain, called via Anthropic API with tools (web_search, web_fetch, read/write/exec) |
| Delivery Queue | Routes cron job outputs to Telegram |
| Workspace | Bot’s “soul”, memory, personality files, and project data |
| Heartbeat Poller | Periodic background check-ins for proactive tasks |
Key Takeaways
- One agent, many sessions — Cron jobs don’t create separate agents, they create separate sessions under the same agent
- “Isolated” = blank slate — Each cron run gets a brand new session with a unique UUID, fresh context window, zero chat history. It only sees the system prompt + the one message from jobs.json
- Sessions don’t persist between runs — Today’s AI news run has NO idea what yesterday’s run produced. Each is a one-shot: prompt in → response out → deliver → done
- Main session is different — Your Telegram DM conversation is persistent, accumulates history, and is shared with heartbeat. Cron sessions are throwaway
- All sessions share the same tools config — web_search, web_fetch, read, write, exec are available to all, but isolated sessions have trouble actually invoking them properly (hence the bug)
More recent articles
- OpenUSD: Advanced Patterns and Common Gotchas. - 28th March 2026
- OpenUSD Mastery: From Composition to Pipeline — A SO-101 Arm Journey - 25th March 2026
- Learning OpenUSD — From Curious Questions to Real Understanding - 19th March 2026