Skip to content

eumemic/chatbox

Repository files navigation

chatbox

A standalone service that encapsulates messaging-platform connectors behind a unified API. Agents reach outbound capabilities through a per-mailbox MCP server; inbound messages flow to the agent's harness via webhook. Owns the focal-attention paradigm so a single agent can hold one focus across many chats and platforms — entirely transparent to the harness.

Phase 1 ships: service core, Signal connector, MCP proxy, templated webhook delivery. Phase 2 ships: focus mechanism (switch_chat, list_chats, recap rendering, per-event-type templates). Phase 3 ships: Telegram connector — same abstraction, second platform. Phase 4 ships: delivery health + retry, HMAC webhook signing, Prometheus metrics, operator CLI. Phase 5 ships: per-account admin MCP server — agents administer their own messaging surface (mute chats, update templates, inspect health) via /mcp/admin/{account_id}. Phase 6 ships: service events / webhook subscriptions — integrators listen for new_chat, delivery_failed, mailbox_paused. Fire-and-forget delivery never blocks the primary inbound flow. Phase 7 ships: Discord connector — built fresh against the connector contract (no AIOS source), validating the contract is usable cold. Phase 8 ships: Slack connector — second fresh build, providing strong evidence the abstraction is sound rather than retroactively shaped to existing implementations. Phase 9 ships: ephemeral ride-along templates — optional ephemeral template key in delivery_templates produces a sibling field on the webhook body, unblocking AIOS-style cache-stable prompt assembly without introducing any mode discriminator. Phase 10 ships: CMA integration adapter (examples/cma_adapter.py) + CMA_INTEGRATION.md walkthrough — closes the loop on the original CMA-first design goal.

387 tests passing across the service core (161), Signal connector (44), Telegram connector (57), Discord connector (66), and Slack connector (59).

Architecture

                 ┌─────────────────────┐
                 │   chatbox API       │  FastAPI, stateless
                 │  (chatbox api)      │  HTTP + per-mailbox MCP server (/mcp/{id})
                 └──────────┬──────────┘
                            │  Postgres
                 ┌──────────┴──────────┐
                 │  Connector procs    │  one per platform; HTTP client to API,
                 │ (chatbox-signal,    │  MCP server for outbound tools
                 │  chatbox-telegram)  │
                 └──────────┬──────────┘
                            │
            ┌───────────────┼───────────────────┐
            │               │                   │
       Signal/Telegram/etc network         Webhook → integrator's harness
                                            (e.g. CMA session inbound URL)

Resources

  • account — tenant key (multi-tenant in code; v1 ships single-tenant via bootstrap).
  • mailbox — attention surface. Has a webhook URL, an MCP URL, delivery templates, and (in phase 2) a focal chat.
  • connection — platform integration within a mailbox. At most one per platform per mailbox.
  • chat — a single conversation thread on a connection. Identified to the agent as <connector>:<external_handle>.
  • credential — encrypted secret (webhook auth, MCP proxy auth, optional HMAC signing key).

Focal attention paradigm (phase 2)

At any moment, a mailbox has zero or one focal chat. Inbound on the focal chat renders via the focal_message template; inbound on a non-focal chat renders via the notification template (which by default includes a $CHAT_LIST footer). Agents shift focus by calling switch_chat(chat_id) on the per-mailbox MCP server, which mutates focal state and returns a recap of the chat's recent history.

The focal paradigm prose lives in InitializeResult.instructions of the per-mailbox MCP server, so it lands in the agent's system prompt without harness involvement.

Quick start

# Postgres
docker run -d --name chatbox-pg -p 5434:5432 \
  -e POSTGRES_USER=chatbox -e POSTGRES_PASSWORD=chatbox -e POSTGRES_DB=chatbox \
  postgres:16-alpine

# Configure
cp .env.example .env
echo "CHATBOX_VAULT_KEY=$(python3 -c 'import base64,secrets; print(base64.b64encode(secrets.token_bytes(32)).decode())')" >> .env

# Install + migrate + bootstrap
uv sync
set -a && source .env && set +a
uv run alembic upgrade head
uv run chatbox bootstrap     # prints the API key once — save it

# Run
uv run chatbox api &

# Health
curl http://localhost:8000/health

See SMOKE_TEST.md for the full operator runbook including connector setup.

API

All endpoints except /health, /metrics, and inbound require Authorization: Bearer <api_key>. Inbound endpoint uses a per-connection inbound_token (returned once at connection creation).

Method Path Purpose
GET /health Service health
GET /metrics Prometheus metrics
POST /v1/mailboxes Create mailbox; returns mcp_url, mcp_token
GET /v1/mailboxes List
GET /v1/mailboxes/:id Get
PUT /v1/mailboxes/:id Update (webhook URL, templates, signing credential)
DELETE /v1/mailboxes/:id Archive
GET /v1/mailboxes/:id/health Delivery health snapshot
POST /v1/mailboxes/:id/unpause Clear paused state
POST /v1/mailboxes/:id/connections Add platform integration
GET /v1/mailboxes/:id/connections List
GET /v1/connections/:id Get
DELETE /v1/connections/:id Archive
POST /v1/credentials Create encrypted credential
GET, PUT, DELETE /v1/credentials/:id Manage
POST /v1/connections/:id/messages Connector → chatbox: inbound message
(MCP) /mcp/:mailbox_id Per-mailbox MCP server

Operator CLI

chatbox migrate                            # Run alembic migrations
chatbox bootstrap                          # Create first account + API key
chatbox api                                # Start the API server
chatbox operator mailbox-list                       # List mailboxes (status, last delivery)
chatbox operator mailbox-health <id>                # Show delivery health
chatbox operator mailbox-unpause <id>               # Clear paused state
chatbox operator mailbox-regenerate-mcp-token <id>  # Rotate the MCP token
chatbox operator connection-list <mailbox_id>       # List connections on a mailbox
chatbox operator connection-archive <conn_id>       # Archive a connection
chatbox operator tail-deliveries <mailbox_id>       # Recent message delivery records

Connectors

Each connector is a separate process that:

  • Calls chatbox's inbound endpoint (POST /v1/connections/:id/messages) when it receives a platform message.
  • Exposes its own MCP server with platform-specific outbound tools (signal_send, telegram_send, etc.) — chatbox's per-mailbox MCP server proxies tool calls to it.

Available:

  • chatbox-signal — Signal via signal-cli (ported from AIOS).
  • chatbox-telegram — Telegram bot via long-polling (ported from AIOS).
  • chatbox-discord — Discord bot via discord.py (built fresh against the contract).
  • chatbox-slack — Slack bot via slack_sdk socket mode (built fresh against the contract).

The contract every connector implements: CONNECTOR_CONTRACT.md.

Testing

# All service tests (requires Docker for testcontainers Postgres).
# On macOS with Docker Desktop, testcontainers may need DOCKER_HOST set;
# discover the socket path with `docker context inspect | jq -r '.[0].Endpoints.docker.Host'`.
CHATBOX_VAULT_KEY=$(python3 -c "import base64,secrets; print(base64.b64encode(secrets.token_bytes(32)).decode())") \
uv run pytest tests/

# Connector tests (no DB)
( cd connectors/signal && uv run pytest )
( cd connectors/telegram && uv run pytest )
( cd connectors/discord && uv run pytest )
( cd connectors/slack && uv run pytest )

Configuration

Env var Required Default Description
CHATBOX_DB_URL yes Postgres URL, e.g. postgresql://chatbox:chatbox@localhost:5434/chatbox
CHATBOX_VAULT_KEY yes Base64-encoded 32-byte master key for AEAD credential storage
CHATBOX_API_HOST no 0.0.0.0 Bind host
CHATBOX_API_PORT no 8000 Bind port
CHATBOX_LOG_LEVEL no INFO Log level

Documentation

License

(unlicensed for now)

About

A standalone service that encapsulates messaging-platform connectors (Signal, Telegram, Discord, Slack) behind a unified API for agents. Per-mailbox MCP server for outbound; webhook delivery for inbound. Owns the focal-attention paradigm so a single agent can hold one focus across many chats and platforms — transparently to the harness.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages