docs: comprehensive documentation audit and improvements (#90)

Fixes and updates:
- README.md: Remove duplicate heartbeat troubleshooting section
- docs/getting-started.md: Fix Node version (18→20), commands, repo URL
- docs/commands.md: Rewrite with accurate command list (/start, /status, /heartbeat)
- docs/README.md: New multi-channel architecture diagram
- docs/whatsapp-setup.md: Add selfChatMode safety docs, media support section
- docs/slack-setup.md: Fix broken links

New documentation:
- docs/configuration.md: Complete YAML config reference
- docs/cron-setup.md: Scheduling guide (cron jobs + heartbeats)

Written by Cameron ◯ Letta Code

"Documentation is a love letter that you write to your future self." - Damian Conway
This commit is contained in:
Cameron
2026-02-02 22:36:06 -08:00
committed by GitHub
parent 3becad2d74
commit 7b6a730df2
8 changed files with 539 additions and 109 deletions

View File

@@ -321,16 +321,6 @@ Check the [ADE](https://app.letta.com) to see if your agent is attempting to use
- Agent doesn't understand it needs to use the CLI
- No delivery target set (user never messaged the bot first)
**Heartbeat/cron messages not reaching my chat**
Heartbeats and cron jobs run in "Silent Mode" - the agent's text output is private and not auto-delivered. To send messages during background tasks, the agent must run:
```bash
lettabot-message send --text "Your message here"
```
Check the [ADE](https://app.letta.com) to see if your agent is attempting to use this command. Common issues:
- Bash tool not enabled (agent can't run CLI commands)
- Agent doesn't understand it needs to use the CLI
- No delivery target set (user never messaged the bot first)
## Documentation
- [Getting Started](docs/getting-started.md)

View File

@@ -1,61 +1,74 @@
# LettaBot Documentation
LettaBot is a Telegram bot powered by [Letta](https://letta.com) that provides persistent memory and local tool execution.
LettaBot is a multi-channel AI assistant powered by [Letta](https://letta.com) that provides persistent memory and local tool execution across Telegram, Slack, Discord, WhatsApp, and Signal.
## Guides
- [Getting Started](./getting-started.md) - Installation and basic setup
- [Configuration Reference](./configuration.md) - All config options
- [Commands Reference](./commands.md) - Bot commands reference
- [Scheduling Tasks](./cron-setup.md) - Cron jobs and heartbeats
- [Gmail Pub/Sub](./gmail-pubsub.md) - Email notifications integration
- [Commands](./commands.md) - Bot commands reference
### Channel Setup
- [Slack Setup](./slack-setup.md) - Socket Mode configuration
- [Discord Setup](./discord-setup.md) - Bot application setup
- [WhatsApp Setup](./whatsapp-setup.md) - Baileys/QR code setup
- [Signal Setup](./signal-setup.md) - signal-cli daemon setup
## Architecture
LettaBot uses a **single agent with unified memory** across all channels:
```
┌──────────────────────────────────────────────────────────────────────┐
┌──────────────────────────────────────────────────────────────────────────
│ Your Server / Machine │
│ │
│ ┌────────────────┐ ┌───────────────────────────────────────┐ │
│ │ Telegram │ │ LettaBot Core │ │
│ │ Bot API │◀──────▶│ (TypeScript/Node) │ │
│ (grammY) │ │ │
└────────────────┘ │ ┌─────────────────────────────────┐ │
│ │ Session Manager
│ │ userId → agentId (persisted)
│ └─────────────────────────────────┘
│ ┌──────────── ┌────────────┐ ┌────────────┐ ┌──────────┐ ┌───────┐ │
│ │ Telegram Slack Discord │ WhatsApp │ │ Signal│ │
│ │ (grammY) │ │ (Socket) │ (Gateway) │(Baileys) │ │ (CLI) │ │
└─────┬──────┘ └─────┬──────┘ └─────┬──────┘ └────┬─────┘ └───┬───┘
│ │ │ │ │
└───────────────┴───────────────┴──────────────┴────────────┘
──────────────────
│ │ LettaBot Core │ │
│ │ (TypeScript) │ │
│ │ │ │
│ ┌─────────────────────────────────┐
│ │ Letta Code SDK
│ createSession/resumeSession │ │
│ └──────────────┬──────────────────┘ │
└─────────────────┼─────────────────────┘
│ spawn subprocess
┌─────────────────────────────────────┐
│ │ Letta Code CLI │ │
│ │ (--input-format stream-json) │ │
• Message Router │
│ • Session Mgmt
│ │ • Heartbeat/Cron │
──────────────────
┌─────────▼─────────┐
Letta Code SDK
│ (subprocess) │
│ │ │ │
│ Local Tool Execution:
│ • Read/Glob/Grep - file ops │
│ • Task - spawn subagents
│ • web_search - internet queries │
└──────────────────┬───────────────────┘
└──────────────────────────────────────────────────────────────────────┘
│ │ Local Tools:
│ │ • Read/Glob/Grep
│ │ • Bash
│ │ • web_search
─────────┬─────────┘
└────────────────────────────────────┼──────────────────────────────────────┘
│ Letta API
┌──────────────────────────────────┐
──────────────────────────┐
│ Letta Server │
(api.letta.com or self-hosted)
(api.letta.com or
│ self-hosted Docker) │
│ │
│ • Agent Memory (persistent)
│ • Agent Memory
│ • LLM Inference │
│ • Conversation History │
└──────────────────────────────────┘
──────────────────────────┘
```
## Key Features
- **Persistent Memory** - Your agent remembers conversations across days/weeks/months
- **Multi-Channel** - Chat across Telegram, Slack, Discord, WhatsApp, and Signal
- **Unified Memory** - Single agent remembers everything from all channels
- **Persistent Memory** - Conversations persist across days/weeks/months
- **Local Tool Execution** - Agent can search files, run commands on your machine
- **Multi-user Support** - Each Telegram user gets their own persistent agent
- **Voice Messages** - Automatic transcription via OpenAI Whisper
- **Streaming Responses** - Real-time message updates as the agent thinks
- **Gmail Integration** - Get email summaries delivered to Telegram
- **Background Tasks** - Heartbeats and cron jobs for proactive actions

View File

@@ -1,6 +1,6 @@
# Commands Reference
LettaBot responds to these slash commands in Telegram.
LettaBot responds to these slash commands in chat channels.
## Available Commands
@@ -9,56 +9,40 @@ LettaBot responds to these slash commands in Telegram.
Shows the welcome message and list of available commands.
```
🤖 LettaBot - AI assistant with persistent memory
LettaBot - AI assistant with persistent memory
Commands:
/new - Start a new conversation (keeps memory)
/reset - Create a new agent (fresh memory)
/status - Show current agent ID
/status - Show current status
/help - Show this message
Just send me a message to get started!
```
### `/new`
Starts a new conversation while keeping the same agent and memory.
Use this when you want to change topics but keep your agent's memory of who you are and past interactions.
**Example:**
```
You: /new
Bot: Started a new conversation. Your agent still remembers you!
You: Let's talk about something different now.
```
### `/reset`
Creates a completely fresh agent with no memory.
Use this if you want to start over from scratch, as if you've never talked to the bot before.
**Warning:** This permanently deletes your agent's memory of past conversations.
**Example:**
```
You: /reset
Bot: Created a fresh agent with no memory. Send a message to begin!
```
### `/status`
Shows your current agent ID.
Shows your current agent ID and connection status.
Useful for debugging or if you need to reference your agent in other tools.
**Example:**
```
You: /status
Bot: Current agent: agent-a1b2c3d4-e5f6-7890-abcd-ef1234567890
Bot: Agent: agent-a1b2c3d4-...
Model: claude-sonnet-4
Channels: telegram, slack
```
### `/heartbeat`
Manually triggers a heartbeat check-in.
Heartbeats are background tasks where the agent can:
- Review pending tasks
- Check reminders
- Perform proactive actions
**Note:** This command runs silently - the agent won't automatically reply. If the agent wants to message you during a heartbeat, it will use the `lettabot-message` CLI.
## Sending Messages
Just type any message to chat with your agent. The agent has:
@@ -82,10 +66,8 @@ The bot supports markdown formatting in responses:
- ```Code blocks```
- [Links](https://example.com)
## Future Commands
Note: Available formatting varies by channel. WhatsApp and Signal have limited markdown support.
These commands are planned for future releases:
## Cross-Channel Commands
- `/model <name>` - Switch the LLM model
- `/verbose` - Toggle tool output visibility
- `/context` - Show memory summary
Commands work the same across all channels (Telegram, Slack, Discord, WhatsApp, Signal). The agent maintains a single conversation across all channels.

217
docs/configuration.md Normal file
View File

@@ -0,0 +1,217 @@
# Configuration Reference
Complete reference for LettaBot configuration options.
## Config File Locations
LettaBot checks these locations in order:
1. `./lettabot.yaml` - Project-local (recommended)
2. `./lettabot.yml` - Project-local alternate
3. `~/.lettabot/config.yaml` - User global
4. `~/.lettabot/config.yml` - User global alternate
## Example Configuration
```yaml
# Server connection
server:
mode: cloud # 'cloud' or 'selfhosted'
apiKey: letta_... # Required for cloud mode
# Agent settings
agent:
name: LettaBot
model: claude-sonnet-4
# id: agent-... # Optional: use existing agent
# Channel configurations
channels:
telegram:
enabled: true
token: "123456:ABC-DEF..."
dmPolicy: pairing
slack:
enabled: true
botToken: xoxb-...
appToken: xapp-...
dmPolicy: pairing
discord:
enabled: true
token: "..."
dmPolicy: pairing
whatsapp:
enabled: true
selfChat: true # IMPORTANT: true for personal numbers
dmPolicy: pairing
signal:
enabled: true
phone: "+1234567890"
selfChat: true
dmPolicy: pairing
# Features
features:
cron: true
heartbeat:
enabled: true
intervalMin: 60
# Voice transcription
transcription:
provider: openai
apiKey: sk-... # Optional: falls back to OPENAI_API_KEY
model: whisper-1
# Attachment handling
attachments:
maxMB: 20
maxAgeDays: 14
```
## Server Configuration
| Option | Type | Description |
|--------|------|-------------|
| `server.mode` | `'cloud'` \| `'selfhosted'` | Connection mode |
| `server.apiKey` | string | API key for Letta Cloud |
| `server.baseUrl` | string | URL for self-hosted server (e.g., `http://localhost:8283`) |
### Self-Hosted Mode
```yaml
server:
mode: selfhosted
baseUrl: http://localhost:8283
```
Run Letta server with Docker:
```bash
docker run -v ~/.letta/.persist/pgdata:/var/lib/postgresql/data \
-p 8283:8283 \
-e OPENAI_API_KEY="..." \
letta/letta:latest
```
## Agent Configuration
| Option | Type | Description |
|--------|------|-------------|
| `agent.id` | string | Use existing agent (skips creation) |
| `agent.name` | string | Name for new agent |
| `agent.model` | string | Model ID (e.g., `claude-sonnet-4`) |
## Channel Configuration
All channels share these common options:
| Option | Type | Description |
|--------|------|-------------|
| `enabled` | boolean | Enable this channel |
| `dmPolicy` | `'pairing'` \| `'allowlist'` \| `'open'` | Access control mode |
| `allowedUsers` | string[] | User IDs/numbers for allowlist mode |
### DM Policies
- **`pairing`** (recommended): New users get a code, approve with `lettabot pairing approve`
- **`allowlist`**: Only specified user IDs can message
- **`open`**: Anyone can message (not recommended)
### Channel-Specific Options
#### Telegram
| Option | Type | Description |
|--------|------|-------------|
| `token` | string | Bot token from @BotFather |
#### Slack
| Option | Type | Description |
|--------|------|-------------|
| `botToken` | string | Bot User OAuth Token (xoxb-...) |
| `appToken` | string | App-Level Token (xapp-...) for Socket Mode |
#### Discord
| Option | Type | Description |
|--------|------|-------------|
| `token` | string | Bot token from Discord Developer Portal |
#### WhatsApp
| Option | Type | Description |
|--------|------|-------------|
| `selfChat` | boolean | **Critical:** `true` = only "Message Yourself" works |
#### Signal
| Option | Type | Description |
|--------|------|-------------|
| `phone` | string | Phone number with + prefix |
| `selfChat` | boolean | `true` = only "Note to Self" works |
## Features Configuration
### Heartbeat
```yaml
features:
heartbeat:
enabled: true
intervalMin: 60 # Check every 60 minutes
```
Heartbeats are background tasks where the agent can review pending work.
### Cron Jobs
```yaml
features:
cron: true
```
Enable scheduled tasks. See [Cron Setup](./cron-setup.md).
## Transcription Configuration
Voice message transcription via OpenAI Whisper:
```yaml
transcription:
provider: openai
apiKey: sk-... # Optional: uses OPENAI_API_KEY env var
model: whisper-1 # Default
```
## Attachments Configuration
```yaml
attachments:
maxMB: 20 # Max file size to download (default: 20)
maxAgeDays: 14 # Auto-delete after N days (default: 14)
```
Attachments are stored in `/tmp/lettabot/attachments/`.
## Environment Variables
Environment variables override config file values:
| Env Variable | Config Equivalent |
|--------------|-------------------|
| `LETTA_API_KEY` | `server.apiKey` |
| `LETTA_BASE_URL` | `server.baseUrl` |
| `LETTA_AGENT_ID` | `agent.id` |
| `LETTA_AGENT_NAME` | `agent.name` |
| `LETTA_MODEL` | `agent.model` |
| `TELEGRAM_BOT_TOKEN` | `channels.telegram.token` |
| `TELEGRAM_DM_POLICY` | `channels.telegram.dmPolicy` |
| `SLACK_BOT_TOKEN` | `channels.slack.botToken` |
| `SLACK_APP_TOKEN` | `channels.slack.appToken` |
| `DISCORD_BOT_TOKEN` | `channels.discord.token` |
| `WHATSAPP_ENABLED` | `channels.whatsapp.enabled` |
| `WHATSAPP_SELF_CHAT_MODE` | `channels.whatsapp.selfChat` |
| `SIGNAL_PHONE_NUMBER` | `channels.signal.phone` |
| `OPENAI_API_KEY` | `transcription.apiKey` |
See [SKILL.md](../SKILL.md) for complete environment variable reference.

181
docs/cron-setup.md Normal file
View File

@@ -0,0 +1,181 @@
# Scheduling Tasks (Cron & Heartbeat)
LettaBot supports two types of background tasks:
- **Cron jobs**: Send scheduled messages at specific times
- **Heartbeats**: Periodic agent check-ins
## Enabling Background Tasks
Add to your `lettabot.yaml`:
```yaml
features:
cron: true
heartbeat:
enabled: true
intervalMin: 60 # Every 60 minutes
```
Or via environment variables:
```bash
CRON_ENABLED=true
HEARTBEAT_ENABLED=true
HEARTBEAT_INTERVAL_MIN=60
```
## Cron Jobs
Schedule tasks that send you messages at specific times.
### Creating a Job
```bash
lettabot-cron create \
--name "Morning Briefing" \
--schedule "0 8 * * *" \
--message "Good morning! Review tasks for today." \
--deliver telegram:123456789
```
**Options:**
- `--name` - Job name (required)
- `--schedule` - Cron expression (required)
- `--message` - Message sent when job runs (required)
- `--deliver` - Where to send: `channel:chatId` (defaults to last messaged chat)
### Managing Jobs
```bash
lettabot-cron list # Show all jobs
lettabot-cron delete <id> # Delete a job
lettabot-cron enable <id> # Enable a job
lettabot-cron disable <id> # Disable a job
```
### Cron Expression Syntax
```
┌───────── minute (0-59)
│ ┌─────── hour (0-23)
│ │ ┌───── day of month (1-31)
│ │ │ ┌─── month (1-12)
│ │ │ │ ┌─ day of week (0-6, Sun=0)
* * * * *
```
**Examples:**
| Expression | When |
|------------|------|
| `0 8 * * *` | Daily at 8:00 AM |
| `0 9 * * 1-5` | Weekdays at 9:00 AM |
| `0 */2 * * *` | Every 2 hours |
| `30 17 * * 5` | Fridays at 5:30 PM |
| `0 0 1 * *` | First of month at midnight |
### Example Jobs
**Daily morning check-in:**
```bash
lettabot-cron create \
-n "Morning" \
-s "0 8 * * *" \
-m "Good morning! What's on today's agenda?"
```
**Weekly review:**
```bash
lettabot-cron create \
-n "Weekly Review" \
-s "0 17 * * 5" \
-m "Friday wrap-up: What did we accomplish this week?"
```
**Hourly reminder:**
```bash
lettabot-cron create \
-n "Hydration" \
-s "0 * * * *" \
-m "Time to drink water!"
```
## Heartbeats
Heartbeats are periodic check-ins where the agent can:
- Review pending tasks
- Check reminders
- Perform proactive actions
### Configuration
```yaml
features:
heartbeat:
enabled: true
intervalMin: 60 # Default: 60 minutes
```
### Manual Trigger
You can trigger a heartbeat manually via the `/heartbeat` command in any channel.
### How It Works
1. At each interval (or when `/heartbeat` is called), the agent receives a heartbeat message
2. The agent runs in **Silent Mode** - responses are not automatically delivered
3. If the agent wants to message you, it must use `lettabot-message send`
This prevents unwanted messages while allowing proactive behavior when needed.
## Silent Mode
Both cron jobs and heartbeats run in **Silent Mode**:
- The agent's text output is NOT automatically sent to users
- The agent sees a `[SILENT MODE]` banner with instructions
- To send messages, the agent must explicitly run:
```bash
lettabot-message send --text "Your message here"
```
**Requirements for background messaging:**
- Bash tool must be enabled for the agent
- A user must have messaged the bot at least once (establishes delivery target)
## Monitoring & Logs
### Check Job Status
```bash
lettabot-cron list
```
Shows:
- Job ID, name, schedule
- Next run time
- Last run status
### Log Files
- `cron-jobs.json` - Job configurations
- `cron-log.jsonl` - Execution logs
## Troubleshooting
### Cron jobs not running
1. Check `features.cron: true` in config
2. Verify schedule expression is valid
3. Check `lettabot-cron list` for next run time
### Agent not sending messages during heartbeat
1. Check if Bash tool is enabled (agent needs to run CLI)
2. Verify a user has messaged the bot at least once
3. Check the [ADE](https://app.letta.com) to see agent activity
### Jobs running but no messages received
The agent runs in Silent Mode - it must actively choose to send messages. Check the agent's behavior in the ADE to see what it's doing during background tasks.

View File

@@ -4,7 +4,7 @@ Get LettaBot running in 5 minutes.
## Prerequisites
- Node.js 18+
- Node.js 20+
- npm or yarn
- A Telegram account
- A Letta account ([app.letta.com](https://app.letta.com))
@@ -14,7 +14,7 @@ Get LettaBot running in 5 minutes.
### 1. Clone and Install
```bash
git clone https://github.com/yourusername/lettabot.git
git clone https://github.com/letta-ai/lettabot.git
cd lettabot
npm install
```
@@ -37,7 +37,9 @@ npm install
**Option A: Interactive Setup (Recommended)**
```bash
npm run setup
npm run build
npm link
lettabot onboard
```
This will walk you through configuration interactively.
@@ -97,4 +99,5 @@ ALLOWED_USERS=123456789,987654321
- [Commands Reference](./commands.md) - Learn all bot commands
- [Gmail Integration](./gmail-pubsub.md) - Set up email notifications
- Check out [PLAN.md](../PLAN.md) for the full roadmap
- [Slack Setup](./slack-setup.md) - Add Slack channel
- [Discord Setup](./discord-setup.md) - Add Discord channel

View File

@@ -211,5 +211,5 @@ First responses may take longer as the agent "wakes up".
## Next Steps
- [WhatsApp Setup](./whatsapp-setup.md)
- [Cron Jobs](./cron-setup.md)
- [Configuration Reference](./configuration.md)
- [Discord Setup](./discord-setup.md)
- [Signal Setup](./signal-setup.md)

View File

@@ -17,19 +17,43 @@ LettaBot connects to WhatsApp using **Baileys**, which uses the WhatsApp Web pro
## Step 1: Enable WhatsApp in Configuration
Add to your `.env` file:
Add to your `lettabot.yaml` or set environment variables:
```yaml
# lettabot.yaml
channels:
whatsapp:
enabled: true
selfChatMode: true # IMPORTANT: See below
dmPolicy: pairing # or 'allowlist' or 'open'
```
Or via environment variables:
```bash
# WhatsApp Configuration
WHATSAPP_ENABLED=true
WHATSAPP_SELF_CHAT_MODE=true # CRITICAL - see below
WHATSAPP_DM_POLICY=pairing
# Optional: Custom session storage path (default: ./data/whatsapp-session)
# WHATSAPP_SESSION_PATH=./data/whatsapp-session
# Optional: Restrict to specific phone numbers
# Optional: Restrict to specific phone numbers (if dmPolicy=allowlist)
# WHATSAPP_ALLOWED_USERS=+15551234567,+15559876543
```
### Self-Chat Mode (Critical Safety Setting)
**`selfChatMode: true`** (default, recommended for personal numbers):
- Bot ONLY responds to "Message Yourself" chat
- Bot will NOT message your contacts
- Safe to use with your personal WhatsApp number
**`selfChatMode: false`** (for dedicated bot numbers):
- Bot responds to ALL incoming messages
- Use ONLY with a dedicated phone number
- Risk of bot messaging your contacts if misconfigured
> **Warning:** If using your personal WhatsApp number, ALWAYS keep `selfChatMode: true` to prevent the bot from accidentally messaging your contacts.
## Step 2: Start LettaBot
```bash
@@ -108,12 +132,31 @@ This uses your personal WhatsApp account:
- Messages appear as coming from your number
- Consider using a dedicated phone number for the bot
- Your contacts will see the bot as "you"
- **Use `selfChatMode: true`** to prevent bot from messaging your contacts
### Multi-Device Limitations
- WhatsApp allows up to 4 linked devices
- The bot counts as one linked device
- If you unlink the bot, you'll need to scan the QR code again
## Media Support
LettaBot supports receiving images, documents, and voice messages:
- **Images**: Downloaded and shown to the agent (agent can view using Read tool)
- **Voice messages**: Automatically transcribed via OpenAI Whisper
- **Documents**: Downloaded with metadata shown to agent
Configure attachment handling in `lettabot.yaml`:
```yaml
attachments:
maxMB: 20 # Max file size to download (default: 20MB)
maxAgeDays: 14 # Auto-delete after N days (default: 14)
```
Attachments are stored in `/tmp/lettabot/attachments/` by default.
## Running in Production
For production deployments:
@@ -150,9 +193,10 @@ If you see "logged out" in the logs:
### Messages Not Being Received
1. Make sure the sender's number is in `WHATSAPP_ALLOWED_USERS` (if configured)
2. Check that the message is a text message (media not fully supported yet)
3. Look for errors in the console
1. Check `selfChatMode` setting - if `true`, only "Message Yourself" works
2. Make sure the sender's number is allowed by `dmPolicy` setting
3. If `dmPolicy: allowlist`, check `allowedUsers` list
4. Look for errors in the console
### Bot Responding to Old Messages
@@ -178,5 +222,5 @@ data/
## Next Steps
- [Slack Setup](./slack-setup.md)
- [Cron Jobs](./cron-setup.md)
- [Configuration Reference](./configuration.md)
- [Discord Setup](./discord-setup.md)
- [Signal Setup](./signal-setup.md)