Envoy Connect — Link Any Claude Code Agent to a Telegram Chat
Connect a Telegram bot to any Claude Code agent, enabling collaborative group chats where multiple people interact with an AI agent that has full access to the project.
Concept
A single Telegram bot serves as a universal gateway to your agent system:
- Agent Mode: Any chat (group or private) can be linked to a Claude Code agent running in a specific project directory, with a per-chat allow list controlling who can interact.
- Envoy Mode (optional): Outbound agenda-driven conversations with external contacts via deep links.
Both modes coexist on the same bot.
Prerequisites
Before running this skill, ensure the user has:
- A Telegram bot created via @BotFather with its token stored in an env file
- An org/project directory with Claude Code agent definitions in
.claude/agents/ - Claude Code CLI (
claude) installed and available in PATH - tmux installed (
brew install tmuxor equivalent) - Python packages:
python-telegram-bot,anthropic,python-dotenv
Setup
Step 1: Check if the Envoy bot infrastructure exists
Look for the bot script and send script. The bot needs two components:
- Bot script — long-running process that receives Telegram messages and routes them to Claude Code agent sessions via tmux
- Send script — small CLI that agents use to reply back to Telegram chats
Check for these in the project's .bin/ or scripts directory. If they don't exist, create them using the architecture below.
Step 2: Check environment configuration
The bot needs these environment variables (typically in ~/.config/telegram/.env or project-level .env):
BOT_TOKEN=<telegram bot token from BotFather>
OWNER_TELEGRAM_ID=<admin user's Telegram ID>
To find a Telegram user ID:
- Ask the person to message
@userinfobot— it replies with their ID - Have the person send
/startto the bot in private — check logs for their user ID - Forward a message from the person to
@userinfobot
Step 3: Register orgs/projects
The bot needs a mapping of org names to filesystem paths where claude --agent <name> will run. This can be:
- A hardcoded dict in the bot script (simplest)
- A JSON config file (more flexible)
- Auto-discovered from a known parent directory (e.g.,
~/Orgs/)
Each org/project must have .claude/agents/<agent-name>.md files.
Step 4: Guide the user through Telegram setup
Tell the user:
- Create a Telegram group (or use an existing one)
- Add the bot to the group
- Add the other person to the group
- In the group, send:
/connect <org> <agent> - Then:
/allow <person_telegram_id> - Verify with:
/status
Architecture
Telegram Group (User A + User B + Bot)
|
v
Bot script (long-running Python process)
|
+-- reads chat config (JSON file)
+-- checks allow list (is sender permitted?)
+-- routes message to AgentSession
|
v
tmux window running: claude --agent <agent>
working directory: <org/project path>
|
v
Agent reads project files, runs tools, etc.
Agent replies via send script --chat <chat_id> "message"
Key components:
Chat config (envoy-chats.json):
{
"chats": {
"<chat_id>": {
"org": "<org-name>",
"org_path": "<absolute path>",
"agent": "<agent-name>",
"allowed_users": [<user_id_1>, <user_id_2>]
}
}
}
AgentSession (tmux-based, same pattern as agent bot runners):
- Each connected chat gets a tmux window:
claude --agent <agent>running in the org directory - Messages are sent via
tmux load-buffer/paste-buffer(handles special chars) - Agent replies via the send script (fire-and-forget)
- Self-healing: TTL-based restart (every 4h), watchdog for unresponsive agents
- Messages tagged with
[chat_id:NUMBER,msg_id:NUMBER,from:NAME]so agents can reply to the right chat
Telegram reply instructions (appended to agent's system prompt via --append-system-prompt):
- Agent must use Bash tool to call the send script — stdout doesn't reach Telegram
- React first (acknowledge), then reply
- Include
--chat <chat_id>in every send command - Plain text only (no markdown)
Bot Commands
| Command | Who | What |
|---|---|---|
/connect <org> <agent> |
Admin only | Link this chat to an org agent |
/allow <user_id> |
Admin only | Add a user to the allow list |
/disconnect |
Admin only | Remove agent link, stop session |
/reset |
Admin only | Restart agent session (fresh context) |
/status |
Anyone | Show current chat configuration |
Troubleshooting
| Problem | Solution |
|---|---|
| Bot not responding | Check if bot process is running. Restart if needed. |
| Agent not responding | /reset to restart tmux session. Check tmux ls for the session. |
| "Unknown org" | Add the org to the path registry in the bot script. |
| "Agent not found" | Verify .claude/agents/<name>.md exists in the org directory. |
| Messages ignored | User not in allow list. Admin must /allow <user_id>. |
| Agent replies to wrong chat | Ensure --chat <chat_id> is in the send script instructions. |
Security Notes
- Only the admin (owner) can
/connect,/allow, and/disconnect - Messages from non-allowed users are silently ignored
- Each chat gets its own isolated Claude session (separate tmux window, separate context)
- Agent sessions run with
--dangerously-skip-permissionsfor autonomous operation — ensure agents have proper boundary policies in their definitions