Akshay Parkhi's Weblog

Subscribe

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

ComponentRole
Openclaw DaemonMain process running on the server, manages everything
Gateway (port 18789)Local HTTP API for internal communication
Telegram ChannelPolls Telegram servers for messages, sends responses back via Bot API
Agent (main)Your direct chat session, maintains conversation history
Cron SchedulerTriggers 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 QueueRoutes cron job outputs to Telegram
WorkspaceBot’s “soul”, memory, personality files, and project data
Heartbeat PollerPeriodic background check-ins for proactive tasks

Key Takeaways

  1. One agent, many sessions — Cron jobs don’t create separate agents, they create separate sessions under the same agent
  2. “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
  3. 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
  4. Main session is different — Your Telegram DM conversation is persistent, accumulates history, and is shared with heartbeat. Cron sessions are throwaway
  5. 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)

This is OpenClaw / ClawdBot Architecture — How a Telegram AI Bot Actually Works by Akshay Parkhi, posted on 8th March 2026.

Next: OpenClaw vs Claude Code Agent Teams — Architecture Comparison

Previous: Agentic Engineering Patterns — Key Takeaways from Simon Willison's Guide