fix: allow selfhosted mode without LETTA_API_KEY (#160)

Users were confused why selfhosted mode still required an API key.
The validation check now properly skips the API key requirement when
server.mode is 'selfhosted'.

Also adds comprehensive selfhosted-setup.md guide covering:
- Letta Docker server setup
- Network configuration (Docker, remote servers)
- Troubleshooting (connection refused, stuck agent, tool approvals)
- Running as a service (systemd, launchd)
- Hardware requirements

Thanks to oculairthebear for the community guide that inspired this.

Written by Cameron and Letta Code

"I've learned that people will forget what you said, people will forget
what you did, but people will never forget how you made them feel."
- Maya Angelou
This commit is contained in:
Cameron
2026-02-05 10:27:33 -08:00
committed by GitHub
parent 407cd2f18d
commit 257da79e94
4 changed files with 318 additions and 4 deletions

View File

@@ -326,6 +326,8 @@ Check the [ADE](https://app.letta.com) to see if your agent is attempting to use
## Documentation
- [Getting Started](docs/getting-started.md)
- [Self-Hosted Setup](docs/selfhosted-setup.md) - Run with your own Letta server
- [Configuration Reference](docs/configuration.md)
- [Slack Setup](docs/slack-setup.md)
- [Discord Setup](docs/discord-setup.md)
- [WhatsApp Setup](docs/whatsapp-setup.md)

View File

@@ -5,10 +5,12 @@ LettaBot is a multi-channel AI assistant powered by [Letta](https://letta.com) t
## Guides
- [Getting Started](./getting-started.md) - Installation and basic setup
- [Self-Hosted Setup](./selfhosted-setup.md) - Run with your own Letta server
- [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
- [Railway Deployment](./railway-deploy.md) - Deploy to Railway
### Channel Setup
- [Telegram Setup](./telegram-setup.md) - BotFather token setup

309
docs/selfhosted-setup.md Normal file
View File

@@ -0,0 +1,309 @@
# Self-Hosted Letta Server Setup
Run LettaBot with your own Letta server instead of Letta Cloud.
## Prerequisites
1. **Docker** installed and running
2. **Node.js 20+** for LettaBot
3. **API keys** for your LLM provider (OpenAI, Anthropic, etc.)
## Step 1: Start Letta Server
```bash
docker run -d \
--name letta-server \
-v ~/.letta/.persist/pgdata:/var/lib/postgresql/data \
-p 8283:8283 \
-e OPENAI_API_KEY="sk-..." \
letta/letta:latest
```
For Anthropic models:
```bash
docker run -d \
--name letta-server \
-v ~/.letta/.persist/pgdata:/var/lib/postgresql/data \
-p 8283:8283 \
-e ANTHROPIC_API_KEY="sk-ant-..." \
letta/letta:latest
```
Verify it's running:
```bash
curl http://localhost:8283/v1/health
```
## Step 2: Configure LettaBot
### Option A: Interactive Setup (Recommended)
```bash
lettabot onboard
```
Select "Enter self-hosted URL" and enter `http://localhost:8283`.
### Option B: Manual Configuration
Create `lettabot.yaml`:
```yaml
server:
mode: selfhosted
baseUrl: http://localhost:8283
# apiKey: optional-if-server-requires-auth
agent:
name: LettaBot
model: gpt-4o # Or claude-sonnet-4, etc.
channels:
telegram:
enabled: true
token: YOUR_TELEGRAM_BOT_TOKEN # From @BotFather
dmPolicy: pairing # pairing | allowlist | open
features:
cron: false
heartbeat:
enabled: false
```
## Step 3: Start LettaBot
```bash
lettabot server
```
You should see:
```
[Config] Loaded from /path/to/lettabot.yaml
[Config] Mode: selfhosted, Agent: LettaBot, Model: gpt-4o
Starting LettaBot...
LettaBot initialized. Agent ID: (new)
[Telegram] Bot started as @YourBotName
```
## Network Configuration
### Remote Server
If your Letta server is on a different machine:
```yaml
server:
baseUrl: http://192.168.1.100:8283
```
### Docker to Docker
If LettaBot runs in Docker and needs to reach Letta server on the host:
```yaml
server:
baseUrl: http://host.docker.internal:8283
```
### Docker Compose
```yaml
services:
letta:
image: letta/letta:latest
ports:
- "8283:8283"
volumes:
- letta-data:/var/lib/postgresql/data
environment:
- OPENAI_API_KEY=${OPENAI_API_KEY}
lettabot:
build: .
depends_on:
- letta
environment:
- LETTA_BASE_URL=http://letta:8283
volumes:
- ./lettabot.yaml:/app/lettabot.yaml
- ./lettabot-agent.json:/app/lettabot-agent.json
volumes:
letta-data:
```
## Troubleshooting
### Connection Refused
```
Error: connect ECONNREFUSED 127.0.0.1:8283
```
**Fix:** Ensure Letta server is running:
```bash
docker ps | grep letta
curl http://localhost:8283/v1/health
```
### Agent Stuck / Not Responding
If the bot hangs after sending a message:
**1. Check for pending tool approvals**
Some tools may have `requires_approval: true` set. LettaBot disables these on startup, but check:
```bash
# List tools and their approval status
curl http://localhost:8283/v1/agents/YOUR_AGENT_ID/tools | jq '.[].requires_approval'
# Disable approval for a specific tool
curl -X PATCH http://localhost:8283/v1/tools/TOOL_ID \
-H "Content-Type: application/json" \
-d '{"requires_approval": null}'
```
**2. Invalid conversation ID**
If the conversation was deleted but LettaBot still references it:
```bash
# Clear the stored conversation (keeps agent)
cat lettabot-agent.json | jq 'del(.conversationId)' > tmp.json && mv tmp.json lettabot-agent.json
# Restart
lettabot server
```
**3. Check server logs**
```bash
docker logs letta-server --tail 100
```
### Model Not Available
```
Error: Model 'claude-sonnet-4' not found
```
Ensure you set the correct API key when starting Letta server:
- OpenAI models: `-e OPENAI_API_KEY="sk-..."`
- Anthropic models: `-e ANTHROPIC_API_KEY="sk-ant-..."`
### Reset Everything
```bash
# Remove LettaBot state
rm lettabot-agent.json
# Remove Letta server data (WARNING: deletes all agents)
docker stop letta-server
docker rm letta-server
rm -rf ~/.letta/.persist/pgdata
# Restart fresh
docker run ... (same command as before)
lettabot server
```
## Running as a Service
### systemd (Linux)
Create `/etc/systemd/system/lettabot.service`:
```ini
[Unit]
Description=LettaBot - Multi-channel AI Assistant
After=network.target docker.service
Wants=docker.service
[Service]
Type=simple
User=your-user
WorkingDirectory=/path/to/lettabot
ExecStart=/usr/bin/npx lettabot server
Restart=on-failure
RestartSec=10
Environment=NODE_ENV=production
[Install]
WantedBy=multi-user.target
```
```bash
sudo systemctl daemon-reload
sudo systemctl enable lettabot
sudo systemctl start lettabot
# View logs
journalctl -u lettabot -f
```
### launchd (macOS)
Create `~/Library/LaunchAgents/com.lettabot.plist`:
```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.lettabot</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/npx</string>
<string>lettabot</string>
<string>server</string>
</array>
<key>WorkingDirectory</key>
<string>/path/to/lettabot</string>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardOutPath</key>
<string>/tmp/lettabot.log</string>
<key>StandardErrorPath</key>
<string>/tmp/lettabot.err</string>
</dict>
</plist>
```
```bash
launchctl load ~/Library/LaunchAgents/com.lettabot.plist
# View logs
tail -f /tmp/lettabot.log
```
## Hardware Requirements
**Minimum for LettaBot itself:**
- 512MB RAM, 1 CPU core
- LettaBot is lightweight - the heavy lifting is done by Letta server
**For Letta server with cloud LLMs (OpenAI/Anthropic):**
- 2GB RAM, 2 CPU cores
- No GPU required (LLM runs in the cloud)
**For local LLM inference (e.g., Ollama):**
- 16GB+ system RAM for 7B models
- 48GB+ for 70B models
- GPU recommended: 8GB+ VRAM for 7B, 48GB+ for larger
## Security Considerations
1. **Network exposure**: Don't expose port 8283 to the internet without authentication
2. **API keys**: Keep your `.env` and `lettabot.yaml` out of version control
3. **Tool permissions**: Review which tools your agent has access to (Bash can execute arbitrary commands)
4. **DM policy**: Use `pairing` (default) to require approval for new users
## Getting Help
- [GitHub Issues](https://github.com/letta-ai/lettabot/issues)
- [Letta Documentation](https://docs.letta.com)
- [Letta Discord](https://discord.gg/letta)

View File

@@ -304,10 +304,11 @@ if (!config.telegram.enabled && !config.slack.enabled && !config.whatsapp.enable
process.exit(1);
}
// Validate LETTA_API_KEY is set for cloud mode
if (!process.env.LETTA_API_KEY) {
console.error('\n Error: LETTA_API_KEY is required.');
console.error(' Get your API key from https://app.letta.com and set it as an environment variable.\n');
// Validate LETTA_API_KEY is set for cloud mode (selfhosted mode doesn't require it)
if (yamlConfig.server.mode !== 'selfhosted' && !process.env.LETTA_API_KEY) {
console.error('\n Error: LETTA_API_KEY is required for Letta Cloud.');
console.error(' Get your API key from https://app.letta.com and set it as an environment variable.');
console.error(' Or use selfhosted mode: run "lettabot onboard" and select "Enter self-hosted URL".\n');
process.exit(1);
}