My agentic slop goes here. Not intended for anyone else!

Zulip Echo Bot with Verbose Logging#

An enhanced echo bot that demonstrates the Zulip bot framework with comprehensive logging and CLI configuration. The bot responds to direct messages and mentions by echoing back the message content, with detailed logging at every step.

Features#

  • Responds to direct messages and @mentions in channels
  • Comprehensive logging with multiple verbosity levels
  • Command-line interface with help and configuration options
  • Detailed message tracing for debugging
  • Structured logging using the OCaml logs library
  • Built-in commands: help, ping, and echo
  • Avoids infinite loops by ignoring its own messages

Prerequisites#

  1. A Zulip account and server
  2. A bot user created in Zulip (Settings → Bots → Add a new bot)
  3. OCaml and dependencies installed

Setup#

1. Create a Bot in Zulip#

  1. Go to your Zulip settings
  2. Navigate to "Bots" section
  3. Click "Add a new bot"
  4. Choose "Generic bot" type
  5. Give it a name (e.g., "Echo Bot")
  6. Note down the bot email and API key

2. Configure Authentication#

Create a ~/.zuliprc file with your bot's credentials:

[api]
email=echo-bot@your-domain.zulipchat.com
key=your-bot-api-key
site=https://your-domain.zulipchat.com

Replace the values with your actual bot credentials.

3. Build the Bot#

# From the zulip directory
dune build

# Or build just the echo bot
dune build zulip/examples/echo_bot.exe

Running the Bot#

Basic Usage#

# Show help and available options
dune exec echo_bot -- --help

# Run with default settings (info level logging)
dune exec echo_bot

# Run with verbose logging (shows all info messages)
dune exec echo_bot -- -v

# Run with debug logging (shows everything)
dune exec echo_bot -- -vv

# Use custom config file
dune exec echo_bot -- -c /path/to/bot.zuliprc

# Combine options
dune exec echo_bot -- -vv -c ~/my-bot.zuliprc

Example Output with Different Verbosity Levels#

Default (no flags) - Info level:

echo_bot: [INFO] Starting Zulip Echo Bot
echo_bot: [INFO] Log level: Info
echo_bot: [INFO] =============================

echo_bot: [INFO] Echo bot is running!
echo_bot: [INFO] Send a direct message or mention @echobot in a channel.
echo_bot: [INFO] Commands: 'help', 'ping', or any message to echo
echo_bot: [INFO] Press Ctrl+C to stop.

Verbose (-v) - Info level with more details:

echo_bot: [INFO] Starting Zulip Echo Bot
echo_bot: [INFO] Log level: Info
echo_bot: [INFO] =============================

echo_bot: [INFO] Loaded authentication for: echo-bot@your-domain.zulipchat.com
echo_bot: [INFO] Server: https://your-domain.zulipchat.com
echo_bot: [INFO] Bot identity created: Echo Bot (echo-bot@your-domain.zulipchat.com)
echo_bot: [INFO] Echo bot is running!
echo_bot: [INFO] Processing message with 12 fields
echo_bot: [INFO] Message metadata: type=private, sender=John Doe (john@example.com), id=12345
echo_bot: [INFO] Processing message from John Doe (ID: 123): Hello bot!
echo_bot: [INFO] Sending private reply: Echo from John Doe: Hello bot!

Debug (-vv) - Full debug output:

echo_bot: [INFO] Starting Zulip Echo Bot
echo_bot: [DEBUG] Creating Zulip client
echo_bot: [DEBUG] Creating bot storage for echo-bot@your-domain.zulipchat.com
echo_bot: [DEBUG] Creating bot handler
echo_bot: [DEBUG] Creating bot runner
echo_bot: [DEBUG] Received message for processing
echo_bot: [DEBUG] Extracted field content: Hello bot!
echo_bot: [DEBUG] Extracted field sender_email: john@example.com
echo_bot: [DEBUG] Extracted field sender_full_name: John Doe
echo_bot: [DEBUG] Extracted field type: private
echo_bot: [DEBUG] Extracted field sender_id: 123
echo_bot: [DEBUG] Extracted field id: 12345
echo_bot: [DEBUG] No bot mention to remove
echo_bot: [DEBUG] Generated response: Echo from John Doe: Hello bot!

Testing the Bot#

Direct Message Test#

  1. Open Zulip
  2. Send a direct message to your bot
  3. Type: Hello bot!
  4. The bot should respond: Echo from [Your Name]: Hello bot!

Channel Mention Test#

  1. In any channel, type: @echobot Hello everyone!
  2. The bot should respond: Echo from [Your Name]: Hello everyone!

Special Commands#

  • help - Get usage information
  • ping - Bot responds with "Pong! 🏓"
  • Any other text - Bot echoes it back

How It Works#

The echo bot:

  1. Initializes logging based on CLI verbosity flags
  2. Connects to Zulip using the real-time events API
  3. Listens for messages where it's mentioned or direct messaged
  4. Logs message details at various verbosity levels
  5. Extracts fields with debug logging for each field
  6. Processes content and removes bot mentions
  7. Generates responses with appropriate logging
  8. Sends back echo with type-appropriate reply
  9. Ignores own messages to prevent loops

Code Structure#

  • Logging Setup: Creates a custom log source echo_bot for structured logging
  • Bot Handler Module: Implements the Bot_handler.S signature with comprehensive logging
  • Field Extraction: Helper functions with debug logging for each field
  • Message Processing: Detailed logging of message metadata and content
  • Response Generation: Logs response creation and type determination
  • CLI Interface: Cmdliner-based argument parsing with help text
  • Verbosity Control: Maps CLI flags to log levels (Info/Debug)
  • Error Handling: Catches and logs exceptions with backtraces

Customization#

You can modify the echo bot to:

  • Add more commands (parse for specific keywords)
  • Store conversation history (use Bot_storage)
  • Integrate with external APIs
  • Format responses differently
  • Add emoji reactions

Troubleshooting#

Bot doesn't respond#

  • Check that the bot is actually running (look for console output)
  • Verify the bot has permissions in the channel
  • Check that you're mentioning the bot correctly (@botname)
  • Look for error messages in the console

Authentication errors#

  • Verify your .zuliprc file has the correct credentials
  • Ensure the API key hasn't been regenerated
  • Check that the bot user is active in Zulip

Build errors#

  • Make sure all dependencies are installed: opam install zulip zulip_bot eio_main
  • Clean and rebuild: dune clean && dune build

Next Steps#

Once you have the echo bot working, you can:

  1. Extend it with more complex command parsing
  2. Add persistent storage for user preferences
  3. Integrate with external services
  4. Build more sophisticated bots using the same framework

Example Extensions#

Adding a Command Parser#

let parse_command content =
  match String.split_on_char ' ' content with
  | "!echo" :: rest -> Some ("echo", String.concat " " rest)
  | "!reverse" :: rest -> Some ("reverse", String.concat " " rest)
  | _ -> None

Using Bot Storage#

(* Store user preferences *)
let _ = Bot_storage.put storage ~key:"user_prefs" ~value:"{...}" in

(* Retrieve later *)
let prefs = Bot_storage.get storage ~key:"user_prefs" in

Sending to Specific Channels#

Bot_handler.Response.ChannelMessage {
  channel = "general";
  topic = "Bot Updates";
  content = "Echo bot is online!";
}