Files
ajarbot/docs/README_ADAPTERS.md
Jordan Ramos a99799bf3d Initial commit: Ajarbot with optimizations
Features:
- Multi-platform bot (Slack, Telegram)
- Memory system with SQLite FTS
- Tool use capabilities (file ops, commands)
- Scheduled tasks system
- Dynamic model switching (/sonnet, /haiku)
- Prompt caching for cost optimization

Optimizations:
- Default to Haiku 4.5 (12x cheaper)
- Reduced context: 3 messages, 2 memory results
- Optimized SOUL.md (48% smaller)
- Automatic caching when using Sonnet (90% savings)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-13 19:06:28 -07:00

11 KiB

Ajarbot Multi-Platform Adapters

This document describes the adapter system that allows ajarbot to run on multiple messaging platforms simultaneously (Slack, Telegram, and more).

Architecture Overview

The adapter system is inspired by OpenClaw's sophisticated plugin-based architecture but simplified for ajarbot's needs:

┌─────────────────────────────────────────────────────────┐
│                    Bot Runner                           │
│  ┌───────────────────────────────────────────────────┐ │
│  │            Adapter Runtime                         │ │
│  │  ┌──────────────┐  ┌──────────────┐               │ │
│  │  │    Slack     │  │  Telegram    │  ...          │ │
│  │  │   Adapter    │  │   Adapter    │               │ │
│  │  └──────┬───────┘  └──────┬───────┘               │ │
│  │         │                 │                        │ │
│  │         └────────┬────────┘                        │ │
│  │                  │                                 │ │
│  │          ┌───────▼───────┐                         │ │
│  │          │  Agent Core   │                         │ │
│  │          │ (Memory+LLM)  │                         │ │
│  │          └───────────────┘                         │ │
│  └───────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘

Key Components

  1. BaseAdapter (adapters/base.py)

    • Abstract interface that all platform adapters implement
    • Defines capabilities (threads, reactions, media, markdown, etc.)
    • Handles message chunking based on platform limits
    • Manages message handler registration
  2. AdapterRuntime (adapters/runtime.py)

    • Connects messaging adapters to the Agent
    • Manages message queue and async processing
    • Handles user ID mapping (platform → ajarbot username)
    • Supports preprocessors and postprocessors
  3. AdapterRegistry (adapters/base.py)

    • Manages multiple adapter instances
    • Provides lookup by platform name
    • Handles bulk start/stop operations
  4. ConfigLoader (config/config_loader.py)

    • Loads adapter configuration from YAML
    • Supports environment variable overrides
    • Separates secrets (.local.yaml) from templates

Supported Platforms

Slack (Socket Mode)

Features:

  • Socket Mode (no webhooks needed)
  • Thread support
  • Reactions
  • Media/file attachments
  • Markdown (mrkdwn)
  • 4000 character limit

Configuration:

slack:
  enabled: true
  credentials:
    bot_token: "xoxb-..."
    app_token: "xapp-..."
  settings:
    auto_react_emoji: "thinking_face"  # Optional

Setup Steps:

  1. Go to https://api.slack.com/apps
  2. Create new app → "From scratch"
  3. Enable Socket Mode (Settings → Socket Mode)
  4. Generate App-Level Token with connections:write scope
  5. Add Bot Token Scopes:
    • chat:write
    • channels:history
    • groups:history
    • im:history
    • mpim:history
    • app_mentions:read
  6. Install app to workspace
  7. Copy Bot User OAuth Token (xoxb-...) and App-Level Token (xapp-...)

Telegram

Features:

  • Direct polling (no webhooks)
  • Reactions (new API)
  • Media/file attachments
  • Markdown or HTML
  • 4096 character limit
  • User allowlist support

Configuration:

telegram:
  enabled: true
  credentials:
    bot_token: "123456:ABC-DEF..."
  settings:
    allowed_users: []  # Optional: [123456789]
    parse_mode: "Markdown"  # or "HTML"

Setup Steps:

  1. Open Telegram and message @BotFather
  2. Send /newbot
  3. Follow prompts (choose name and username)
  4. Copy the bot token
  5. (Optional) Configure privacy settings with /setprivacy

Quick Start

1. Install Dependencies

pip install -r requirements.txt

2. Generate Configuration Template

python bot_runner.py --init

This creates config/adapters.local.yaml with a template.

3. Edit Configuration

Edit config/adapters.local.yaml:

adapters:
  slack:
    enabled: true  # Change to true
    credentials:
      bot_token: "xoxb-YOUR-ACTUAL-TOKEN"
      app_token: "xapp-YOUR-ACTUAL-TOKEN"

  telegram:
    enabled: true  # Change to true
    credentials:
      bot_token: "YOUR-ACTUAL-BOT-TOKEN"

4. Run the Bot

python bot_runner.py

Output:

============================================================
🤖 Ajarbot Multi-Platform Runner
============================================================

[Setup] Initializing agent...
[Setup] ✓ Agent initialized

[Setup] Loading Slack adapter...
[Setup] ✓ Slack adapter loaded

[Setup] Loading Telegram adapter...
[Setup] ✓ Telegram adapter loaded

[Setup] ✓ 2 adapter(s) configured

============================================================
🚀 Starting bot...
============================================================

[Slack] Starting Socket Mode connection...
[Slack] ✓ Connected and listening for messages
[Telegram] Starting bot...
[Telegram] ✓ Bot started: @your_bot (Your Bot Name)
[Runtime] Message processing loop started

============================================================
✓ Bot is running! Press Ctrl+C to stop.
============================================================

Environment Variables (Alternative to YAML)

You can use environment variables instead of or in addition to the YAML config:

export AJARBOT_SLACK_BOT_TOKEN="xoxb-..."
export AJARBOT_SLACK_APP_TOKEN="xapp-..."
export AJARBOT_TELEGRAM_BOT_TOKEN="123456:ABC..."

python bot_runner.py

Environment variables take precedence over YAML configuration.

User Mapping

Map platform user IDs to ajarbot usernames for memory consistency:

user_mapping:
  slack:U12345ABCDE: "alice"
  telegram:123456789: "alice"

Now when Alice messages from either Slack or Telegram, the bot will use the same memory profile.

Advanced Usage

Custom Preprocessors

Add custom logic before messages reach the Agent:

from adapters.runtime import AdapterRuntime
from adapters.base import InboundMessage

def my_preprocessor(message: InboundMessage) -> InboundMessage:
    # Example: Auto-expand abbreviations
    if message.text == "status":
        message.text = "What is your current status?"
    return message

runtime.add_preprocessor(my_preprocessor)

Custom Postprocessors

Modify responses before sending to platforms:

def my_postprocessor(response: str, original: InboundMessage) -> str:
    # Example: Add platform-specific formatting
    if original.platform == "slack":
        response = response.replace("**", "*")  # Bold
    return response

runtime.add_postprocessor(my_postprocessor)

Health Checks

python bot_runner.py --health

Output:

============================================================
Health Check
============================================================

Runtime running: True

Adapters:

  SLACK:
    platform: slack
    running: True
    healthy: True
    bot_id: B12345
    team: T12345
    connected: True

  TELEGRAM:
    platform: telegram
    running: True
    healthy: True
    bot_id: 123456789
    username: your_bot
    connected: True

Adding New Adapters

To add support for a new platform (Discord, WhatsApp, etc.):

  1. Create adapter file adapters/newplatform/adapter.py
  2. Inherit from BaseAdapter and implement required methods:
    • platform_name property
    • capabilities property
    • validate_config()
    • start() / stop()
    • send_message()
  3. Register in bot_runner.py
  4. Add config section to adapters.yaml

Example skeleton:

from adapters.base import BaseAdapter, AdapterConfig, AdapterCapabilities

class NewPlatformAdapter(BaseAdapter):
    @property
    def platform_name(self) -> str:
        return "newplatform"

    @property
    def capabilities(self) -> AdapterCapabilities:
        return AdapterCapabilities(
            supports_threads=True,
            max_message_length=2000
        )

    def validate_config(self) -> bool:
        return bool(self.config.credentials.get("api_key"))

    async def start(self):
        # Initialize connection
        self.is_running = True

    async def stop(self):
        # Cleanup
        self.is_running = False

    async def send_message(self, message: OutboundMessage):
        # Send message to platform
        return {"success": True, "message_id": "123"}

Comparison with OpenClaw

Feature OpenClaw Ajarbot Adapters
Architecture Plugin-based with 12+ sub-adapters per channel Simplified single-adapter per platform
Type System TypeScript with structural typing Python with ABC/dataclasses
Adapters config, gateway, outbound, status, security, pairing, etc. Combined into BaseAdapter
Registry Two-tier (DOCKS + plugin registry) Single AdapterRegistry
Scope 20+ platforms, enterprise features Core platforms, essential features
Complexity High (production-grade) Medium (developer-friendly)

What We Adopted from OpenClaw

Plugin-based architecture - Each platform is self-contained Capability declarations - Platforms declare what they support Consistent interfaces - All adapters implement the same contract Gateway pattern - start/stop lifecycle management Outbound adapter - Message sending abstraction Status/health checks - Monitoring and diagnostics Chunking strategies - Platform-aware text splitting

What We Simplified

🔄 Single adapter class instead of 12+ sub-adapters 🔄 Python dataclasses instead of TypeScript interfaces 🔄 YAML config instead of complex config system 🔄 Direct integration instead of full plugin loading system

Troubleshooting

"No adapters enabled"

  • Check that enabled: true in your config
  • Verify credentials are set correctly
  • Try running with --init to regenerate template

Slack: "invalid_auth"

  • Ensure bot_token starts with xoxb-
  • Ensure app_token starts with xapp-
  • Verify app is installed to workspace

Telegram: Bot not responding

  • Check bot token is correct (from @BotFather)
  • Ensure no other instance is polling the same bot
  • Check allowed_users setting isn't blocking you

Import errors

pip install -r requirements.txt --upgrade

License

Same as ajarbot (check main repository).

Credits

Adapter architecture inspired by OpenClaw by Chloe.