Setting Up Your Agent Environment
Communication Channels: Telegram & Discord
An agent without a communication channel is like a brilliant assistant locked in a room with no door. You need a way to talk to your agent — and more importantly, a way for your agent to reach you. Telegram and Discord are the two most practical channels for agent communication, each with distinct strengths.
Before you write a line of this: CrewAI has no channel layer. There is no
channels:block in any CrewAI config file, and no Telegram or Discord integration ships withcrewaiorcrewai-tools. What you are building in this lesson is a small program you own that holds the platform connection and callscrew.kickoff()— roughly 40 lines per platform. Module 1 Lesson 4 covers why the split lands where it does. Everything below is real code against the platforms' own libraries, so it will run.
Why These Two Channels
Telegram is ideal for personal, one-on-one agent interaction. It works on every device, supports rich media (photos, documents, voice notes), and its Bot API is one of the most straightforward to work with. When you want your agent to feel like a personal assistant in your pocket, Telegram is the right choice.
Discord excels at parallel, multi-context work. Each Discord channel provides a separate conversation context, which means you can have your agent working on different tasks in different channels simultaneously — research in one channel, code review in another, email drafting in a third. This channel-based separation is uniquely powerful for agent orchestration.
Setting Up a Telegram Bot
Telegram bots are created through BotFather, Telegram's official bot management tool.
Step 1: Create the bot
- Open Telegram and search for
@BotFather - Send the command
/newbot - Choose a display name (e.g., "My AI Agent")
- Choose a username ending in
bot(e.g.,my_ai_agent_bot) - BotFather responds with your bot token — save this securely
Step 2: Write the adapter
pip install python-telegram-bot
export TELEGRAM_BOT_TOKEN="your-bot-token-here"
export TELEGRAM_ALLOWED_USERS="123456789" # comma-separated numeric IDs
# telegram_agent.py
import asyncio, os
from telegram import Update
from telegram.ext import Application, MessageHandler, ContextTypes, filters
from my_crew import build_crew # your Crew — see the capstone in Module 5
ALLOWED = {int(u) for u in os.environ["TELEGRAM_ALLOWED_USERS"].split(",") if u.strip()}
async def on_message(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
if update.effective_user.id not in ALLOWED:
return # silent drop — do not confirm the bot exists
await update.message.chat.send_action("typing")
# crew.kickoff() is synchronous and can run for minutes. Never await it directly
# on the event loop — it would block every other update the bot is handling.
crew = build_crew(update.message.text)
result = await asyncio.to_thread(crew.kickoff)
await update.message.reply_text(str(result)[:4000]) # Telegram caps messages ~4096 chars
app = Application.builder().token(os.environ["TELEGRAM_BOT_TOKEN"]).build()
app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, on_message))
app.run_polling()
That is the whole channel layer. The two lines worth pausing on are the allow-list check (an
unrestricted bot is a public endpoint to your API budget) and asyncio.to_thread — a crew run is
blocking work, and calling it directly inside an async handler freezes the bot for everyone else
until it finishes. That second one is the bug people ship, because it works fine with one user.
Step 3: Set bot commands (optional but recommended)
Send these to BotFather to define your bot's command menu:
/setcommands
status - Check agent status
help - Show available commands
task - Assign a new task
Step 4: Get your user ID
To restrict your bot to only respond to you, you need your Telegram user ID. Send a message to @userinfobot on Telegram — it will reply with your numeric user ID.
Setting Up a Discord Bot
Discord bots require a few more steps because of Discord's permission and intent system.
Step 1: Create a Discord application
- Go to the Discord Developer Portal (discord.com/developers/applications)
- Click "New Application" and give it a name
- Navigate to the "Bot" section and click "Add Bot"
- Copy the bot token — save this securely
- Under "Privileged Gateway Intents," enable Message Content Intent (required for reading messages)
Step 2: Invite the bot to your server
- In the Developer Portal, go to "OAuth2" then "URL Generator"
- Select scopes:
bot,applications.commands - Select permissions:
Send Messages,Read Message History,Embed Links,Attach Files - Copy the generated URL and open it in your browser to invite the bot
Step 3: Write the adapter
pip install discord.py
export DISCORD_BOT_TOKEN="your-discord-bot-token-here"
# discord_agent.py
import asyncio, os
import discord
from discord.ext import commands
from my_crew import build_crew
# Per-channel briefs: the channel a message arrives in decides the agent's job.
CHANNEL_PURPOSE = {
"research": "Search the web and summarise findings with sources.",
"code-review": "Review the pasted diff and report correctness risks only.",
"email-drafts": "Draft a reply for human review. Never send anything.",
}
OPERATOR_ROLE = "agent-operator"
intents = discord.Intents.default()
intents.message_content = True # must also be enabled in the Developer Portal
bot = commands.Bot(command_prefix="!", intents=intents)
@bot.event
async def on_message(message: discord.Message) -> None:
if message.author.bot:
return # or two bots will talk to each other forever
purpose = CHANNEL_PURPOSE.get(message.channel.name)
if purpose is None:
return # bot is inert outside the channels you listed
if not any(r.name == OPERATOR_ROLE for r in getattr(message.author, "roles", [])):
return
async with message.channel.typing():
crew = build_crew(f"{purpose}\n\nRequest: {message.content}")
result = await asyncio.to_thread(crew.kickoff)
await message.reply(str(result)[:1900]) # Discord caps messages at 2000 chars
bot.run(os.environ["DISCORD_BOT_TOKEN"])
Note if message.author.bot: return. Without it, two agents sharing a server will answer each
other's messages indefinitely — a cheap mistake that gets expensive overnight.
Discord's Parallel Context Advantage
This is where Discord becomes particularly valuable for agent work. Consider this setup:
| Channel | Purpose | Agent Behavior |
|---|---|---|
#research | Web research tasks | Agent searches, summarizes, and saves findings |
#code-review | Code analysis | Agent reviews PRs and provides feedback |
#email-drafts | Email composition | Agent drafts emails for your review |
#daily-briefing | Morning reports | Agent posts daily summaries on schedule |
#logs | Agent activity logs | Agent logs all actions for audit |
Each channel maintains its own conversation context. When you message the agent in #research, it does not confuse that with the conversation happening in #code-review. This natural isolation means you can run multiple workflows in parallel without context pollution.
That isolation is not something the platform gives you for free — it is the CHANNEL_PURPOSE
dictionary in the adapter above. The channel name selects which brief gets prepended to the
request, so a message in #code-review and a message in #research reach the crew with different
instructions. Adding a workflow is one dictionary entry plus one Discord channel.
The shape of every channel adapter
Both bots above are the same four steps. Once you can see the shape, adding Slack, SMS, or a web form is the same work with a different library:
Message in, answer out — what your adapter owns
The framework owns exactly one box in that diagram. Everything else is yours, which is also why swapping CrewAI for another orchestrator later costs you one line in this file.
Security Considerations
Messaging channels are a direct interface to your agent's capabilities. Securing them is critical.
Allow lists: Always restrict your bot to known users (Telegram) or specific servers and roles (Discord). An unrestricted bot is a security liability — anyone who finds it can issue commands.
Message validation: Validate incoming messages before processing. Check that the sender is authorized, the message format is expected, and the requested action is within allowed boundaries.
Token security: Bot tokens are equivalent to passwords. Never commit them to version control. Use environment variables or a secrets manager.
# WRONG: Token hardcoded in config
bot_token: "7234567890:AAF..."
# RIGHT: Token loaded from environment
bot_token: ${TELEGRAM_BOT_TOKEN}
Rate limiting: Implement rate limits to prevent accidental or malicious message floods from triggering excessive API calls and running up costs.
Audit logging: Log all commands received and actions taken. If something goes wrong, you need a clear trail of what happened and who triggered it.
Key takeaway: Telegram gives you a personal assistant in your pocket. Discord gives you a multi-channel command center. Use Telegram for direct interaction and Discord for parallel workflows — and always secure both with allow lists and proper token management.
Next: Expanding your agent's capabilities with memory, voice, and email integration. :::
Sign in to rate