# External Integrations **Analysis Date:** 2026-04-01 ## Bot Platform APIs **Telegram Bot API:** - Purpose: Primary messaging surface for user ↔ Lambda agent interaction - Client library: `aiogram` 3.26.0 (async, wraps Telegram Bot API v7+) - Authentication: Bot token via `TELEGRAM_BOT_TOKEN` - Entry point: `adapter/telegram/bot.py` (planned; aiogram worktree branch `feat/telegram-adapter`) - Transport: Long-polling or webhook (aiogram supports both; mode not yet locked in) - Bot API docs: https://core.telegram.org/bots/api **Matrix Client-Server API:** - Purpose: Secondary messaging surface (Matrix/Element clients) - Client library: `matrix-nio` 0.25.2 (async) - Authentication: password login or pre-existing access token (`MATRIX_ACCESS_TOKEN`) - Login flow in `adapter/matrix/bot.py` `main()`: - If `MATRIX_ACCESS_TOKEN` is set → assigned directly to `client.access_token` - Else if `MATRIX_PASSWORD` is set → `client.login(password=..., device_name="surfaces-bot")` - Sync method: `client.sync_forever(timeout=30000)` (30-second long-poll) - E2EE store: nio file-based store at path from `MATRIX_STORE_PATH` (default: `"matrix_store"`) - Matrix C-S API docs: https://spec.matrix.org/latest/client-server-api/ ### Matrix Room Model Rooms are mapped to Lambda chat slots (C1, C2, C3…) via `adapter/matrix/room_router.py`: - First message in a room → assigns next chat ID (C1, C2, …) and persists mapping to store - Room metadata stored under key `matrix_room:` in `StateStore` - User metadata (next chat index) stored under `matrix_user:` ### Matrix Event Types Handled | nio Event Class | Handler | Action | |--------------------|-----------------------------|-------------------------------| | `RoomMessageText` | `MatrixBot.on_room_message` | Dispatch to `EventDispatcher` | | `ReactionEvent` | `MatrixBot.on_reaction` | Button confirmation / skill toggle | | `InviteMemberEvent`| `MatrixBot.on_member` | Accept room invite | | `RoomMemberEvent` | `MatrixBot.on_member` | Membership change handling | ## Lambda Platform (Internal SDK) **Purpose:** AI agent backend — processes user messages, manages user accounts, returns responses **Interface:** `sdk/interface.py` — `PlatformClient` Protocol **Current Implementation:** `sdk/mock.py` — `MockPlatformClient` - Simulates network latency (10–80 ms default, 200–600 ms for message calls) - In-process in-memory state (users, messages, settings dicts) - Supports webhook simulation via `simulate_agent_event()` **Production Integration (future):** - URL: `LAMBDA_PLATFORM_URL` (default: `http://localhost:8000`) - Auth: `LAMBDA_SERVICE_TOKEN` (bearer token) - Mode switch: `PLATFORM_MODE=mock` vs `PLATFORM_MODE=production` - Swap path: replace `sdk/mock.py` only; no changes to `core/` or `adapter/` **Platform API Methods (from `sdk/interface.py`):** ```python async def get_or_create_user(external_id, platform, display_name) -> User async def send_message(user_id, chat_id, text, attachments) -> MessageResponse async def stream_message(user_id, chat_id, text, attachments) -> AsyncIterator[MessageChunk] async def get_settings(user_id) -> UserSettings async def update_settings(user_id, action) -> None ``` **Webhook / Push (outbound from platform → bot):** - Interface: `WebhookReceiver` Protocol (`sdk/interface.py`) - Registration: `MockPlatformClient.register_webhook_receiver(receiver)` - Event types: `task_done`, `task_error`, `task_progress` (modelled in `AgentEvent`) - Production implementation not yet wired; mock supports `simulate_agent_event()` for testing ## Data Storage **Databases:** *SQLite (primary persistence):* - Client: stdlib `sqlite3` (synchronous, called from async code without `asyncio.to_thread`) - Schema: single key-value table: `kv (key TEXT PRIMARY KEY, value TEXT NOT NULL)` - JSON serialization for values (`json.dumps` / `json.loads`) - Matrix bot DB path: `MATRIX_DB_PATH` (default: `"lambda_matrix.db"`) - Telegram bot DB path: implicit `"lambda_bot.db"` (file present in repo root — development artifact) - Implementation: `core/store.py` `SQLiteStore` *In-Memory (testing / development):* - `InMemoryStore` — plain Python dict, no persistence across restarts - `MockPlatformClient` internal state — also in-memory dicts **File Storage:** - Matrix nio E2EE store: local filesystem directory at `MATRIX_STORE_PATH` (default: `"matrix_store/"`) - No object storage (S3/GCS/etc.) currently; mock client has `attachment_mode` flag (`"url"` | `"binary"` | `"s3"`) reserved for future real SDK **Caching:** - None — no Redis or external cache layer ## Authentication & Identity **Telegram Auth:** - Bot token → passed to aiogram dispatcher at startup - User identity: Telegram user ID mapped to platform `external_id` **Matrix Auth:** - Password or access token (see above) - User identity: Matrix user ID (e.g. `@user:matrix.org`) mapped to platform `external_id` **Lambda Platform User Identity:** - `get_or_create_user(external_id, platform)` → returns `User` with internal `user_id` - External IDs are platform-prefixed in mock: `"{platform}:{external_id}"` ## Monitoring & Observability **Logging:** - `structlog` 25.5.0 — structured logging (key=value pairs) - Logger instantiation: `structlog.get_logger(__name__)` in each module - Log calls use keyword arguments: `logger.info("event_name", key=value, ...)` - No log shipping / aggregation configured (local stdout only) **Error Tracking:** - None — no Sentry, Datadog, or similar integration **Metrics:** - None — `MockPlatformClient.get_stats()` returns basic in-memory counters (not exported) ## CI/CD & Deployment **Hosting:** - Not specified — no Dockerfile, docker-compose, or cloud config files present **CI Pipeline:** - None detected — no `.github/workflows/`, `.gitlab-ci.yml`, etc. ## Environment Configuration **Required variables (from `.env.example`):** | Variable | Required | Default | Purpose | |-----------------------|----------|--------------------|--------------------------------------| | `TELEGRAM_BOT_TOKEN` | Yes* | — | Telegram Bot API token | | `MATRIX_HOMESERVER` | Yes* | — | Matrix homeserver URL (e.g. `https://matrix.org`) | | `MATRIX_USER_ID` | Yes* | — | Bot's Matrix user ID | | `MATRIX_PASSWORD` | Cond. | — | Login password (if no access token) | | `MATRIX_ACCESS_TOKEN` | Cond. | — | Pre-issued access token (preferred) | | `MATRIX_DEVICE_ID` | No | `""` | Matrix device ID | | `MATRIX_DB_PATH` | No | `"lambda_matrix.db"` | SQLite DB file path (Matrix bot) | | `MATRIX_STORE_PATH` | No | `"matrix_store"` | nio E2EE store directory | | `LAMBDA_PLATFORM_URL` | No** | `http://localhost:8000` | Lambda platform base URL | | `LAMBDA_SERVICE_TOKEN`| No** | — | Service auth token for Lambda API | | `PLATFORM_MODE` | No | `"mock"` | `"mock"` or `"production"` | \* Required for the respective bot to function. \*\* Only required when `PLATFORM_MODE=production`. **Secrets location:** - `.env` file (gitignored) - Never committed — `.env.example` provides template - Loaded via `python-dotenv` at module import in each `bot.py` entry point ## Webhooks & Callbacks **Incoming (platform → bot):** - `WebhookReceiver.on_agent_event(event: AgentEvent)` — receives async task completion notifications - Not yet wired to an HTTP endpoint; `MockPlatformClient.simulate_agent_event()` used for testing **Outgoing (bot → external):** - Telegram: all via `aiogram` polling or webhook (no direct outbound HTTP beyond Telegram API) - Matrix: all via `matrix-nio` `AsyncClient.room_send()`, `room_typing()`, etc. - Platform: via `PlatformClient` send/stream methods --- *Integration audit: 2026-04-01*