Add Agent Mail multi-workspace deployment guide and scripts
- docs/AGENT_MAIL_DEPLOYMENT.md: 10-step deployment plan for 13 workspaces - docs/AGENT_MAIL_MULTI_WORKSPACE_SETUP.md: Architecture and configuration guide - scripts/setup-agent-mail-workspace.sh: Auto-configure .envrc per workspace - scripts/start-agent-mail-server.sh: Start Agent Mail server - scripts/stop-agent-mail-server.sh: Stop Agent Mail server - scripts/agent-mail-status.sh: Monitor server and all channels Supports 3-channel setup: beads.dev, vc.dev, wyvern.dev Ready for 0.23.0 deployment with Agent Mail integration Amp-Thread-ID: https://ampcode.com/threads/T-bc960efb-3ddc-4635-8c8e-a42a6e9e67d9 Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
643
docs/AGENT_MAIL_DEPLOYMENT.md
Normal file
643
docs/AGENT_MAIL_DEPLOYMENT.md
Normal file
@@ -0,0 +1,643 @@
|
|||||||
|
# Agent Mail Deployment - Last Mile Steps
|
||||||
|
|
||||||
|
Complete step-by-step guide to deploy Agent Mail across all 12 beads-enabled workspaces.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- ✅ MCP Agent Mail package installed at `~/src/mcp_agent_mail/`
|
||||||
|
- ✅ beads integration code completed (just finished)
|
||||||
|
- ✅ Helper scripts created in `scripts/`
|
||||||
|
- ✅ direnv installed (`brew install direnv`)
|
||||||
|
- ✅ direnv hook added to shell config
|
||||||
|
|
||||||
|
## Architecture Overview
|
||||||
|
|
||||||
|
**One Server, Three Channels:**
|
||||||
|
- **Agent Mail Server**: Single instance on `http://127.0.0.1:8765`
|
||||||
|
- **beads.dev**: 5 beads workers communicate here
|
||||||
|
- **vc.dev**: 5 vc workers communicate here
|
||||||
|
- **wyvern.dev**: 3 wyvern workers communicate here
|
||||||
|
|
||||||
|
**Total: 13 workspaces** (12 repos + main beads for version bump)
|
||||||
|
|
||||||
|
## Step 1: Version Bump (5 minutes)
|
||||||
|
|
||||||
|
Since Agent Mail integration is brand new, bump beads version first.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd ~/src/fred/beads
|
||||||
|
|
||||||
|
# Determine new version (check current first)
|
||||||
|
./bd --version
|
||||||
|
# Example output: bd version 0.16.0
|
||||||
|
|
||||||
|
# Bump to next version
|
||||||
|
./scripts/bump-version.sh 0.23.0 --commit
|
||||||
|
|
||||||
|
# Push to trigger release
|
||||||
|
git push origin main
|
||||||
|
git push origin v0.23.0
|
||||||
|
```
|
||||||
|
|
||||||
|
**Rationale:** All workspaces should use the new version with Agent Mail support.
|
||||||
|
|
||||||
|
## Step 2: Start Agent Mail Server (2 minutes)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd ~/src/fred/beads
|
||||||
|
|
||||||
|
# Start server in background
|
||||||
|
./scripts/start-agent-mail-server.sh
|
||||||
|
|
||||||
|
# Expected output:
|
||||||
|
# ✅ Agent Mail server started successfully!
|
||||||
|
# PID: 12345
|
||||||
|
# Health: http://127.0.0.1:8765/health
|
||||||
|
# Web UI: http://127.0.0.1:8765/mail
|
||||||
|
|
||||||
|
# Verify server health
|
||||||
|
curl http://127.0.0.1:8765/health
|
||||||
|
# Expected: {"status": "healthy"}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Troubleshooting:**
|
||||||
|
- If port 8765 in use: `lsof -i :8765` then `kill <PID>`
|
||||||
|
- If server fails: Check `~/agent-mail.log` for errors
|
||||||
|
- If venv missing: See installation steps in `docs/AGENT_MAIL_QUICKSTART.md`
|
||||||
|
|
||||||
|
## Step 3: Configure All Workspaces (10 minutes)
|
||||||
|
|
||||||
|
Run setup script in each workspace to create `.envrc` files.
|
||||||
|
|
||||||
|
### 3a. Configure 5 beads repos
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Main beads repo
|
||||||
|
cd ~/src/beads
|
||||||
|
../fred/beads/scripts/setup-agent-mail-workspace.sh .
|
||||||
|
direnv allow
|
||||||
|
|
||||||
|
# cino/beads fork
|
||||||
|
cd ~/src/cino/beads
|
||||||
|
../../fred/beads/scripts/setup-agent-mail-workspace.sh .
|
||||||
|
direnv allow
|
||||||
|
|
||||||
|
# dave/beads fork
|
||||||
|
cd ~/src/dave/beads
|
||||||
|
../../fred/beads/scripts/setup-agent-mail-workspace.sh .
|
||||||
|
direnv allow
|
||||||
|
|
||||||
|
# emma/beads fork
|
||||||
|
cd ~/src/emma/beads
|
||||||
|
../../fred/beads/scripts/setup-agent-mail-workspace.sh .
|
||||||
|
direnv allow
|
||||||
|
|
||||||
|
# fred/beads fork (current repo)
|
||||||
|
cd ~/src/fred/beads
|
||||||
|
./scripts/setup-agent-mail-workspace.sh .
|
||||||
|
direnv allow
|
||||||
|
```
|
||||||
|
|
||||||
|
**Expected .envrc content:**
|
||||||
|
```bash
|
||||||
|
# Agent Mail Configuration
|
||||||
|
export BEADS_AGENT_MAIL_URL=http://127.0.0.1:8765
|
||||||
|
export BEADS_AGENT_NAME=fred-beads-macbook # (varies by workspace/hostname)
|
||||||
|
export BEADS_PROJECT_ID=beads.dev
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3b. Configure 5 vc repos
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Main vc repo (if standalone exists)
|
||||||
|
cd ~/src/vc
|
||||||
|
../fred/beads/scripts/setup-agent-mail-workspace.sh .
|
||||||
|
direnv allow
|
||||||
|
|
||||||
|
# cino/vc
|
||||||
|
cd ~/src/cino/vc
|
||||||
|
../../fred/beads/scripts/setup-agent-mail-workspace.sh .
|
||||||
|
direnv allow
|
||||||
|
|
||||||
|
# dave/vc
|
||||||
|
cd ~/src/dave/vc
|
||||||
|
../../fred/beads/scripts/setup-agent-mail-workspace.sh .
|
||||||
|
direnv allow
|
||||||
|
|
||||||
|
# fred/vc
|
||||||
|
cd ~/src/fred/vc
|
||||||
|
../../fred/beads/scripts/setup-agent-mail-workspace.sh .
|
||||||
|
direnv allow
|
||||||
|
|
||||||
|
# (One more standalone vc if it exists - adjust path as needed)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Expected PROJECT_ID:** `vc.dev`
|
||||||
|
|
||||||
|
### 3c. Configure 3 wyvern repos
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Main wyvern repo
|
||||||
|
cd ~/src/wyvern
|
||||||
|
../fred/beads/scripts/setup-agent-mail-workspace.sh .
|
||||||
|
direnv allow
|
||||||
|
|
||||||
|
# cino/wyvern
|
||||||
|
cd ~/src/cino/wyvern
|
||||||
|
../../fred/beads/scripts/setup-agent-mail-workspace.sh .
|
||||||
|
direnv allow
|
||||||
|
|
||||||
|
# fred/wyvern
|
||||||
|
cd ~/src/fred/wyvern
|
||||||
|
../../fred/beads/scripts/setup-agent-mail-workspace.sh .
|
||||||
|
direnv allow
|
||||||
|
```
|
||||||
|
|
||||||
|
**Expected PROJECT_ID:** `wyvern.dev`
|
||||||
|
|
||||||
|
## Step 4: Upgrade beads Binary Everywhere (5 minutes)
|
||||||
|
|
||||||
|
After version bump in Step 1, upgrade all workspaces to new version.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Wait for GitHub release to build (check https://github.com/steveyegge/beads/releases)
|
||||||
|
# Or build locally if impatient
|
||||||
|
|
||||||
|
# Option 1: Install from release (when ready)
|
||||||
|
curl -sSL https://raw.githubusercontent.com/steveyegge/beads/main/install.sh | bash
|
||||||
|
|
||||||
|
# Option 2: Build locally and copy to all repos
|
||||||
|
cd ~/src/fred/beads
|
||||||
|
go build -o bd ./cmd/bd
|
||||||
|
|
||||||
|
# Copy to other repos (example for beads repos)
|
||||||
|
cp bd ~/src/beads/bd
|
||||||
|
cp bd ~/src/cino/beads/bd
|
||||||
|
cp bd ~/src/dave/beads/bd
|
||||||
|
cp bd ~/src/emma/beads/bd
|
||||||
|
|
||||||
|
# Verify new version includes Agent Mail support
|
||||||
|
cd ~/src/fred/beads
|
||||||
|
./bd --version
|
||||||
|
# Expected: bd version 0.23.0 (or whatever you bumped to)
|
||||||
|
|
||||||
|
./bd info --json | grep -i agent
|
||||||
|
# Expected: JSON output showing agent_mail config
|
||||||
|
```
|
||||||
|
|
||||||
|
## Step 5: Document Configuration (2 minutes)
|
||||||
|
|
||||||
|
Add Agent Mail config to each workspace's AGENTS.md (if applicable). Agents need these instructions before testing.
|
||||||
|
|
||||||
|
Example for vc repos:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd ~/src/fred/vc
|
||||||
|
|
||||||
|
# Add to AGENTS.md (or create if missing)
|
||||||
|
cat >> AGENTS.md <<'EOF'
|
||||||
|
|
||||||
|
## Agent Mail Configuration
|
||||||
|
|
||||||
|
This workspace participates in multi-agent coordination via MCP Agent Mail.
|
||||||
|
|
||||||
|
**Channel**: vc.dev (shared with all vc workers)
|
||||||
|
**Server**: http://127.0.0.1:8765
|
||||||
|
**Agent Name**: fred-vc-<hostname>
|
||||||
|
|
||||||
|
**Configuration**: Loaded automatically via `.envrc` (direnv)
|
||||||
|
|
||||||
|
**Tightly coupled workers**:
|
||||||
|
- ~/src/vc
|
||||||
|
- ~/src/cino/vc
|
||||||
|
- ~/src/dave/vc
|
||||||
|
- ~/src/fred/vc
|
||||||
|
- (one more standalone)
|
||||||
|
|
||||||
|
All vc workers coordinate issue reservations in real-time (<100ms latency).
|
||||||
|
|
||||||
|
**Cross-project coordination**: vc → beads bugs filed via git/PRs (not Agent Mail messaging)
|
||||||
|
|
||||||
|
See `docs/AGENT_MAIL_MULTI_WORKSPACE_SETUP.md` for details.
|
||||||
|
EOF
|
||||||
|
```
|
||||||
|
|
||||||
|
Repeat for beads and wyvern workspaces with appropriate channel names.
|
||||||
|
|
||||||
|
## Step 6: Test Same-Channel Coordination (5 minutes)
|
||||||
|
|
||||||
|
Verify agents in same channel can see each other's reservations.
|
||||||
|
|
||||||
|
### 6a. Test vc.dev channel (2 vc repos)
|
||||||
|
|
||||||
|
**Terminal 1 - fred/vc:**
|
||||||
|
```bash
|
||||||
|
cd ~/src/fred/vc
|
||||||
|
|
||||||
|
# Verify env vars
|
||||||
|
echo $BEADS_PROJECT_ID # Expected: vc.dev
|
||||||
|
echo $BEADS_AGENT_NAME # Expected: fred-vc-<hostname>
|
||||||
|
|
||||||
|
# Create test issue and reserve it
|
||||||
|
bd create "Test Agent Mail coordination" -p 2 -t task
|
||||||
|
# Example output: bd-test42
|
||||||
|
|
||||||
|
bd update bd-test42 --status in_progress
|
||||||
|
# Expected: ✅ Reserved bd-test42 for fred-vc-macbook
|
||||||
|
```
|
||||||
|
|
||||||
|
**Terminal 2 - cino/vc:**
|
||||||
|
```bash
|
||||||
|
cd ~/src/cino/vc
|
||||||
|
|
||||||
|
# Verify env vars
|
||||||
|
echo $BEADS_PROJECT_ID # Expected: vc.dev
|
||||||
|
echo $BEADS_AGENT_NAME # Expected: cino-vc-<hostname>
|
||||||
|
|
||||||
|
# Try to claim same issue
|
||||||
|
bd update bd-test42 --status in_progress
|
||||||
|
# Expected: ❌ Error - bd-test42 already reserved by fred-vc-macbook
|
||||||
|
```
|
||||||
|
|
||||||
|
**Success!** Collision prevented across different repos in same channel.
|
||||||
|
|
||||||
|
**Terminal 1 - Cleanup:**
|
||||||
|
```bash
|
||||||
|
cd ~/src/fred/vc
|
||||||
|
bd close bd-test42 "Test complete"
|
||||||
|
# Expected: ✅ Reservation released
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6b. Test channel isolation
|
||||||
|
|
||||||
|
Verify agents in different channels DON'T interfere.
|
||||||
|
|
||||||
|
**Terminal 1 - fred/beads (beads.dev):**
|
||||||
|
```bash
|
||||||
|
cd ~/src/fred/beads
|
||||||
|
bd create "Test channel isolation" -p 2
|
||||||
|
# Example: Created bd-test1
|
||||||
|
|
||||||
|
bd update bd-test1 --status in_progress
|
||||||
|
# Expected: Success
|
||||||
|
```
|
||||||
|
|
||||||
|
**Terminal 2 - fred/vc (vc.dev):**
|
||||||
|
```bash
|
||||||
|
cd ~/src/fred/vc
|
||||||
|
bd create "Test channel isolation" -p 2
|
||||||
|
# Example: Created bd-test2
|
||||||
|
|
||||||
|
bd update bd-test2 --status in_progress
|
||||||
|
# Expected: Success (no conflict - different channel!)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Both reservations succeed** because they're in different channels.
|
||||||
|
|
||||||
|
## Step 7: Monitor All Channels (2 minutes)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd ~/src/fred/beads
|
||||||
|
|
||||||
|
# Check overall status
|
||||||
|
./scripts/agent-mail-status.sh
|
||||||
|
|
||||||
|
# Expected output:
|
||||||
|
# === Agent Mail Status ===
|
||||||
|
# Server Process: ✅ Running (PID: 12345)
|
||||||
|
# Server Health: ✅ OK
|
||||||
|
# Active Projects:
|
||||||
|
# • beads.dev
|
||||||
|
# • vc.dev
|
||||||
|
# • wyvern.dev
|
||||||
|
# Active File Reservations:
|
||||||
|
# (list of current reservations across all channels)
|
||||||
|
|
||||||
|
# Open Web UI for visual monitoring
|
||||||
|
open http://127.0.0.1:8765/mail
|
||||||
|
```
|
||||||
|
|
||||||
|
## Step 8: Make Server Auto-Start on Reboot (Optional, 5 minutes)
|
||||||
|
|
||||||
|
Use macOS launchd for automatic server startup.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create launchd plist
|
||||||
|
cat > ~/Library/LaunchAgents/com.user.mcp-agent-mail.plist <<'EOF'
|
||||||
|
<?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.user.mcp-agent-mail</string>
|
||||||
|
<key>ProgramArguments</key>
|
||||||
|
<array>
|
||||||
|
<string>/Users/stevey/src/mcp_agent_mail/.venv/bin/python</string>
|
||||||
|
<string>-m</string>
|
||||||
|
<string>mcp_agent_mail.cli</string>
|
||||||
|
<string>serve-http</string>
|
||||||
|
<string>--host</string>
|
||||||
|
<string>127.0.0.1</string>
|
||||||
|
<string>--port</string>
|
||||||
|
<string>8765</string>
|
||||||
|
</array>
|
||||||
|
<key>WorkingDirectory</key>
|
||||||
|
<string>/Users/stevey/src/mcp_agent_mail</string>
|
||||||
|
<key>StandardOutPath</key>
|
||||||
|
<string>/Users/stevey/agent-mail.log</string>
|
||||||
|
<key>StandardErrorPath</key>
|
||||||
|
<string>/Users/stevey/agent-mail-error.log</string>
|
||||||
|
<key>RunAtLoad</key>
|
||||||
|
<true/>
|
||||||
|
<key>KeepAlive</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Load service
|
||||||
|
launchctl load ~/Library/LaunchAgents/com.user.mcp-agent-mail.plist
|
||||||
|
|
||||||
|
# Verify loaded
|
||||||
|
launchctl list | grep mcp-agent-mail
|
||||||
|
# Expected: Shows PID and status
|
||||||
|
|
||||||
|
# Test restart
|
||||||
|
sudo reboot # (or just log out/in)
|
||||||
|
# After reboot, verify server auto-started:
|
||||||
|
curl http://127.0.0.1:8765/health
|
||||||
|
```
|
||||||
|
|
||||||
|
## Step 9: Auto-Start on Reboot (Optional, 5 minutes)
|
||||||
|
|
||||||
|
Use macOS launchd for automatic server startup.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create launchd plist
|
||||||
|
cat > ~/Library/LaunchAgents/com.user.mcp-agent-mail.plist <<'EOF'
|
||||||
|
<?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.user.mcp-agent-mail</string>
|
||||||
|
<key>ProgramArguments</key>
|
||||||
|
<array>
|
||||||
|
<string>/Users/stevey/src/mcp_agent_mail/.venv/bin/python</string>
|
||||||
|
<string>-m</string>
|
||||||
|
<string>mcp_agent_mail.cli</string>
|
||||||
|
<string>serve-http</string>
|
||||||
|
<string>--host</string>
|
||||||
|
<string>127.0.0.1</string>
|
||||||
|
<string>--port</string>
|
||||||
|
<string>8765</string>
|
||||||
|
</array>
|
||||||
|
<key>WorkingDirectory</key>
|
||||||
|
<string>/Users/stevey/src/mcp_agent_mail</string>
|
||||||
|
<key>StandardOutPath</key>
|
||||||
|
<string>/Users/stevey/agent-mail.log</string>
|
||||||
|
<key>StandardErrorPath</key>
|
||||||
|
<string>/Users/stevey/agent-mail-error.log</string>
|
||||||
|
<key>RunAtLoad</key>
|
||||||
|
<true/>
|
||||||
|
<key>KeepAlive</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Load service
|
||||||
|
launchctl load ~/Library/LaunchAgents/com.user.mcp-agent-mail.plist
|
||||||
|
|
||||||
|
# Verify loaded
|
||||||
|
launchctl list | grep mcp-agent-mail
|
||||||
|
# Expected: Shows PID and status
|
||||||
|
|
||||||
|
# Test restart
|
||||||
|
sudo reboot # (or just log out/in)
|
||||||
|
# After reboot, verify server auto-started:
|
||||||
|
curl http://127.0.0.1:8765/health
|
||||||
|
```
|
||||||
|
|
||||||
|
## Step 10: Verification Checklist
|
||||||
|
|
||||||
|
Run through this checklist to confirm deployment success.
|
||||||
|
|
||||||
|
### ✅ Server Health
|
||||||
|
- [ ] `curl http://127.0.0.1:8765/health` returns `{"status": "healthy"}`
|
||||||
|
- [ ] PID file exists: `cat ~/agent-mail.pid`
|
||||||
|
- [ ] Process running: `ps -p $(cat ~/agent-mail.pid)`
|
||||||
|
- [ ] Logs clean: `tail ~/agent-mail.log` (no errors)
|
||||||
|
|
||||||
|
### ✅ Workspace Configuration
|
||||||
|
- [ ] All 13 workspaces have `.envrc` files
|
||||||
|
- [ ] All `.envrc` files have correct `BEADS_PROJECT_ID`:
|
||||||
|
- 5 beads repos → `beads.dev`
|
||||||
|
- 5 vc repos → `vc.dev`
|
||||||
|
- 3 wyvern repos → `wyvern.dev`
|
||||||
|
- [ ] All workspaces allowed: `direnv allow` in each
|
||||||
|
- [ ] Env vars load automatically when `cd`-ing into workspace
|
||||||
|
|
||||||
|
### ✅ beads Binary
|
||||||
|
- [ ] All workspaces using new version with Agent Mail support
|
||||||
|
- [ ] `bd --version` shows 0.23.0+ everywhere
|
||||||
|
- [ ] `bd info --json | grep agent_mail` shows config
|
||||||
|
|
||||||
|
### ✅ Multi-Agent Coordination
|
||||||
|
- [ ] Same channel: Reservation conflict works (tested in Step 6a)
|
||||||
|
- [ ] Different channels: No interference (tested in Step 6b)
|
||||||
|
- [ ] Web UI shows all 3 channels: http://127.0.0.1:8765/mail
|
||||||
|
- [ ] Status script works: `./scripts/agent-mail-status.sh`
|
||||||
|
|
||||||
|
### ✅ Persistence
|
||||||
|
- [ ] Server survives reboot (if launchd configured in Step 8)
|
||||||
|
- [ ] Reservations cleared on server restart (expected behavior)
|
||||||
|
- [ ] Agents re-register automatically after server restart
|
||||||
|
|
||||||
|
## Common Issues
|
||||||
|
|
||||||
|
### Issue: direnv not loading .envrc
|
||||||
|
|
||||||
|
**Symptoms:**
|
||||||
|
```bash
|
||||||
|
cd ~/src/fred/beads
|
||||||
|
echo $BEADS_PROJECT_ID
|
||||||
|
# (empty output)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Fix:**
|
||||||
|
```bash
|
||||||
|
# Check direnv hook installed
|
||||||
|
grep direnv ~/.zshrc
|
||||||
|
# Should see: eval "$(direnv hook zsh)"
|
||||||
|
|
||||||
|
# If missing, add it
|
||||||
|
echo 'eval "$(direnv hook zsh)"' >> ~/.zshrc
|
||||||
|
source ~/.zshrc
|
||||||
|
|
||||||
|
# Allow .envrc
|
||||||
|
cd ~/src/fred/beads
|
||||||
|
direnv allow
|
||||||
|
```
|
||||||
|
|
||||||
|
### Issue: Agent names collide
|
||||||
|
|
||||||
|
**Symptoms:** Two workspaces use same `BEADS_AGENT_NAME`
|
||||||
|
|
||||||
|
**Fix:** Edit `.envrc` to make agent names unique:
|
||||||
|
```bash
|
||||||
|
# Bad (collision!)
|
||||||
|
export BEADS_AGENT_NAME=fred-beads-macbook # Same in fred/beads and fred/vc
|
||||||
|
|
||||||
|
# Good (unique)
|
||||||
|
export BEADS_AGENT_NAME=fred-beads-macbook # In fred/beads
|
||||||
|
export BEADS_AGENT_NAME=fred-vc-macbook # In fred/vc
|
||||||
|
```
|
||||||
|
|
||||||
|
The `setup-agent-mail-workspace.sh` script already handles this by including workspace name.
|
||||||
|
|
||||||
|
### Issue: Server not accessible
|
||||||
|
|
||||||
|
**Symptoms:**
|
||||||
|
```bash
|
||||||
|
bd update bd-42 --status in_progress
|
||||||
|
# WARN Agent Mail unavailable, falling back to git-only mode
|
||||||
|
```
|
||||||
|
|
||||||
|
**Fix:**
|
||||||
|
```bash
|
||||||
|
# Check server health
|
||||||
|
curl http://127.0.0.1:8765/health
|
||||||
|
# If unreachable, restart server:
|
||||||
|
./scripts/stop-agent-mail-server.sh
|
||||||
|
./scripts/start-agent-mail-server.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### Issue: Old reservations stuck
|
||||||
|
|
||||||
|
**Symptoms:** Agent crashed but reservation persists
|
||||||
|
|
||||||
|
**Fix:**
|
||||||
|
```bash
|
||||||
|
# Option 1: Release via API
|
||||||
|
curl -X DELETE http://127.0.0.1:8765/api/reservations/bd-stuck
|
||||||
|
|
||||||
|
# Option 2: Restart server (clears all)
|
||||||
|
./scripts/stop-agent-mail-server.sh
|
||||||
|
./scripts/start-agent-mail-server.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
## Maintenance
|
||||||
|
|
||||||
|
### Daily Operations
|
||||||
|
|
||||||
|
**Start/stop server manually:**
|
||||||
|
```bash
|
||||||
|
cd ~/src/fred/beads
|
||||||
|
./scripts/start-agent-mail-server.sh
|
||||||
|
./scripts/stop-agent-mail-server.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
**Check status:**
|
||||||
|
```bash
|
||||||
|
./scripts/agent-mail-status.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
**View logs:**
|
||||||
|
```bash
|
||||||
|
tail -f ~/agent-mail.log
|
||||||
|
```
|
||||||
|
|
||||||
|
**Monitor Web UI:**
|
||||||
|
```bash
|
||||||
|
open http://127.0.0.1:8765/mail
|
||||||
|
```
|
||||||
|
|
||||||
|
### Upgrading beads
|
||||||
|
|
||||||
|
When you bump beads version in the future:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd ~/src/fred/beads
|
||||||
|
|
||||||
|
# Bump version
|
||||||
|
./scripts/bump-version.sh 0.24.0 --commit
|
||||||
|
git push origin main
|
||||||
|
git push origin v0.24.0
|
||||||
|
|
||||||
|
# Wait for release, then upgrade all workspaces
|
||||||
|
curl -sSL https://raw.githubusercontent.com/steveyegge/beads/main/install.sh | bash
|
||||||
|
|
||||||
|
# Or rebuild locally and distribute
|
||||||
|
go build -o bd ./cmd/bd
|
||||||
|
# ... copy to other repos
|
||||||
|
```
|
||||||
|
|
||||||
|
### Adding New Workspaces
|
||||||
|
|
||||||
|
To add a new workspace to Agent Mail coordination:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Example: Adding ~/src/gina/beads
|
||||||
|
cd ~/src/gina/beads
|
||||||
|
|
||||||
|
# Run setup script
|
||||||
|
~/src/fred/beads/scripts/setup-agent-mail-workspace.sh .
|
||||||
|
|
||||||
|
# Allow direnv
|
||||||
|
direnv allow
|
||||||
|
|
||||||
|
# Verify configuration
|
||||||
|
echo $BEADS_PROJECT_ID
|
||||||
|
# Expected: beads.dev (or vc.dev/wyvern.dev)
|
||||||
|
|
||||||
|
# Test reservation
|
||||||
|
bd ready | head -1 | xargs -I {} bd update {} --status in_progress
|
||||||
|
# Should work immediately
|
||||||
|
```
|
||||||
|
|
||||||
|
## Success Criteria
|
||||||
|
|
||||||
|
You've successfully deployed Agent Mail when:
|
||||||
|
|
||||||
|
1. ✅ **Server running**: `curl http://127.0.0.1:8765/health` returns healthy
|
||||||
|
2. ✅ **All workspaces configured**: 13 `.envrc` files created and allowed
|
||||||
|
3. ✅ **Three channels active**: beads.dev, vc.dev, wyvern.dev visible in Web UI
|
||||||
|
4. ✅ **Coordination works**: Reservation conflict test passes (Step 6a)
|
||||||
|
5. ✅ **Isolation works**: Different channels don't interfere (Step 6b)
|
||||||
|
6. ✅ **Monitoring works**: Status script shows all active projects
|
||||||
|
7. ✅ **Auto-start works**: Server survives reboot (if Step 8 completed)
|
||||||
|
|
||||||
|
## Next Steps
|
||||||
|
|
||||||
|
After successful deployment:
|
||||||
|
|
||||||
|
1. **Start using bd normally** - Agent Mail coordination happens automatically
|
||||||
|
2. **Monitor reservations** via Web UI during concurrent work
|
||||||
|
3. **File issues** for any coordination bugs (rare with hash-based IDs)
|
||||||
|
4. **Consider MCP integration** for Claude Desktop (see `docs/AGENT_MAIL_QUICKSTART.md`)
|
||||||
|
5. **Wait for cross-project messaging** (planned in Agent Mail roadmap)
|
||||||
|
|
||||||
|
## Reference
|
||||||
|
|
||||||
|
- **Main Guide**: [AGENT_MAIL_MULTI_WORKSPACE_SETUP.md](AGENT_MAIL_MULTI_WORKSPACE_SETUP.md)
|
||||||
|
- **Quick Start**: [AGENT_MAIL_QUICKSTART.md](AGENT_MAIL_QUICKSTART.md)
|
||||||
|
- **Architecture**: [AGENT_MAIL.md](AGENT_MAIL.md)
|
||||||
|
- **ADR**: [adr/002-agent-mail-integration.md](../adr/002-agent-mail-integration.md)
|
||||||
|
|
||||||
|
## Timeline Estimate
|
||||||
|
|
||||||
|
- **Step 1** (Version bump): 5 minutes
|
||||||
|
- **Step 2** (Start server): 2 minutes
|
||||||
|
- **Step 3** (Configure 13 workspaces): 10 minutes
|
||||||
|
- **Step 4** (Upgrade binaries): 5 minutes
|
||||||
|
- **Step 5** (Document): 2 minutes
|
||||||
|
- **Step 6** (Same-channel test): 5 minutes
|
||||||
|
- **Step 7** (Channel isolation test): 5 minutes
|
||||||
|
- **Step 8** (Monitor): 2 minutes
|
||||||
|
- **Step 9** (Auto-start, optional): 5 minutes
|
||||||
|
- **Step 10** (Verify checklist): 5 minutes
|
||||||
|
|
||||||
|
**Total: ~46 minutes** (or ~41 minutes if skipping auto-start)
|
||||||
|
|
||||||
|
You're ready to deploy! 🚀
|
||||||
345
docs/AGENT_MAIL_MULTI_WORKSPACE_SETUP.md
Normal file
345
docs/AGENT_MAIL_MULTI_WORKSPACE_SETUP.md
Normal file
@@ -0,0 +1,345 @@
|
|||||||
|
# Multi-Workspace Agent Mail Setup
|
||||||
|
|
||||||
|
Guide for running Agent Mail across multiple beads repositories.
|
||||||
|
|
||||||
|
## Service Management
|
||||||
|
|
||||||
|
### Start Agent Mail Server (One Instance for All Projects)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Start in background with nohup
|
||||||
|
cd ~/src/mcp_agent_mail
|
||||||
|
source .venv/bin/activate
|
||||||
|
nohup python -m mcp_agent_mail.cli serve-http --host 127.0.0.1 --port 8765 > ~/agent-mail.log 2>&1 &
|
||||||
|
echo $! > ~/agent-mail.pid
|
||||||
|
```
|
||||||
|
|
||||||
|
### Check Server Status
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Health check
|
||||||
|
curl http://127.0.0.1:8765/health
|
||||||
|
|
||||||
|
# View logs
|
||||||
|
tail -f ~/agent-mail.log
|
||||||
|
|
||||||
|
# Check process
|
||||||
|
ps aux | grep mcp_agent_mail
|
||||||
|
# Or use saved PID
|
||||||
|
ps -p $(cat ~/agent-mail.pid) || echo "Server not running"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Restart Server
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Kill old server
|
||||||
|
kill $(cat ~/agent-mail.pid) 2>/dev/null || pkill -f mcp_agent_mail
|
||||||
|
|
||||||
|
# Start fresh
|
||||||
|
cd ~/src/mcp_agent_mail
|
||||||
|
source .venv/bin/activate
|
||||||
|
nohup python -m mcp_agent_mail.cli serve-http --host 127.0.0.1 --port 8765 > ~/agent-mail.log 2>&1 &
|
||||||
|
echo $! > ~/agent-mail.pid
|
||||||
|
```
|
||||||
|
|
||||||
|
### Auto-Start on Reboot (macOS launchd)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create ~/Library/LaunchAgents/com.user.mcp-agent-mail.plist
|
||||||
|
cat > ~/Library/LaunchAgents/com.user.mcp-agent-mail.plist <<'EOF'
|
||||||
|
<?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.user.mcp-agent-mail</string>
|
||||||
|
<key>ProgramArguments</key>
|
||||||
|
<array>
|
||||||
|
<string>/Users/stevey/src/mcp_agent_mail/.venv/bin/python</string>
|
||||||
|
<string>-m</string>
|
||||||
|
<string>mcp_agent_mail.cli</string>
|
||||||
|
<string>serve-http</string>
|
||||||
|
<string>--host</string>
|
||||||
|
<string>127.0.0.1</string>
|
||||||
|
<string>--port</string>
|
||||||
|
<string>8765</string>
|
||||||
|
</array>
|
||||||
|
<key>WorkingDirectory</key>
|
||||||
|
<string>/Users/stevey/src/mcp_agent_mail</string>
|
||||||
|
<key>StandardOutPath</key>
|
||||||
|
<string>/Users/stevey/agent-mail.log</string>
|
||||||
|
<key>StandardErrorPath</key>
|
||||||
|
<string>/Users/stevey/agent-mail-error.log</string>
|
||||||
|
<key>RunAtLoad</key>
|
||||||
|
<true/>
|
||||||
|
<key>KeepAlive</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Load service
|
||||||
|
launchctl load ~/Library/LaunchAgents/com.user.mcp-agent-mail.plist
|
||||||
|
|
||||||
|
# Check status
|
||||||
|
launchctl list | grep mcp-agent-mail
|
||||||
|
```
|
||||||
|
|
||||||
|
## Project Configuration Strategy
|
||||||
|
|
||||||
|
**Three team channels** for tightly-coupled workers:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
beads.dev → All beads workers (5 repos)
|
||||||
|
vc.dev → All vc workers (5 repos)
|
||||||
|
wyvern.dev → All wyvern workers (3 repos)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Why this design:**
|
||||||
|
- Each team's workers are tightly coupled and need frequent coordination
|
||||||
|
- Simple namespace strings (no filesystem paths required)
|
||||||
|
- Usenet-style naming for clarity
|
||||||
|
- Cross-project filing handled via git/PRs for now (until Agent Mail adds cross-project messaging)
|
||||||
|
|
||||||
|
### Configuration by Workspace
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# All beads repos use same project
|
||||||
|
~/src/beads → BEADS_PROJECT_ID=beads.dev
|
||||||
|
~/src/cino/beads → BEADS_PROJECT_ID=beads.dev
|
||||||
|
~/src/dave/beads → BEADS_PROJECT_ID=beads.dev
|
||||||
|
~/src/emma/beads → BEADS_PROJECT_ID=beads.dev
|
||||||
|
~/src/fred/beads → BEADS_PROJECT_ID=beads.dev
|
||||||
|
|
||||||
|
# All vc repos use same project
|
||||||
|
~/src/cino/vc → BEADS_PROJECT_ID=vc.dev
|
||||||
|
~/src/dave/vc → BEADS_PROJECT_ID=vc.dev
|
||||||
|
~/src/fred/vc → BEADS_PROJECT_ID=vc.dev
|
||||||
|
~/src/vc → BEADS_PROJECT_ID=vc.dev
|
||||||
|
(standalone at ~/src/vc if exists)
|
||||||
|
|
||||||
|
# All wyvern repos use same project
|
||||||
|
~/src/cino/wyvern → BEADS_PROJECT_ID=wyvern.dev
|
||||||
|
~/src/fred/wyvern → BEADS_PROJECT_ID=wyvern.dev
|
||||||
|
~/src/wyvern → BEADS_PROJECT_ID=wyvern.dev
|
||||||
|
```
|
||||||
|
|
||||||
|
## Per-Directory Configuration
|
||||||
|
|
||||||
|
Create `.envrc` or `.env` file in each workspace:
|
||||||
|
|
||||||
|
### Example: ~/src/fred/vc/.envrc
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Agent Mail Configuration for fred's vc
|
||||||
|
export BEADS_AGENT_MAIL_URL=http://127.0.0.1:8765
|
||||||
|
export BEADS_AGENT_NAME=fred-vc-$(hostname)
|
||||||
|
export BEADS_PROJECT_ID=vc.dev
|
||||||
|
|
||||||
|
# Load with direnv
|
||||||
|
# Install direnv: brew install direnv
|
||||||
|
# Then: direnv allow
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example: ~/src/cino/beads/.envrc
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Agent Mail Configuration for cino's beads fork
|
||||||
|
export BEADS_AGENT_MAIL_URL=http://127.0.0.1:8765
|
||||||
|
export BEADS_AGENT_NAME=cino-beads-$(hostname)
|
||||||
|
export BEADS_PROJECT_ID=beads.dev
|
||||||
|
```
|
||||||
|
|
||||||
|
### Quick Setup Script
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
# setup-agent-mail.sh - Run in each workspace
|
||||||
|
|
||||||
|
WORKSPACE=$(pwd)
|
||||||
|
WORKSPACE_NAME=$(basename $WORKSPACE)
|
||||||
|
PARENT=$(basename $(dirname $WORKSPACE))
|
||||||
|
|
||||||
|
# Determine project ID based on coupling
|
||||||
|
case "$WORKSPACE_NAME" in
|
||||||
|
vc|wyvern)
|
||||||
|
# Tightly coupled - use parent coordination project
|
||||||
|
PROJECT_ID="/Users/stevey/src/${PARENT}/coordination"
|
||||||
|
;;
|
||||||
|
beads)
|
||||||
|
# Loosely coupled - use workspace as project
|
||||||
|
PROJECT_ID="$WORKSPACE"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
# Default - use workspace
|
||||||
|
PROJECT_ID="$WORKSPACE"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
cat > .envrc <<EOF
|
||||||
|
# Agent Mail Configuration
|
||||||
|
export BEADS_AGENT_MAIL_URL=http://127.0.0.1:8765
|
||||||
|
export BEADS_AGENT_NAME=${PARENT}-${WORKSPACE_NAME}-\$(hostname)
|
||||||
|
export BEADS_PROJECT_ID=$PROJECT_ID
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo "Created .envrc with PROJECT_ID=$PROJECT_ID"
|
||||||
|
echo "Run: direnv allow"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Project Relationship Matrix
|
||||||
|
|
||||||
|
| Workspace | Project Channel | Agent Name | Can Message |
|
||||||
|
|-----------|----------------|------------|-------------|
|
||||||
|
| ~/src/beads | beads.dev | main-beads-* | All beads workers ✅ |
|
||||||
|
| ~/src/cino/beads | beads.dev | cino-beads-* | All beads workers ✅ |
|
||||||
|
| ~/src/dave/beads | beads.dev | dave-beads-* | All beads workers ✅ |
|
||||||
|
| ~/src/emma/beads | beads.dev | emma-beads-* | All beads workers ✅ |
|
||||||
|
| ~/src/fred/beads | beads.dev | fred-beads-* | All beads workers ✅ |
|
||||||
|
| ~/src/cino/vc | vc.dev | cino-vc-* | All vc workers ✅ |
|
||||||
|
| ~/src/dave/vc | vc.dev | dave-vc-* | All vc workers ✅ |
|
||||||
|
| ~/src/fred/vc | vc.dev | fred-vc-* | All vc workers ✅ |
|
||||||
|
| ~/src/vc | vc.dev | main-vc-* | All vc workers ✅ |
|
||||||
|
| ~/src/cino/wyvern | wyvern.dev | cino-wyvern-* | All wyvern workers ✅ |
|
||||||
|
| ~/src/fred/wyvern | wyvern.dev | fred-wyvern-* | All wyvern workers ✅ |
|
||||||
|
| ~/src/wyvern | wyvern.dev | main-wyvern-* | All wyvern workers ✅ |
|
||||||
|
|
||||||
|
## Monitoring Multiple Projects
|
||||||
|
|
||||||
|
### Web UI
|
||||||
|
|
||||||
|
View all projects and agents:
|
||||||
|
```bash
|
||||||
|
open http://127.0.0.1:8765/mail
|
||||||
|
```
|
||||||
|
|
||||||
|
### API Queries
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# List all projects
|
||||||
|
curl http://127.0.0.1:8765/api/projects | jq
|
||||||
|
|
||||||
|
# View agents in specific project
|
||||||
|
curl "http://127.0.0.1:8765/api/projects/$(urlencode /Users/stevey/src/fred/coordination)/agents" | jq
|
||||||
|
|
||||||
|
# Check file reservations across all projects
|
||||||
|
curl http://127.0.0.1:8765/api/file_reservations | jq
|
||||||
|
```
|
||||||
|
|
||||||
|
### Unified Dashboard Script
|
||||||
|
|
||||||
|
```bash
|
||||||
|
#!/bin/bash
|
||||||
|
# agent-mail-status.sh - View all active agents and reservations
|
||||||
|
|
||||||
|
echo "=== Agent Mail Status ==="
|
||||||
|
echo
|
||||||
|
|
||||||
|
echo "Server Health:"
|
||||||
|
curl -s http://127.0.0.1:8765/health | jq -r '.status // "UNREACHABLE"'
|
||||||
|
echo
|
||||||
|
|
||||||
|
echo "Active Projects:"
|
||||||
|
curl -s http://127.0.0.1:8765/api/projects | jq -r '.[] | "\(.slug) - \(.human_key)"'
|
||||||
|
echo
|
||||||
|
|
||||||
|
echo "Active Reservations:"
|
||||||
|
curl -s http://127.0.0.1:8765/api/file_reservations | jq -r '.[] | "\(.agent_name) → \(.resource_id) (\(.project_id))"'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Future: Cross-Project Messaging
|
||||||
|
|
||||||
|
When Agent Mail adds cross-project support (planned), you'll be able to:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Send message from fred/vc to cino/vc
|
||||||
|
bd agent-mail send \
|
||||||
|
--from fred-vc \
|
||||||
|
--to cino-vc \
|
||||||
|
--to-project /Users/stevey/src/cino/coordination \
|
||||||
|
--subject "API changes in shared library"
|
||||||
|
```
|
||||||
|
|
||||||
|
For now, use git commits/PRs for cross-project coordination.
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Problem: Different agents step on each other
|
||||||
|
|
||||||
|
**Symptom:** Two agents in same project both claim same issue
|
||||||
|
|
||||||
|
**Cause:** Agents using different `BEADS_AGENT_NAME` but same project
|
||||||
|
|
||||||
|
**Fix:** Ensure unique agent names per workspace:
|
||||||
|
```bash
|
||||||
|
export BEADS_AGENT_NAME=$(whoami)-$(basename $PWD)-$(hostname)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Problem: Agents can't see each other
|
||||||
|
|
||||||
|
**Symptom:** Agent sends message but recipient doesn't receive it
|
||||||
|
|
||||||
|
**Cause:** Agents in different `BEADS_PROJECT_ID`
|
||||||
|
|
||||||
|
**Fix:** Verify both agents use same project ID:
|
||||||
|
```bash
|
||||||
|
# In each workspace
|
||||||
|
echo $BEADS_PROJECT_ID
|
||||||
|
```
|
||||||
|
|
||||||
|
### Problem: Reservation persists after crash
|
||||||
|
|
||||||
|
**Symptom:** Issue stays reserved after agent died
|
||||||
|
|
||||||
|
**Fix:**
|
||||||
|
```bash
|
||||||
|
# Release via API
|
||||||
|
curl -X DELETE http://127.0.0.1:8765/api/reservations/bd-stuck-issue
|
||||||
|
|
||||||
|
# Or restart server (clears all)
|
||||||
|
kill $(cat ~/agent-mail.pid)
|
||||||
|
cd ~/src/mcp_agent_mail
|
||||||
|
source .venv/bin/activate
|
||||||
|
nohup python -m mcp_agent_mail.cli serve-http --host 127.0.0.1 --port 8765 > ~/agent-mail.log 2>&1 &
|
||||||
|
echo $! > ~/agent-mail.pid
|
||||||
|
```
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
1. **Use direnv for automatic env loading**
|
||||||
|
```bash
|
||||||
|
brew install direnv
|
||||||
|
# Add to ~/.zshrc: eval "$(direnv hook zsh)"
|
||||||
|
# Then create .envrc in each workspace
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Descriptive agent names**
|
||||||
|
```bash
|
||||||
|
# Bad: export BEADS_AGENT_NAME=agent1
|
||||||
|
# Good: export BEADS_AGENT_NAME=fred-vc-macbook
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Monitor server logs**
|
||||||
|
```bash
|
||||||
|
tail -f ~/agent-mail.log
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Health check in scripts**
|
||||||
|
```bash
|
||||||
|
if ! curl -sf http://127.0.0.1:8765/health > /dev/null; then
|
||||||
|
echo "WARNING: Agent Mail unavailable (falling back to git-only)"
|
||||||
|
fi
|
||||||
|
```
|
||||||
|
|
||||||
|
5. **Document project relationships**
|
||||||
|
- Keep this file updated when adding workspaces
|
||||||
|
- Add comments in .envrc explaining project coupling
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
- **One server** handles all projects (lightweight HTTP API)
|
||||||
|
- **Project ID = namespace** for agent isolation
|
||||||
|
- **Tight coupling** → shared project (vc + wyvern)
|
||||||
|
- **Loose coupling** → separate projects (beads forks)
|
||||||
|
- **Auto-restart** via launchd recommended
|
||||||
|
- **Per-directory .envrc** for automatic config loading
|
||||||
70
scripts/agent-mail-status.sh
Executable file
70
scripts/agent-mail-status.sh
Executable file
@@ -0,0 +1,70 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# View Agent Mail server status and active projects
|
||||||
|
# Usage: ./agent-mail-status.sh
|
||||||
|
|
||||||
|
PORT="${AGENT_MAIL_PORT:-8765}"
|
||||||
|
URL="http://127.0.0.1:$PORT"
|
||||||
|
PID_FILE="${AGENT_MAIL_PID:-$HOME/agent-mail.pid}"
|
||||||
|
|
||||||
|
echo "=== Agent Mail Status ==="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check PID file
|
||||||
|
if [[ -f "$PID_FILE" ]]; then
|
||||||
|
PID=$(cat "$PID_FILE")
|
||||||
|
if ps -p "$PID" > /dev/null 2>&1; then
|
||||||
|
echo "Server Process: ✅ Running (PID: $PID)"
|
||||||
|
else
|
||||||
|
echo "Server Process: ⚠️ Stale PID file (process $PID not found)"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "Server Process: ⚠️ No PID file found"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check health endpoint
|
||||||
|
echo ""
|
||||||
|
echo "Server Health:"
|
||||||
|
if HEALTH=$(curl -sf "$URL/health" 2>/dev/null); then
|
||||||
|
echo " ✅ $(echo $HEALTH | jq -r '.status // "OK"')"
|
||||||
|
echo " URL: $URL"
|
||||||
|
else
|
||||||
|
echo " ❌ UNREACHABLE at $URL"
|
||||||
|
echo ""
|
||||||
|
echo "Start server with:"
|
||||||
|
echo " ./scripts/start-agent-mail-server.sh"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# List projects
|
||||||
|
echo ""
|
||||||
|
echo "Active Projects:"
|
||||||
|
if PROJECTS=$(curl -sf "$URL/api/projects" 2>/dev/null); then
|
||||||
|
if [[ $(echo "$PROJECTS" | jq -r '. | length') -eq 0 ]]; then
|
||||||
|
echo " (none yet)"
|
||||||
|
else
|
||||||
|
echo "$PROJECTS" | jq -r '.[] | " • \(.slug)\n Path: \(.human_key)"'
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo " (failed to fetch)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# List reservations
|
||||||
|
echo ""
|
||||||
|
echo "Active File Reservations:"
|
||||||
|
if RESERVATIONS=$(curl -sf "$URL/api/file_reservations" 2>/dev/null); then
|
||||||
|
if [[ $(echo "$RESERVATIONS" | jq -r '. | length') -eq 0 ]]; then
|
||||||
|
echo " (none)"
|
||||||
|
else
|
||||||
|
echo "$RESERVATIONS" | jq -r '.[] | " • \(.agent_name) → \(.resource_id)\n Project: \(.project_id)\n Expires: \(.expires_at)"'
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo " (failed to fetch)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Web UI: $URL/mail"
|
||||||
|
echo ""
|
||||||
|
echo "Commands:"
|
||||||
|
echo " Start: ./scripts/start-agent-mail-server.sh"
|
||||||
|
echo " Stop: ./scripts/stop-agent-mail-server.sh"
|
||||||
|
echo " Logs: tail -f $HOME/agent-mail.log"
|
||||||
67
scripts/setup-agent-mail-workspace.sh
Executable file
67
scripts/setup-agent-mail-workspace.sh
Executable file
@@ -0,0 +1,67 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Setup Agent Mail configuration for a beads workspace
|
||||||
|
# Usage: ./setup-agent-mail-workspace.sh [workspace-path]
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
WORKSPACE="${1:-$(pwd)}"
|
||||||
|
cd "$WORKSPACE"
|
||||||
|
|
||||||
|
WORKSPACE_NAME=$(basename "$WORKSPACE")
|
||||||
|
PARENT=$(basename $(dirname "$WORKSPACE"))
|
||||||
|
HOSTNAME=$(hostname -s)
|
||||||
|
|
||||||
|
# Determine project ID based on workspace type
|
||||||
|
determine_project_id() {
|
||||||
|
local ws_name="$1"
|
||||||
|
|
||||||
|
case "$ws_name" in
|
||||||
|
beads)
|
||||||
|
echo "beads.dev"
|
||||||
|
;;
|
||||||
|
vc)
|
||||||
|
echo "vc.dev"
|
||||||
|
;;
|
||||||
|
wyvern)
|
||||||
|
echo "wyvern.dev"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "unknown.dev"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
PROJECT_ID=$(determine_project_id "$WORKSPACE_NAME")
|
||||||
|
AGENT_NAME="${PARENT}-${WORKSPACE_NAME}-${HOSTNAME}"
|
||||||
|
|
||||||
|
# Create .envrc for direnv
|
||||||
|
cat > .envrc <<EOF
|
||||||
|
# Agent Mail Configuration
|
||||||
|
# Generated: $(date)
|
||||||
|
# Workspace: $WORKSPACE
|
||||||
|
# Coupling: $(basename "$PROJECT_ID")
|
||||||
|
|
||||||
|
export BEADS_AGENT_MAIL_URL=http://127.0.0.1:8765
|
||||||
|
export BEADS_AGENT_NAME=$AGENT_NAME
|
||||||
|
export BEADS_PROJECT_ID=$PROJECT_ID
|
||||||
|
|
||||||
|
# Optional: Uncomment for debugging
|
||||||
|
# export BEADS_AGENT_MAIL_DEBUG=1
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo "✅ Created .envrc in $WORKSPACE"
|
||||||
|
echo ""
|
||||||
|
echo "Configuration:"
|
||||||
|
echo " BEADS_AGENT_MAIL_URL: http://127.0.0.1:8765"
|
||||||
|
echo " BEADS_AGENT_NAME: $AGENT_NAME"
|
||||||
|
echo " BEADS_PROJECT_ID: $PROJECT_ID"
|
||||||
|
echo ""
|
||||||
|
echo "Next steps:"
|
||||||
|
echo " 1. Review .envrc and adjust if needed"
|
||||||
|
echo " 2. Run: direnv allow"
|
||||||
|
echo " 3. Test: bd info | grep -i agent"
|
||||||
|
echo ""
|
||||||
|
echo "To install direnv:"
|
||||||
|
echo " brew install direnv"
|
||||||
|
echo " echo 'eval \"\$(direnv hook zsh)\"' >> ~/.zshrc"
|
||||||
|
echo " source ~/.zshrc"
|
||||||
86
scripts/start-agent-mail-server.sh
Executable file
86
scripts/start-agent-mail-server.sh
Executable file
@@ -0,0 +1,86 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Start Agent Mail server in background
|
||||||
|
# Usage: ./start-agent-mail-server.sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
AGENT_MAIL_DIR="${AGENT_MAIL_DIR:-$HOME/src/mcp_agent_mail}"
|
||||||
|
LOG_FILE="${AGENT_MAIL_LOG:-$HOME/agent-mail.log}"
|
||||||
|
PID_FILE="${AGENT_MAIL_PID:-$HOME/agent-mail.pid}"
|
||||||
|
PORT="${AGENT_MAIL_PORT:-8765}"
|
||||||
|
|
||||||
|
# Check if server already running
|
||||||
|
if [[ -f "$PID_FILE" ]]; then
|
||||||
|
PID=$(cat "$PID_FILE")
|
||||||
|
if ps -p "$PID" > /dev/null 2>&1; then
|
||||||
|
echo "⚠️ Agent Mail server already running (PID: $PID)"
|
||||||
|
echo " Stop it first: kill $PID"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
echo "🗑️ Removing stale PID file"
|
||||||
|
rm -f "$PID_FILE"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if directory exists
|
||||||
|
if [[ ! -d "$AGENT_MAIL_DIR" ]]; then
|
||||||
|
echo "❌ Agent Mail directory not found: $AGENT_MAIL_DIR"
|
||||||
|
echo ""
|
||||||
|
echo "Install with:"
|
||||||
|
echo " git clone https://github.com/Dicklesworthstone/mcp_agent_mail.git $AGENT_MAIL_DIR"
|
||||||
|
echo " cd $AGENT_MAIL_DIR"
|
||||||
|
echo " python3 -m venv .venv"
|
||||||
|
echo " source .venv/bin/activate"
|
||||||
|
echo " pip install -e ."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if venv exists
|
||||||
|
if [[ ! -d "$AGENT_MAIL_DIR/.venv" ]]; then
|
||||||
|
echo "❌ Virtual environment not found in $AGENT_MAIL_DIR/.venv"
|
||||||
|
echo ""
|
||||||
|
echo "Create with:"
|
||||||
|
echo " cd $AGENT_MAIL_DIR"
|
||||||
|
echo " python3 -m venv .venv"
|
||||||
|
echo " source .venv/bin/activate"
|
||||||
|
echo " pip install -e ."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Start server
|
||||||
|
echo "🚀 Starting Agent Mail server..."
|
||||||
|
echo " Directory: $AGENT_MAIL_DIR"
|
||||||
|
echo " Log file: $LOG_FILE"
|
||||||
|
echo " Port: $PORT"
|
||||||
|
|
||||||
|
cd "$AGENT_MAIL_DIR"
|
||||||
|
source .venv/bin/activate
|
||||||
|
|
||||||
|
nohup python -m mcp_agent_mail.cli serve-http \
|
||||||
|
--host 127.0.0.1 \
|
||||||
|
--port "$PORT" \
|
||||||
|
> "$LOG_FILE" 2>&1 &
|
||||||
|
|
||||||
|
echo $! > "$PID_FILE"
|
||||||
|
|
||||||
|
# Wait a moment for server to start
|
||||||
|
sleep 2
|
||||||
|
|
||||||
|
# Check if server is healthy
|
||||||
|
if curl -sf http://127.0.0.1:$PORT/health > /dev/null; then
|
||||||
|
echo "✅ Agent Mail server started successfully!"
|
||||||
|
echo " PID: $(cat $PID_FILE)"
|
||||||
|
echo " Health: http://127.0.0.1:$PORT/health"
|
||||||
|
echo " Web UI: http://127.0.0.1:$PORT/mail"
|
||||||
|
echo ""
|
||||||
|
echo "View logs:"
|
||||||
|
echo " tail -f $LOG_FILE"
|
||||||
|
echo ""
|
||||||
|
echo "Stop server:"
|
||||||
|
echo " kill $(cat $PID_FILE)"
|
||||||
|
else
|
||||||
|
echo "❌ Server failed to start"
|
||||||
|
echo " Check logs: tail -f $LOG_FILE"
|
||||||
|
rm -f "$PID_FILE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
53
scripts/stop-agent-mail-server.sh
Executable file
53
scripts/stop-agent-mail-server.sh
Executable file
@@ -0,0 +1,53 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Stop Agent Mail server
|
||||||
|
# Usage: ./stop-agent-mail-server.sh
|
||||||
|
|
||||||
|
PID_FILE="${AGENT_MAIL_PID:-$HOME/agent-mail.pid}"
|
||||||
|
|
||||||
|
if [[ ! -f "$PID_FILE" ]]; then
|
||||||
|
echo "⚠️ No PID file found: $PID_FILE"
|
||||||
|
echo " Attempting to kill by process name..."
|
||||||
|
|
||||||
|
if pkill -f "mcp_agent_mail.cli serve-http"; then
|
||||||
|
echo "✅ Killed Agent Mail server by process name"
|
||||||
|
else
|
||||||
|
echo "ℹ️ No Agent Mail server process found"
|
||||||
|
fi
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
PID=$(cat "$PID_FILE")
|
||||||
|
|
||||||
|
if ! ps -p "$PID" > /dev/null 2>&1; then
|
||||||
|
echo "⚠️ Process $PID not running (stale PID file)"
|
||||||
|
rm -f "$PID_FILE"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "🛑 Stopping Agent Mail server (PID: $PID)..."
|
||||||
|
kill "$PID"
|
||||||
|
|
||||||
|
# Wait for graceful shutdown
|
||||||
|
for i in {1..5}; do
|
||||||
|
if ! ps -p "$PID" > /dev/null 2>&1; then
|
||||||
|
echo "✅ Server stopped gracefully"
|
||||||
|
rm -f "$PID_FILE"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
|
||||||
|
# Force kill if needed
|
||||||
|
if ps -p "$PID" > /dev/null 2>&1; then
|
||||||
|
echo "⚠️ Server didn't stop gracefully, forcing..."
|
||||||
|
kill -9 "$PID"
|
||||||
|
sleep 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! ps -p "$PID" > /dev/null 2>&1; then
|
||||||
|
echo "✅ Server stopped (forced)"
|
||||||
|
rm -f "$PID_FILE"
|
||||||
|
else
|
||||||
|
echo "❌ Failed to stop server"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
Reference in New Issue
Block a user