DEV Community
Grade 10
6h ago
Coding Agents over Telegram, Part 2: From Zero to an Agent That Answers
This is the one post in the series you do , not just read. By the end you'll have a single Telegram topic where you type a message and a coding agent answers and drives a tmux pane on your own box. That's the entire goal, nothing more. Memory, monitors, tool servers, and the supervisor all come later; none of them are needed to get an agent answering you. Budget ~30–45 minutes. If you only do one thing, do the Fast path, then prove it with the readiness gate. Everything below the gate is manual explanation and debugging you can skip until you need it. Prerequisites (where solo setups die) The Telegram wiring is the mechanical part; the real failures hide in local state. Confirm every line before you start: A box you control with tmux , and shell access that survives disconnects (you'll leave a gateway running). A coding agent already working in a tmux pane (opencode, Codex, or Claude Code) that you can drive by hand right now . If it isn't installed and authenticated yet, stop and fix that first; OpenClaw drives it, it doesn't replace it. A known, stable pane target for that agent (for example, mybox:1.1 ). Write it down; you'll hard-code it into the agent's instructions. Your agent's launch command : the exact command (or wrapper script) that starts the coding agent in the pane, including how it resumes a session. OpenClaw's restart flow needs this verbatim. The OpenClaw runtime , pinned (see the matrix below). Wrong Node version is the single most common silent failure. A Telegram account and the Telegram app on your phone. Version matrix Pin these. "It runs on Node" is not enough; the gateway is sensitive to the runtime. Component Pinned version Notes Node.js 24.11.1 The gateway is built against Node 24; newer majors can fail the native build. Package manager pnpm 11.2.2 OpenClaw's packageManager field. corepack fetches it for you. OpenClaw github.com/openclaw/openclaw , pinned commit (tested on 2026.5.27 ) Pin a commit or tag; don't track main for a setup everyone must reproduce. Coding agent opencode, installed and authenticated Pin the version your team standardizes on. Node manager nvm This guide assumes nvm; adapt the commands if you use asdf or system Node. Fast path Two scripts do the whole local setup. Grab them from the gist, then run them around the Telegram steps: # Download the bootstrap + readiness scripts curl -fsSL "https://gist.githubusercontent.com/jerilkuriakose/cd0f8353aac74e47c591111b758943e9/raw/setup-openclaw.sh" -o setup-openclaw.sh curl -fsSL "https://gist.githubusercontent.com/jerilkuriakose/7cf94af3e96526f9f14d0c28b6c26b69/raw/ready-check.sh" -o ready-check.sh chmod +x setup-openclaw.sh ready-check.sh # 1. Pin the runtime, fetch + build OpenClaw, and launch the gateway. #Pass your bot token to also write a minimal config in one shot: OPENCLAW_BOT_TOKEN = "<BOT_TOKEN>" OPENCLAW_BOT_ACCOUNT = "my-bot" ./setup-openclaw.sh # 2. Do the Telegram steps in "Telegram side" below (BotFather + group + topic), #then add the allowlist + topic route from "Wire them together". # 3. Prove it works: AGENT_ID = my-agent PANE = mybox:1.1 ./ready-check.sh setup-openclaw.sh pins Node 24.11.1 and pnpm 11.2.2 (via nvm and corepack), clones and builds github.com/openclaw/openclaw , and launches the gateway. ready-check.sh runs the readiness gate for you. Prefer to understand each step, or hit a snag? Follow the manual path. Manual path Three parts: the Telegram side, the box side, then wiring them together. Telegram side You must be the group's creator , so do these from your own Telegram account: Create a bot. Message @BotFather → /newbot → name it → save the bot token it gives you. Treat the token like a password (see Secrets). Create a group , give it a name, and add your bot to it. Promote the bot to admin (Group → Edit → Administrators). This is required : Telegram's privacy mode hides normal group messages from non-admin bots, so without this the bot never sees what you type. Turn Topics on (Group → Edit → Topics). This converts the group to a forum supergroup. Create your first topic and name it for the project the agent will drive (for example, project-a ). Send one message in that topic (anything). This makes the group and topic show up in the gateway log so you can grab their IDs. You also need your own numeric Telegram user ID for the allowlist. Easiest: message @userinfobot and it replies with your ID. (Alternatively, it appears in the gateway log as the sender once messages start flowing in the next step.) Box side: minimal config, then start the gateway The gateway has to know about your bot before it can poll Telegram, so write a minimal valid config first. Create ~/.openclaw/openclaw.json with just the bot account. Use strict JSON (no comments, no trailing commas) because that's exactly what the gateway parses and what you'll validate against: { "channels" : { "telegram" : { "enabled" : true , "accounts" : { "<your-bot-account>" : { "botToken" : "<BOT_TOKEN>" } } } } } Lock it down and
This is the one post in the series you do, not just read. By the end you'll have a single Telegram topic where you type a message and a coding agent answers and drives a tmux pane on your own box. That's the entire goal, nothing more. Memory, monitors, tool servers, and the supervisor all come later; none of them are needed to get an agent answering you. Budget ~30–45 minutes. If you only do one thing, do the Fast path, then prove it with the readiness gate. Everything below the gate is manual explanation and debugging you can skip until you need it. Prerequisites (where solo setups die) The Telegram wiring is the mechanical part; the real failures hide in local state. Confirm every line before you start: - A box you control with tmux , and shell access that survives disconnects (you'll leave a gateway running). - A coding agent already working in a tmux pane (opencode, Codex, or Claude Code) that you can drive by hand right now. If it isn't installed and authenticated yet, stop and fix that first; OpenClaw drives it, it doesn't replace it. - A known, stable pane target for that agent (for example, mybox:1.1 ). Write it down; you'll hard-code it into the agent's instructions. - Your agent's launch command: the exact command (or wrapper script) that starts the coding agent in the pane, including how it resumes a session. OpenClaw's restart flow needs this verbatim. - The OpenClaw runtime, pinned (see the matrix below). Wrong Node version is the single most common silent failure. - A Telegram account and the Telegram app on your phone. Version matrix Pin these. "It runs on Node" is not enough; the gateway is sensitive to the runtime. | Component | Pinned version | Notes | |---|---|---| | Node.js | 24.11.1 | The gateway is built against Node 24; newer majors can fail the native build. | | Package manager | pnpm 11.2.2 | OpenClaw's packageManager field. corepack fetches it for you. | | OpenClaw | github.com/openclaw/openclaw , pinned commit (tested on 2026.5.27 ) | Pin a commit or tag; don't track main for a setup everyone must reproduce. | | Coding agent | opencode, installed and authenticated | Pin the version your team standardizes on. | | Node manager | nvm | This guide assumes nvm; adapt the commands if you use asdf or system Node. | Fast path Two scripts do the whole local setup. Grab them from the gist, then run them around the Telegram steps: # Download the bootstrap + readiness scripts curl -fsSL "https://gist.githubusercontent.com/jerilkuriakose/cd0f8353aac74e47c591111b758943e9/raw/setup-openclaw.sh" -o setup-openclaw.sh curl -fsSL "https://gist.githubusercontent.com/jerilkuriakose/7cf94af3e96526f9f14d0c28b6c26b69/raw/ready-check.sh" -o ready-check.sh chmod +x setup-openclaw.sh ready-check.sh # 1. Pin the runtime, fetch + build OpenClaw, and launch the gateway. # Pass your bot token to also write a minimal config in one shot: OPENCLAW_BOT_TOKEN=" " OPENCLAW_BOT_ACCOUNT="my-bot" ./setup-openclaw.sh # 2. Do the Telegram steps in "Telegram side" below (BotFather + group + topic), # then add the allowlist + topic route from "Wire them together". # 3. Prove it works: AGENT_ID=my-agent PANE=mybox:1.1 ./ready-check.sh setup-openclaw.sh pins Node 24.11.1 and pnpm 11.2.2 (via nvm and corepack), clones and builds github.com/openclaw/openclaw , and launches the gateway. ready-check.sh runs the readiness gate for you. Prefer to understand each step, or hit a snag? Follow the manual path. Manual path Three parts: the Telegram side, the box side, then wiring them together. Telegram side You must be the group's creator, so do these from your own Telegram account: - Create a bot. Message @BotFather →/newbot → name it → save the bot token it gives you. Treat the token like a password (see Secrets). - Create a group, give it a name, and add your bot to it. - Promote the bot to admin (Group → Edit → Administrators). This is required: Telegram's privacy mode hides normal group messages from non-admin bots, so without this the bot never sees what you type. - Turn Topics on (Group → Edit → Topics). This converts the group to a forum supergroup. - Create your first topic and name it for the project the agent will drive (for example, project-a ). - Send one message in that topic (anything). This makes the group and topic show up in the gateway log so you can grab their IDs. You also need your own numeric Telegram user ID for the allowlist. Easiest: message @userinfobot and it replies with your ID. (Alternatively, it appears in the gateway log as the sender once messages start flowing in the next step.) Box side: minimal config, then start the gateway The gateway has to know about your bot before it can poll Telegram, so write a minimal valid config first. Create ~/.openclaw/openclaw.json with just the bot account. Use strict JSON (no comments, no trailing commas) because that's exactly what the gateway parses and what you'll validate against: { "channels": { "telegram": { "enabled": true, "accounts": { " ": { "botToken": " " } } } } } Lock it down and validate before launching: chmod 600 ~/.openclaw/openclaw.json python3 -c "import json; json.load(open('$HOME/.openclaw/openclaw.json')); print('JSON OK')" Get OpenClaw and build it. It's open source. Pin the runtime, clone, install with the corepack -provided pnpm, and build: nvm install 24.11.1 && nvm use 24.11.1 corepack enable && corepack prepare pnpm@11.2.2 --activate git clone https://github.com/openclaw/openclaw.git ~/repos/openclaw cd ~/repos/openclaw # Optional: pin a tested commit/tag for reproducibility (tested on 2026.5.27) # git checkout pnpm install pnpm build # takes a few minutes Now launch the gateway in its own tmux session so it survives your disconnect: pnpm gateway:watch # launches the gateway and manages its own tmux session Find your log path (it differs by config), then confirm the gateway came up and the bot is polling: # If logging.file is set, use ~/.openclaw/logs/openclaw.log. Otherwise the dated default: ls -t /tmp/openclaw/openclaw-*.log | tail -1 # default location grep -a 'gateway ready' | tail -1 # expect a recent line The log directory is locked down ( 0700 ), so read it from the shell, not an editor's file browser. This initial launch, and any laterlogging orplugins.load change, needs a gateway (re)start. The group/topic/routing edits in the next section hot-reload, no restart needed. Wire them together Config lives in ~/.openclaw/openclaw.json . The gateway hot-reloads routing/topic/channel edits; no restart needed for these. We do this in two phases because you need the chat and topic IDs from the log, and the only way to make them appear is to let messages through first. Phase 1: find the chat ID and open the group temporarily. With the gateway now polling, send a message in your topic. It gets blocked (the group isn't configured yet), which conveniently logs the chat ID: grep -a 'not-allowed' | tail -1 # → {"chatId": ,"title":" ","reason":"not-allowed"} Add a groups block to your account so messages flow and topic IDs get logged. This is a fragment; merge the groups key into the account you already created, keeping the file strict JSON: "groups": { " ": { "groupPolicy": "open", "requireMention": false } } Save. The gateway hot-reloads (no restart). Keep the open window tiny. groupPolicy: "open" lets anyone in the group drive a shell-capable agent. The group must be private with only you in it, and this is a momentary bootstrap step: switch toallowlist (Phase 2) as soon as you've harvested the topic IDs, before adding anyone else or doing real work. Phase 1b: harvest topic thread IDs. Send a message in each topic (label them by text so you can tell them apart, since topic IDs are not sequential by creation order), then: grep -ao 'Inbound message telegram:group[^"]*' | sort -u # → ...:topic: Phase 2: lock it down and route the topic to an agent. Now switch the group to an allowlist (owner-only), add yourself, map the topic to an agent, and declare that agent. Strict JSON, merged into your config: "channels": { "telegram": { "enabled": true, "accounts": { " ": { "botToken": " ", "groups": { " ": { "groupPolicy": "allowlist", "allowFrom": [" "], "requireMention": false, "topics": { " ": { "agentId": " " } } } } } } } }, "agents": { "list": [ { "id": " ", "workspace": "~/.openclaw/workspace- ", "agentDir": "~/.openclaw/agents/ " } ] } requireMention: false lets you type naturally instead of prefixing every message with an @mention . allowFrom with only your user ID is what stops anyone else in the group from driving a shell-capable agent. It's your numeric Telegram ID, kept as a quoted string as the config expects (for example, ["123456789"] ). Give the agent its instructions. This is the step that makes status , send , and restart work; the agent's behavior comes entirely from the files in its workspace . Create the workspace directory first (the agentDir must be unique per agent; the gateway creates it on first run): mkdir -p ~/.openclaw/workspace- Then put this in ~/.openclaw/workspace- /AGENTS.md , a minimal command contract: # You are bound to tmux pane ` `, an interactive coding-agent session. ## Hard rules - ALL tmux operations target ` `. Never touch any other session. - Read with `tmux capture-pane -t -p`; write with `tmux send-keys -t ...`. - Strip ANSI codes before relaying pane output to Telegram. - After send-keys, wait a few seconds before re-capturing; replies aren't instant. - Confirm before any destructive action EXCEPT the explicit "restart" command below. ## Common phrasings → actions | User says | You do | |---|---| | "status" / "what's in tmux?" | capture ` `, strip ANSI, summarize the last ~60 lines | | "send ` `" | `send-keys -t -l -- " "`, then Enter, wait, capture | | "compact" / "new session" | send `/compact` or `/new` to the pane | | "interrupt" / "stop it" | confirm, then send `C-c` | | "restart" | run the restart sequence below (no confirmation) | ## Decision / option routing You are a relay, not the owner of the wor
Comments
No comments yet. Start the discussion.