Skip to main content

Aragora Channels

Bidirectional communication across organizational channels


Overview

Aragora is the control plane for multi-agent vetted decisionmaking across organizational knowledge and channels. This document describes the channel integrations that enable:

  • Inbound Queries: Receive vetted decisionmaking requests from any channel
  • Outbound Results: Automatically route results back to the originating channel
  • Real-time Updates: Stream vetted decisionmaking progress via WebSocket
  • Voice Integration: Speech-to-text input, text-to-speech output

Channel Architecture

┌─────────────────────────────────────────────────────────────────┐
│ INBOUND CHANNELS │
├─────────────────────────────────────────────────────────────────┤
│ Slack │ Discord │ Teams │ Telegram │ WhatsApp │ Email │ Voice │ API │
└────────────────────────────┬────────────────────────────────────┘


┌─────────────────────────────────────────────────────────────────┐
│ ARAGORA CONTROL PLANE │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Chat Router │ │ Debate │ │ Result │ │
│ │ │ │ Origin │ │ Router │ │
│ │ Platform │ │ Tracker │ │ │ │
│ │ detection │ │ │ │ Auto-route │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │
└────────────────────────────┬────────────────────────────────────┘


┌─────────────────────────────────────────────────────────────────┐
│ OUTBOUND CHANNELS │
├─────────────────────────────────────────────────────────────────┤
│ Slack │ Discord │ Teams │ Telegram │ WhatsApp │ Email │ Voice │ API │
└─────────────────────────────────────────────────────────────────┘

Inbound Channels

Chat Platforms

PlatformHandlerFeatures
Slack/api/bots/slack/webhookSlash commands, app mentions, threads
Discord/api/bots/discord/webhookSlash commands, bot mentions
Microsoft Teams/api/bots/teams/webhookBot Framework, Adaptive Cards
Telegram/api/bots/telegram/webhookBot commands, inline queries
WhatsApp/api/bots/whatsapp/webhookCloud API integration
Google Chat/api/bots/google-chat/webhookSpace messages
Email (Gmail)/api/v1/email/inboxGmail ingestion + prioritization
Email (Outlook)/api/v1/outlook/messagesOutlook/M365 ingestion
Shared Inbox/api/v1/inbox/sharedCollaborative inbox triage

Configuration

# Slack
export SLACK_BOT_TOKEN=xoxb-...
export SLACK_SIGNING_SECRET=...

# Discord
export DISCORD_APPLICATION_ID=...
export DISCORD_PUBLIC_KEY=...
export DISCORD_BOT_TOKEN=...

# Teams
export TEAMS_APP_ID=...
export TEAMS_APP_PASSWORD=...

# Telegram
export TELEGRAM_BOT_TOKEN=...

# WhatsApp
export WHATSAPP_ACCESS_TOKEN=...
export WHATSAPP_PHONE_NUMBER_ID=...

# Gmail (email ingestion + prioritization)
export GMAIL_CLIENT_ID=...
export GMAIL_CLIENT_SECRET=...

Unified Chat Router

The chat router auto-detects the originating platform and normalizes requests:

Location: aragora/server/handlers/chat/router.py

# Auto-detect platform
POST /api/chat/webhook
Content-Type: application/json

{
"message": "Review this API design",
"attachments": [...],
"metadata": {...}
}

The router extracts:

  • Platform type
  • User/channel identity
  • Thread context (for replies)
  • Attachments

Normalized Messages & Channel Docks

Outbound results are normalized into a platform‑independent message format before being adapted by channel‑specific docks.

Normalized message model: aragora/channels/normalized.py
Dock interface: aragora/channels/dock.py

from aragora.channels.normalized import NormalizedMessage, MessageFormat

message = NormalizedMessage(
content="Decision complete ✅",
format=MessageFormat.MARKDOWN,
).with_button("View receipt", "https://aragora.ai/receipts/abc123")

Each platform implements a ChannelDock that declares capabilities (buttons, threads, files, voice) and renders the normalized message into the platform’s native format.

Dock Registry

Use the dock registry to discover and initialize platform docks:

from aragora.channels.registry import get_dock_registry
from aragora.channels.docks.slack import SlackDock

registry = get_dock_registry()
registry.register(SlackDock)

dock = await registry.get_initialized_dock("slack")
await dock.send_message("C123456", message)

Agent Channels (Peer Messaging)

Debates can enable peer‑to‑peer messaging between agents using AgentChannel. This enables proposals, critiques, and direct questions to flow alongside the main debate loop.

Integration helper: aragora/debate/channel_integration.py

Protocol flags:

  • enable_agent_channels (default: true)
  • agent_channel_max_history (default: 100)
from aragora.debate.channel_integration import ChannelIntegration

integration = ChannelIntegration(
debate_id="debate-123",
agents=agents,
protocol=protocol,
)
await integration.setup()

context = integration.get_context_for_prompt(limit=5)
await integration.broadcast_proposal(
agent_name="proposer",
proposal_content="We should rate-limit by org tier.",
round_number=1,
)

Message Bindings API

Bindings map incoming messages to routing targets (provider, account, pattern).

Endpoints:

  • GET /api/bindings – list all bindings
  • GET /api/bindings/\{provider\} – list provider bindings
  • POST /api/bindings – create binding
  • PUT /api/bindings/\{id\} – update binding
  • DELETE /api/bindings/\{id\} – remove binding
  • POST /api/bindings/resolve – resolve binding for a message
  • GET /api/bindings/stats – router statistics

RBAC permissions:

  • bindings.read
  • bindings.create
  • bindings.update
  • bindings.delete

Voice Integration

Aragora supports bidirectional voice I/O over WebSocket:

  • STT: Live transcription via Whisper connector
  • TTS: Optional synthesized responses from agent messages

Endpoint: /ws/voice/\{debate_id\}

Location: aragora/server/stream/voice_stream.py

Key settings:

ARAGORA_VOICE_TTS_ENABLED=true
ARAGORA_VOICE_TTS_DEFAULT_VOICE=narrator
ARAGORA_VOICE_MAX_SESSION=300
ARAGORA_VOICE_INTERVAL=3000

Outbound Routing

Result Router

When a vetted decisionmaking session completes, results automatically route back to the originating channel.

Location: aragora/server/result_router.py

from aragora.server import ResultRouter

router = ResultRouter()

# Results are automatically sent to the originating channel
await router.route_result(
debate_id="dbt_abc123",
result={
"consensus": True,
"confidence": 0.85,
"answer": "...",
"evidence": [...],
}
)

Debate Origin Tracking

Every debate tracks its origin for result routing:

Location: aragora/server/debate_origin.py

from aragora.server import DebateOrigin

origin = DebateOrigin(
platform="slack",
channel_id="C123456",
thread_ts="1234567890.123456",
user_id="U123456",
)

# Store with debate
debate = await create_debate(topic="...", origin=origin)

# Results automatically route back
await debate.complete(result) # Sends to Slack thread

Platform-Specific Formatting

Results are formatted for each platform:

PlatformFormat
SlackRich blocks with expandable sections
DiscordEmbeds with color-coded confidence
TeamsAdaptive Cards
TelegramMarkdown with inline buttons
WhatsAppPlain text with links

Real-time Streaming

WebSocket Events

80+ WebSocket events for real-time updates:

Location: aragora/server/stream/

Event CategoryEvents
Debate lifecycledebate_start, debate_end, round_start, round_end
Agent activityagent_message, agent_thinking, critique
Votingvote_cast, vote_tally, consensus_reached
Progressprogress_update, phase_change

Subscription

const ws = new WebSocket('wss://api.aragora.ai/ws');

ws.send(JSON.stringify({
type: 'subscribe',
debate_id: 'dbt_abc123'
}));

ws.onmessage = (event) => {
const data = JSON.parse(event.data);
console.log(data.type, data.payload);
};

Voice Integration

Speech-to-Text

Location: aragora/connectors/chat/voice_bridge.py

from aragora.connectors.chat import VoiceBridge

bridge = VoiceBridge()

# Transcribe audio to text
text = await bridge.transcribe(audio_bytes)

# Start a debate from voice
debate = await create_debate(topic=text, origin=voice_origin)

Supported formats: WAV, MP3, M4A, FLAC, OGG Max file size: 25MB

Text-to-Speech

Location: aragora/connectors/chat/tts_bridge.py

from aragora.connectors.chat import TTSBridge

tts = TTSBridge()

# Generate audio from debate result
audio = await tts.synthesize(
text=debate_result.summary,
voice="nova", # OpenAI TTS voice
)

# Send audio response
await send_voice_message(channel, audio)

Email Integration

Inbound Email

Location: aragora/server/handlers/bots/email_webhook.py

ProviderEndpoint
SendGridPOST /api/bots/email/webhook/sendgrid
AWS SESPOST /api/bots/email/webhook/ses

Gmail Integration

Location: aragora/connectors/enterprise/communication/gmail/

from aragora.connectors.enterprise.communication import GmailConnector

gmail = GmailConnector()

# Sync emails for knowledge ingestion
await gmail.sync(
query="label:important",
max_results=100,
)

# Emails are indexed and available for vetted decisionmaking context

External Integrations

Zapier / Make / n8n

Location: aragora/server/handlers/external_integrations.py

PlatformEndpoint
ZapierPOST /api/integrations/zapier/triggers
MakePOST /api/integrations/make/webhooks
n8nPOST /api/integrations/n8n/webhooks

These integrations allow:

  • Triggering debates from external workflows
  • Receiving results in external systems
  • Chaining debates with other automations

Channel Statistics

Aragora tracks channel usage:

GET /api/channels/stats

{
"total_messages": 12456,
"by_platform": {
"slack": 5234,
"discord": 3122,
"teams": 2100,
"telegram": 1000,
"api": 1000
},
"avg_response_time_ms": 450,
"debates_triggered": 789
}

Rate Limiting

Per-channel rate limits:

ChannelLimitWindow
Slack60 req/minPer workspace
Discord50 req/minPer guild
Teams60 req/minPer tenant
Telegram30 req/minPer chat
WhatsApp80 req/minPer number
API100 req/minPer API key