From 257da79e9411dd664ebc8e8ae7a150cb3fee2b44 Mon Sep 17 00:00:00 2001 From: Cameron Date: Thu, 5 Feb 2026 10:27:33 -0800 Subject: [PATCH] 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 --- README.md | 2 + docs/README.md | 2 + docs/selfhosted-setup.md | 309 +++++++++++++++++++++++++++++++++++++++ src/main.ts | 9 +- 4 files changed, 318 insertions(+), 4 deletions(-) create mode 100644 docs/selfhosted-setup.md diff --git a/README.md b/README.md index a5f714b..d4d5dba 100644 --- a/README.md +++ b/README.md @@ -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) diff --git a/docs/README.md b/docs/README.md index 7471a74..8a9b1cb 100644 --- a/docs/README.md +++ b/docs/README.md @@ -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 diff --git a/docs/selfhosted-setup.md b/docs/selfhosted-setup.md new file mode 100644 index 0000000..79febdd --- /dev/null +++ b/docs/selfhosted-setup.md @@ -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 + + + + + Label + com.lettabot + ProgramArguments + + /usr/local/bin/npx + lettabot + server + + WorkingDirectory + /path/to/lettabot + RunAtLoad + + KeepAlive + + StandardOutPath + /tmp/lettabot.log + StandardErrorPath + /tmp/lettabot.err + + +``` + +```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) diff --git a/src/main.ts b/src/main.ts index a4382b6..6697259 100644 --- a/src/main.ts +++ b/src/main.ts @@ -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); }