Skip to content

Channel Setup

Channels connect your agents to messaging platforms. Each channel plugin handles the platform’s API, message formatting, rate limits, and streaming behavior so your agent just sends and receives text.

RivetOS ships with four channel plugins:

ChannelPlatformUse Case
DiscordDiscord servers & DMsPrimary chat interface, streaming responses, reactions
TelegramTelegram botsMobile-friendly, simple setup
VoiceDiscord voice channelsReal-time voice conversations via xAI Realtime or Gemini Live API
AgentHTTP (internal)Agent-to-agent messaging, mesh networking

The Discord channel connects your agent to Discord servers and DMs using discord.js. It supports streaming message edits, emoji reactions, thread creation, embeds, buttons, and file attachments.

  1. Go to the Discord Developer Portal
  2. Click New Application → give it a name → Create
  3. Go to Bot in the sidebar
  4. Click Reset Token → copy the token (you’ll only see it once)
  5. Under Privileged Gateway Intents, enable:
    • Message Content Intent
    • Server Members Intent (optional, for member info)
  1. Go to OAuth2URL Generator in the sidebar
  2. Under Scopes, check: bot, applications.commands
  3. Under Bot Permissions, check:
    • Send Messages
    • Read Message History
    • Add Reactions
    • Manage Messages (for editing streamed responses)
    • Create Public Threads (optional)
    • Attach Files (optional)
    • Use Slash Commands
  4. Copy the generated URL → open it in your browser → select your server → Authorize
  1. In Discord, go to User SettingsAdvanced → enable Developer Mode
  2. Right-click any channel → Copy Channel ID
  3. Right-click your user → Copy User ID (for owner_id)

Add the bot token to .env:

Terminal window
DISCORD_BOT_TOKEN=MTIz...your-token-here

Add the channel config to config.yaml:

channels:
discord:
owner_id: "YOUR_USER_ID"
channel_bindings:
"123456789012345678": opus # #deep-thinking → opus agent
"987654321098765432": grok # #brainstorm → grok agent
KeyTypeDefaultDescription
channel_bindingsobjectrequiredMaps Discord channel IDs → agent names
owner_idstringYour Discord user ID. Enables owner-only features
bot_tokenstring${DISCORD_BOT_TOKEN}Bot token. Always use env var
mention_onlybooleanfalseOnly respond when @mentioned in servers
allowed_guildsstring[]Restrict to specific server IDs
allowed_channelsstring[]Restrict to specific channel IDs
allowed_usersstring[]Restrict to specific user IDs
  • Message limit: 2000 characters. The plugin automatically splits longer responses into multiple messages.
  • Streaming: Responses stream in real-time by editing the message as tokens arrive. Discord rate limits apply — the plugin throttles edits automatically.
  • Reactions: The agent can react to messages with emoji. Useful for acknowledgements without cluttering the chat.
  • Threads: The agent can create and reply in threads for long conversations.

The Telegram channel connects your agent to a Telegram bot using grammY. It supports text, photos, voice messages, documents, inline buttons, and HTML-formatted responses.

  1. Open Telegram and message @BotFather
  2. Send /newbot
  3. Follow the prompts — choose a name and username
  4. BotFather gives you an API token like 123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11
  5. Copy the token

Your Telegram user ID is a number (not your @username). To find it:

  1. Message @userinfobot on Telegram
  2. It replies with your numeric user ID

The owner_id restricts the bot to only respond to you. Without it, anyone who finds your bot can talk to it.

Add the bot token to .env:

Terminal window
TELEGRAM_BOT_TOKEN=123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11

Add the channel config to config.yaml:

channels:
telegram:
owner_id: "YOUR_NUMERIC_USER_ID"
KeyTypeDefaultDescription
owner_idstringrequiredYour Telegram user ID. Only this user can talk to the bot
bot_tokenstring${TELEGRAM_BOT_TOKEN}Bot API token from BotFather
allowed_usersstring[]Additional user IDs allowed to use the bot
agentstringDefault agent to route messages to
  • Message limit: 4096 characters. Longer responses are split automatically.
  • Formatting: Markdown is converted to Telegram HTML format automatically. Code blocks, bold, italic, and links all work.
  • Streaming: Responses stream by editing the message in-place, similar to Discord.
  • 409 Conflict: If you run multiple instances with the same bot token, Telegram returns 409 errors. The plugin handles this with backoff and retry, but you should only run one instance per token.

The voice channel plugin connects your agent to Discord voice channels for real-time spoken conversations. It supports multiple voice providers — choose the one that fits your setup.

ProviderBackendBest For
xaixAI Realtime APINative xAI users, low-latency
geminiGemini Live APIGoogle ecosystem, Google Search grounding
  • A Discord bot token (same one used for the text Discord channel is fine, or a separate one)
  • An API key for your chosen voice provider (xAI or Google)
  • The bot must have Connect and Speak permissions in the voice channel

Add keys to .env:

Terminal window
DISCORD_VOICE_TOKEN=MTIz...your-token-here
# For xAI provider:
XAI_API_KEY=xai-...your-key-here
# For Gemini provider:
GOOGLE_API_KEY=AIza...your-key-here

Add to config.yaml:

# Example: Gemini Live provider
channels:
voice-discord:
provider: gemini
discord_token: ${DISCORD_VOICE_TOKEN}
google_api_key: ${GOOGLE_API_KEY}
guild_id: "YOUR_SERVER_ID"
voice_channel_id: "YOUR_VOICE_CHANNEL_ID"
allowed_users:
- "YOUR_USER_ID"
voice: "Kore"
instructions: "You are a helpful assistant. Be concise in voice responses."
# Example: xAI Realtime provider
channels:
voice-discord:
provider: xai
discord_token: ${DISCORD_VOICE_TOKEN}
xai_api_key: ${XAI_API_KEY}
guild_id: "YOUR_SERVER_ID"
voice_channel_id: "YOUR_VOICE_CHANNEL_ID"
allowed_users:
- "YOUR_USER_ID"
voice: "Ara"
instructions: "You are a helpful assistant. Be concise in voice responses."
KeyTypeDefaultDescription
providerstringxaiVoice provider: xai or gemini
discord_tokenstringrequiredDiscord bot token
guild_idstringrequiredDiscord server ID
voice_channel_idstringBind to a specific voice channel (recommended for multi-agent)
allowed_usersstring[]requiredUser IDs allowed to activate the bot
voicestringAra (xAI) / Kore (Gemini)Voice to use for text-to-speech
instructionsstringSystem instructions for the voice agent
silence_duration_msnumber1500How long to wait after silence before responding
sample_ratenumber24000Audio sample rate (Hz)
transcript_dirstringtranscriptsDirectory for voice transcript logs
leave_grace_period_msnumber10000How long to wait before leaving after everyone else leaves
xai_api_keystringxAI API key (required for xai provider)
google_api_keystringGoogle API key (required for gemini provider)
gemini_modelstringgemini-2.0-flash-live-001Gemini model for live voice (only for gemini provider)
xai_collection_idstringxAI knowledge collection for context (only for xai provider)
  1. Auto-join: When an allowed user joins a voice channel, the bot automatically joins too
  2. Voice activity detection (VAD): The provider detects when you’re speaking (server-side VAD)
  3. Audio pipeline: Discord Opus → PCM → Voice Provider → PCM → 48kHz stereo → Discord
  4. Auto-leave: When all users leave, the bot leaves after the grace period
  5. Transcripts: All voice conversations are logged to markdown files
  6. Memory tools: The voice agent can search your conversation memory via function calling

Each agent can bind to its own voice channel with its own provider:

# Grok uses xAI Realtime in one VC
channels:
voice-discord:
provider: xai
voice_channel_id: "111222333"
# ...
# Opus uses Gemini Live in another VC
channels:
voice-discord:
provider: gemini
voice_channel_id: "444555666"
# ...

Once the bot is in your server, these slash commands are available:

CommandDescription
/voice joinForce the bot to join your voice channel
/voice leaveForce the bot to leave
/voice statusShow current voice session info
/voice voice [name]Switch the TTS voice

The agent channel enables agent-to-agent communication over HTTP. This is how multi-instance mesh networking works — agents on different machines can send messages to each other.

  • Multi-agent setups: Opus delegates tasks to Grok on another machine
  • Mesh networking: Multiple RivetOS instances share work
  • API access: External systems can send messages to your agent

Add a shared secret to .env:

Terminal window
RIVETOS_AGENT_SECRET=your-shared-secret-here

Add to config.yaml:

channels:
agent:
port: 3100
secret: ${RIVETOS_AGENT_SECRET}

For mesh networking, also configure the mesh section:

mesh:
nodes:
- name: rivet-opus
host: 192.0.2.10
port: 3100
agents: [opus]
- name: rivet-grok
host: 192.0.2.11
port: 3100
agents: [grok]
KeyTypeDefaultDescription
portnumber3100HTTP port for the agent API
hoststring0.0.0.0Bind address
secretstringrequiredShared secret for authentication
peersobjectNamed peer agents with their URLs

The agent channel exposes these HTTP endpoints:

MethodPathDescription
POST/api/messageSend a message to the agent
GET/api/healthHealth check
GET/api/meshList mesh nodes
POST/api/mesh/joinRegister a new mesh node
Terminal window
curl -X POST http://localhost:3100/api/message \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your-shared-secret" \
-d '{
"fromAgent": "external",
"message": "Hello, what is the status of the project?",
"waitForResponse": true
}'

You can run multiple channels simultaneously. A common setup:

channels:
discord:
owner_id: "111222333"
channel_bindings:
"444555666": opus
"777888999": grok
telegram:
owner_id: "123456789"
agent:
port: 3100
secret: ${RIVETOS_AGENT_SECRET}

Each channel routes messages to agents independently. The same agent can receive messages from multiple channels.