Skip to content

130e/msgbot

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

msgbot

A message automation program that essentially process incoming message and forward to designate channel.

Currently 2 services provided:

  • Mail forwarding. It receives email, summarize using agent and forward to telegram chat.
  • Chat. A Telegram group chatbot backed by agent with recent multi-user context.

Services have different requirements. For example, using Chatbot does not require setting up mail routing.

This project is an experiment towards an automation that does the things I need in a way that I understand.

Design

At a high level, the program is event driven and consist of modules and tasks.

A module is a stateful service unit that exposes API to do things. For example, telegram bot module has function to receive update, send messages. I think of them as limbs, claws, jet engine, or plasma cannon installed on msgbot. Not all modules require explicit state and one can simply provide utility functions.

A task describe a workflow. For example, when receiving a mail, send it to agent for summary. Then forward summary to telegram chat. It achieves this by producing a callback handler which will be registered into specified module entry point.

Note: not a plugin system like extensions where a standarized interface is exposed by modules.

Configuration

The program runs as a service and reads configuration from a TOML file:

  • executable ~/.local/bin/msgbot
  • config file ~/.config/msgbot/config.toml

The checked-in config.toml shows the expected shape.

  • [modules.mail] configures the webhook listener, shared secret, and .eml save directory
  • [modules.telegram] configures the bot token and the default destination chat used by forwardmail
  • [modules.agent] chooses passthrough or claude
  • [tasks.forwardmail] enables the mail-to-Telegram workflow
  • [tasks.chat] enables the group-chat reply workflow, chat-specific agent overrides, and chat context/reply limits

Note: modules.agent.type = "passthrough" basically means echo. To enable real LLM agent, switch it to "claude" and fill in [modules.agent.claude].

Local run

Start the service with an explicit config path:

go run . -config ./config.toml

Deploy as systemd service

Build and install into your user account:

go build -o msgbot .
mkdir -p ~/.local/bin ~/.config/msgbot ~/.config/systemd/user ~/msgbot/mail
install -m 0755 msgbot ~/.local/bin/msgbot
cp config.toml ~/.config/msgbot/config.toml
cp deploy/msgbot.service ~/.config/systemd/user/msgbot.service

If you want the service to start at boot even when you are logged out, enable lingering for your user:

sudo loginctl enable-linger "$USER"

Then start the user service:

systemctl --user daemon-reload
systemctl --user enable --now msgbot

Useful commands:

systemctl --user status msgbot
journalctl --user -u msgbot -f
systemctl --user restart msgbot

Service catalog

forwardmail

Receives email, extract email body, summarize using agent, forwards summary to chat, and saves received messages to disk.

For the mail receiving end, it should terminate HTTPS in TLS proxy (Nginx, Caddy, etc) and keep msgbot bound to localhost.

Methodology:

  • the program: this app
  • receive mail: email routed (by cloudflare worker)
  • extract email: plain text or summary generated by LLM
  • forward to chat: send (by telegram bot)
  • save to disk: .eml

Requirement:

  • Valid domain managed by cloudflare
  • Public server (VPS)
  • Time or fixation for configuring Cloudflare

Email ingress config

The example worker.js can be used as the Cloudflare Email Routing ingress that POSTs raw RFC822 bytes to the bot.

In the worker configuration:

  • WEBHOOK_SECRET must match modules.mail.webhook_secret in config.toml
  • SERVER_ENDPOINT should be set to http://{DOMAIN}/email/notify

The webhook listens on http://127.0.0.1:8181/email/notify by default and expects header X-Webhook-Secret.

Reverse proxy behind cloudflare

Setting up reverse proxy behind cloudflare requires additional setup.

  • Create the Origin CA cert in Cloudflare
  • Copy them into server, e.g. /etc/ssl/cloudflare/origin.crt, /etc/ssl/cloudflare/private.key
  • Ensure read permission for proxy
  • Configure proxy to use the certificates

Example using Caddy to proxy the https traffic to msgbot:

example.com {
    tls /etc/ssl/cloudflare/origin.crt /etc/ssl/cloudflare/private.key
    reverse_proxy /email/notify localhost:8181
}

Chat

When [tasks.chat] is enabled, the bot keeps an in-memory recent-message window for each Telegram chat. Every non-empty user text message from a group is recorded.

When someone mentions the bot, it sends the agent an IRC-style transcript of recent messages in chronological order. Human messages are prefixed with their display name, and the bot's own previous chat-task replies are prefixed with [bot]. This history is shared across topics in the same supergroup chat, but the reply is still posted back into the triggering thread.

The chat context is runtime-only and resets on restart. forwardmail messages are not added to chat history.

Available [tasks.chat] settings:

  • enabled: turn the chat task on or off
  • context_max_messages: maximum number of recent chat messages to include, default 24
  • context_window: age limit for chat context, default "12h"
  • max_reply_messages: maximum number of Telegram messages used for one bot reply, default 2
  • agent_max_tokens: token budget passed to the agent for one reply, default 2048
  • agent_model: optional Anthropic model override used only for chat replies; when empty, chat uses modules.agent.anthropic.model
  • web_search_enabled: enable Claude web search for chat replies
  • web_search_max_uses: max Claude web-search tool calls for one reply, default 5

When web_search_enabled=true:

  • Anthropic web search must be enabled in Claude Console for the workspace before deployment
  • msgbot only passes the Claude web-search tool to the API and lets Anthropic decide whether the current model can use it

Chat replies with Claude web search append a plain-text Sources: footer using cited URLs returned by Anthropic.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors