# F3 Picoclaw XMPP An XMPP chatbot bridge that connects an XMPP account to a PicoClaw AI backend via MQTT pub/sub. ## Features - Listens for messages in XMPP chat rooms and direct messages - Responds when mentioned (`@botname`) in group chats - Replies to all direct messages automatically - Forwards incoming messages to PicoClaw over MQTT and streams replies back - Per-sender PicoClaw conversation context (one `client_id` per XMPP user) - Configurable logging levels ## How it works The bridge is a single long-running asyncio service that holds two connections: - One XMPP connection (slixmpp) to your chat account - One persistent MQTT connection (paho-mqtt) to your broker Incoming XMPP messages are published to the PicoClaw request topic, and PicoClaw streams reply chunks back on the response topic. Since PicoClaw's MQTT channel sends no end-of-stream marker, a reply is considered finished after `MQTT_RESPONSE_TIMEOUT` seconds of silence; chunks are forwarded to XMPP live as they arrive. Topics follow PicoClaw's MQTT channel convention: ``` {prefix}/{agent_id}/{client_id}/request # bridge -> PicoClaw {prefix}/{agent_id}/{client_id}/response # PicoClaw -> bridge ``` `client_id` is the (sanitized) bare JID of the XMPP sender, so each user gets an independent conversation. ## Requirements - Python >= 3.10 - [uv](https://docs.astral.sh/uv/) package manager - An MQTT broker (e.g. Mosquitto, EMQX) - A running [PicoClaw](https://github.com/sipeed/picoclaw) gateway with the MQTT channel enabled (`channel_list.mqtt` with the same `agent_id` and `topic_prefix`) ## Setup ```bash # Install dependencies uv sync # Configure environment cp .env.example .env # Edit .env with your XMPP credentials and MQTT settings ``` ## Environment Variables | Variable | Description | |---|---| | `XMPP_USERNAME` | Full JID for the XMPP bot account | | `XMPP_PASSWORD` | XMPP account password | | `XMPP_ROOMS` | Comma-separated list of MUC rooms to join | | `MQTT_BROKER` | MQTT broker URL, e.g. `tcp://host:1883` or `ssl://host:8883` | | `MQTT_USERNAME` | Optional broker username | | `MQTT_PASSWORD` | Optional broker password | | `MQTT_TOPIC_PREFIX` | Topic namespace prefix (default `/picoclaw`) | | `MQTT_AGENT_ID` | PicoClaw agent id used in the topic path (default `assistant`) | | `MQTT_CONN_CLIENT_ID` | Broker-level client id for the bridge's MQTT connection | | `MQTT_QOS` | MQTT QoS for publish/subscribe: `0`, `1`, or `2` (default `0`) | | `MQTT_RESPONSE_TIMEOUT` | Seconds of silence before a streamed reply is considered done (default `30`) | | `DEBUG` | Logging level: `debug`, `info`, `warn`, `error`, `critical` | ## Usage ```bash # Run the XMPP-to-PicoClaw bridge uv run python -m src.server ``` ## Project Structure ``` src/ ├── server.py # Main entry point - bridges XMPP and PicoClaw ├── xmpp.py # XMPP bot client (slixmpp) ├── picoclaw.py # PicoClaw MQTT client (paho-mqtt) └── log.py # Logging configuration ``` ## Tech Stack - Python 3.14 / asyncio - [slixmpp](https://github.com/poezio/slixmpp) for XMPP - [paho-mqtt](https://github.com/eclipse/paho.mqtt.python) for MQTT