Skip to content

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

XChat Agent Skeleton

Starter X Chat bot powered by Grok and Grok Imagine.

Out of the box it is a Grok pass-through: encrypted DMs in, Grok out. /imagine generates (or edits) an image with Grok Imagine and sends it back as an encrypted Chat attachment.

The X Chat crypto, inbox, activity stream, and media path are already working. Put your product in xchat_bot/handler.py.

inbound ciphertext  → Chat XDK decrypt → handler.handle(Message) → Reply
Reply text/image    → Chat XDK encrypt → POST /2/chat/conversations/{id}/messages

Layout

File What it is
xchat_bot/handler.py Customize this. Message in, Reply out.
xchat_bot/grok.py Grok chat completions + Imagine generate/edit
xchat_bot/bot.py Delivery loop (stream, poll, decrypt, send, media)
xchat_bot/chat.py Chat XDK wrapper
xchat_bot/x_api.py X HTTP (/2/chat/*, activity, media)
xchat_bot/store.py SQLite: seen events, cursors, history

Setup

Python 3.10+.

git clone git@github.com:xdevplatform/xchat-agent-skeleton.git
cd xchat-agent-skeleton
python3 -m venv .venv
source .venv/bin/activate
pip install -e .
cp .env.example .env

Fill in .env:

Variable What
X_ACCESS_TOKEN OAuth 2.0 user token for the bot with dm.read dm.write tweet.read users.read media.write
X_BEARER_TOKEN App-only Bearer (inbox discovery via GET /2/activity/stream)
CHAT_BOT_USER_ID Numeric user id of the bot account
CHAT_PRIVATE_KEYS_B64 Chat XDK export_keys blob (recommended)
CHAT_SIGNING_KEY_VERSION Registered public_key_version
XAI_API_KEY xAI key for Grok and Imagine

Then:

python -m xchat_bot.main

Keep that process running. GET /2/chat/conversations only returns the primary inbox. DMs from people who don't follow the bot sit in Message requests. Set X_BEARER_TOKEN so the activity stream can discover those threads. Until then, put handles in CHAT_PEER_USER_IDS or ask people to follow the bot first.

python -m unittest discover -s tests

Default behavior

Anyone who DMs the bot gets a Grok reply, with per-user history.

User sends Bot does
text Grok chat, using stored history
photo (+ optional caption) Grok vision
/imagine a red fox in fog Grok Imagine → encrypted image
photo + /imagine make it a sketch Imagine edit against the attached photo
/reset clears that user's Grok history

Change the voice with GROK_SYSTEM_PROMPT in .env, or edit DEFAULT_SYSTEM_PROMPT in config.py.

Build your bot

handler.py is the product layer. The rest of the process (keys, decrypt, send, media) stays as-is.

from xchat_bot.handler import Message, Reply

class MyBot:
    def handle(self, message: Message) -> Reply:
        if message.text.lower().startswith("/imagine"):
            image = self.grok.imagine(message.text.split(" ", 1)[1])
            return Reply("Here you go.", image)
        answer = self.grok.chat([
            {"role": "system", "content": "You are a travel concierge."},
            {"role": "user", "content": message.text},
        ])
        return Reply(answer)

Wire it in main.py instead of GrokPassthrough. Reply.text is the DM body. Reply.image (optional bytes) is uploaded as encrypted Chat media.

Bots should use a Chat XDK key blob (CHAT_PRIVATE_KEYS_B64), not a Juicebox PIN. Never commit .env, never log plaintext or key material.

About

XChat Bot Skeleton with Grok & Grok Imagine

Resources

Code of conduct

Stars

54 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages