# RateRight Multi-Agent Coordination System - Technical Specification

**Version:** 1.0  
**Date:** 2026-02-13  
**Author:** Rivet (Ops)  
**Target:** Claude Code (Builder) Implementation  

## Overview

This specification defines the technical architecture for RateRight's multi-agent coordination system. The system enables multiple specialized Clawdbot instances to collaborate through a shared Supabase database while maintaining security boundaries and cost optimization.

## Architecture Components

1. **Supabase Database Schema** - Centralized coordination hub
2. **Row Level Security (RLS)** - Bot-specific access controls  
3. **Multi-Instance Clawdbot Setup** - Isolated agent directories
4. **Inter-Agent Communication** - Database polling + messaging hybrid
5. **Cost Optimization** - Model selection and heartbeat tuning
6. **Implementation Phases** - Incremental rollout plan

---

## 1. Supabase Database Schema

### Database: `rateright-growth`

Create tables with full SQL migrations:

```sql
-- Migration: 001_create_multi_agent_schema.sql

-- Bot Tasks Queue
CREATE TABLE bot_tasks (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    bot_id TEXT NOT NULL, -- Owner bot (e.g., 'rivet', 'sales', 'legal')
    assigned_to TEXT, -- Assigned bot (null = unassigned)
    title TEXT NOT NULL,
    description TEXT,
    status TEXT NOT NULL CHECK (status IN ('pending', 'in_progress', 'completed', 'failed')),
    priority TEXT NOT NULL CHECK (priority IN ('critical', 'high', 'medium', 'low')) DEFAULT 'medium',
    created_at TIMESTAMPTZ DEFAULT NOW(),
    updated_at TIMESTAMPTZ DEFAULT NOW(),
    completed_at TIMESTAMPTZ,
    metadata JSONB DEFAULT '{}'::jsonb
);

-- Bot Communications Queue (Approval System)
CREATE TABLE bot_comms_queue (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    requesting_bot TEXT NOT NULL,
    channel TEXT NOT NULL CHECK (channel IN ('sms', 'email', 'whatsapp', 'telegram')),
    recipient TEXT NOT NULL,
    message_body TEXT NOT NULL,
    status TEXT NOT NULL CHECK (status IN ('draft', 'pending_review', 'approved', 'rejected', 'sent')) DEFAULT 'draft',
    reviewed_by TEXT,
    review_notes TEXT,
    created_at TIMESTAMPTZ DEFAULT NOW(),
    sent_at TIMESTAMPTZ
);

-- Cross-Bot Task Handoffs
CREATE TABLE bot_handoffs (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    from_bot TEXT NOT NULL,
    to_bot TEXT NOT NULL,
    task_summary TEXT NOT NULL,
    context JSONB DEFAULT '{}'::jsonb,
    status TEXT NOT NULL CHECK (status IN ('pending', 'accepted', 'completed')) DEFAULT 'pending',
    created_at TIMESTAMPTZ DEFAULT NOW(),
    accepted_at TIMESTAMPTZ,
    completed_at TIMESTAMPTZ
);

-- Immutable Audit Log
CREATE TABLE bot_audit_log (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    bot_id TEXT NOT NULL,
    action TEXT NOT NULL,
    details JSONB DEFAULT '{}'::jsonb,
    created_at TIMESTAMPTZ DEFAULT NOW()
);

-- Bot Status & Heartbeats
CREATE TABLE bot_status (
    bot_id TEXT PRIMARY KEY,
    last_heartbeat TIMESTAMPTZ DEFAULT NOW(),
    status TEXT NOT NULL CHECK (status IN ('online', 'offline', 'error')) DEFAULT 'online',
    current_task UUID REFERENCES bot_tasks(id),
    metadata JSONB DEFAULT '{}'::jsonb
);

-- Indexes for performance
CREATE INDEX idx_bot_tasks_bot_id ON bot_tasks(bot_id);
CREATE INDEX idx_bot_tasks_assigned_to ON bot_tasks(assigned_to);
CREATE INDEX idx_bot_tasks_status ON bot_tasks(status);
CREATE INDEX idx_bot_tasks_priority ON bot_tasks(priority);
CREATE INDEX idx_bot_tasks_created_at ON bot_tasks(created_at);

CREATE INDEX idx_bot_comms_queue_status ON bot_comms_queue(status);
CREATE INDEX idx_bot_comms_queue_requesting_bot ON bot_comms_queue(requesting_bot);
CREATE INDEX idx_bot_comms_queue_created_at ON bot_comms_queue(created_at);

CREATE INDEX idx_bot_handoffs_from_bot ON bot_handoffs(from_bot);
CREATE INDEX idx_bot_handoffs_to_bot ON bot_handoffs(to_bot);
CREATE INDEX idx_bot_handoffs_status ON bot_handoffs(status);

CREATE INDEX idx_bot_audit_log_bot_id ON bot_audit_log(bot_id);
CREATE INDEX idx_bot_audit_log_created_at ON bot_audit_log(created_at);

-- Updated_at trigger for bot_tasks
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_at = NOW();
    RETURN NEW;
END;
$$ language 'plpgsql';

CREATE TRIGGER update_bot_tasks_updated_at 
    BEFORE UPDATE ON bot_tasks 
    FOR EACH ROW 
    EXECUTE FUNCTION update_updated_at_column();
```

---

## 2. Row Level Security (RLS) Policies

### Authentication Pattern: Service Keys + Bot Context

Each bot uses a service role key with bot-specific context in JWT claims:

```sql
-- Enable RLS on all tables
ALTER TABLE bot_tasks ENABLE ROW LEVEL SECURITY;
ALTER TABLE bot_comms_queue ENABLE ROW LEVEL SECURITY;
ALTER TABLE bot_handoffs ENABLE ROW LEVEL SECURITY;
ALTER TABLE bot_audit_log ENABLE ROW LEVEL SECURITY;
ALTER TABLE bot_status ENABLE ROW LEVEL SECURITY;

-- Create function to get current bot ID from JWT
CREATE OR REPLACE FUNCTION current_bot_id()
RETURNS TEXT AS $$
BEGIN
    RETURN current_setting('app.bot_id', true);
EXCEPTION
    WHEN OTHERS THEN RETURN NULL;
END;
$$ LANGUAGE plpgsql;

-- Bot Tasks RLS Policies
CREATE POLICY "Rivet sees all tasks" ON bot_tasks
    FOR ALL TO authenticated
    USING (current_bot_id() = 'rivet');

CREATE POLICY "Bots see own tasks and assigned" ON bot_tasks
    FOR ALL TO authenticated
    USING (
        bot_id = current_bot_id() 
        OR assigned_to = current_bot_id()
        OR current_bot_id() = 'rivet'
    );

-- Bot Comms Queue RLS Policies  
CREATE POLICY "Comms Gateway and Rivet see all comms" ON bot_comms_queue
    FOR ALL TO authenticated
    USING (current_bot_id() IN ('comms_gateway', 'rivet'));

CREATE POLICY "Bots see own comms requests" ON bot_comms_queue
    FOR ALL TO authenticated
    USING (requesting_bot = current_bot_id());

-- Bot Handoffs RLS Policies
CREATE POLICY "All bots see handoffs" ON bot_handoffs
    FOR ALL TO authenticated
    USING (true);

-- Bot Audit Log RLS Policies
CREATE POLICY "All bots read audit log" ON bot_audit_log
    FOR SELECT TO authenticated
    USING (true);

CREATE POLICY "Bots write own audit entries" ON bot_audit_log
    FOR INSERT TO authenticated
    WITH CHECK (bot_id = current_bot_id());

-- Bot Status RLS Policies
CREATE POLICY "All bots read status" ON bot_status
    FOR SELECT TO authenticated
    USING (true);

CREATE POLICY "Bots update own status" ON bot_status
    FOR ALL TO authenticated
    USING (bot_id = current_bot_id());
```

### Bot Authentication Setup

Each bot connects with service role key + bot context:

```javascript
// Example connection string for sales bot
const supabase = createClient(
  process.env.SUPABASE_URL,
  process.env.SUPABASE_SERVICE_KEY,
  {
    global: {
      headers: {
        'x-bot-id': 'sales' // Custom header for RLS
      }
    }
  }
);
```

---

## 3. Clawdbot Multi-Instance Setup

### Directory Structure

```
/home/ccuser/
├── .clawdbot/
│   ├── auth-profiles.json      # Shared auth profiles
│   └── secrets.json           # Shared API keys
├── rivet/                     # Rivet (Ops) - Existing
│   ├── agentDir/              # Clawdbot instance data
│   │   ├── auth-profiles.json # Symlink to shared
│   │   └── sessions/          # Session storage
│   ├── SOUL.md
│   ├── HEARTBEAT.md
│   ├── AGENTS.md
│   └── shared/                # Shared workspace
│       ├── TODO.md
│       ├── updates/
│       └── comms-queue/
├── builder/                   # Builder (Code)
│   ├── agentDir/
│   │   └── auth-profiles.json # Symlink to shared
│   ├── SOUL.md
│   └── HEARTBEAT.md
├── sales/                     # Sales & Marketing
│   ├── agentDir/
│   ├── SOUL.md
│   └── HEARTBEAT.md
├── legal/                     # Legal & Finance
│   ├── agentDir/
│   ├── SOUL.md
│   └── HEARTBEAT.md
├── chief/                     # Chief of Staff
│   ├── agentDir/
│   ├── SOUL.md
│   └── HEARTBEAT.md
└── comms-gateway/             # Communications Gateway
    ├── agentDir/
    ├── SOUL.md
    └── HEARTBEAT.md
```

### Shared Configuration Setup

```bash
# Create shared auth profiles symlink
ln -s /home/ccuser/.clawdbot/auth-profiles.json /home/ccuser/rivet/agentDir/auth-profiles.json
ln -s /home/ccuser/.clawdbot/auth-profiles.json /home/ccuser/builder/agentDir/auth-profiles.json
# Repeat for each bot...
```

### Systemd Service Files

Create service files for each bot instance:

```ini
# /etc/systemd/system/clawdbot-rivet.service
[Unit]
Description=Clawdbot - Rivet (Ops)
After=network.target

[Service]
Type=simple
User=ccuser
WorkingDirectory=/home/ccuser/rivet
Environment=HOME=/home/ccuser
Environment=AGENT_DIR=/home/ccuser/rivet/agentDir
ExecStart=/usr/local/bin/clawdbot gateway start --port 8081
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target
```

```ini
# /etc/systemd/system/clawdbot-sales.service
[Unit]
Description=Clawdbot - Sales Bot
After=network.target

[Service]
Type=simple
User=ccuser
WorkingDirectory=/home/ccuser/sales
Environment=HOME=/home/ccuser
Environment=AGENT_DIR=/home/ccuser/sales/agentDir
Environment=BOT_ID=sales
ExecStart=/usr/local/bin/clawdbot gateway start --port 8082
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target
```

### Model Routing Configuration

Configure per-bot model selection in Clawdbot:

```json
// /home/ccuser/.clawdbot/config.json
{
  "modelRouting": {
    "rivet": {
      "default": "anthropic/claude-opus-4-6",
      "tasks": {
        "heartbeat": "moonshot/kimi-k2-0905-preview",
        "dirty_data": "anthropic/claude-opus-4-6"
      }
    },
    "builder": {
      "default": "anthropic/claude-sonnet-3.7",
      "tasks": {
        "complex_coding": "anthropic/claude-opus-4-6"
      }
    },
    "sales": {
      "default": "moonshot/kimi-k2-0905-preview",
      "tasks": {
        "outreach": "moonshot/kimi-k2-0905-preview",
        "strategy": "anthropic/claude-sonnet-3.7"
      }
    },
    "legal": {
      "default": "anthropic/claude-opus-4-6"
    },
    "chief": {
      "default": "anthropic/claude-opus-4-6"
    },
    "comms_gateway": {
      "default": "anthropic/claude-opus-4-6"
    }
  }
}
```

---

## 4. Inter-Agent Communication Patterns

### Database Polling Pattern

Each bot polls for new tasks every 30-60 seconds:

```javascript
// Example polling implementation
async function pollForTasks() {
  const { data: tasks } = await supabase
    .from('bot_tasks')
    .select('*')
    .eq('assigned_to', BOT_ID)
    .eq('status', 'pending')
    .order('priority', { ascending: false })
    .order('created_at', { ascending: true });
    
  for (const task of tasks || []) {
    await processTask(task);
  }
}

// Run every 30 seconds
setInterval(pollForTasks, 30000);
```

### Clawdbot Sessions_Send for Real-Time Messaging

Use for urgent communications:

```javascript
// Send message to specific bot
await clawdbot.sessions.send({
  target: 'sales',
  message: 'URGENT: New hot lead requires immediate follow-up',
  priority: 'high'
});
```

### File-Based Coordination

What stays in files vs database:

**Database (Structured Data):**
- Task assignments and status
- Communication queue items
- Audit logs
- Bot heartbeats

**Files (Human-Readable):**
- SOUL.md, HEARTBEAT.md - Bot configuration
- Research documents and plans
- Daily memory logs
- Long-term MEMORY.md

### Hybrid Approach Decision Matrix

| Use Case | Database | Files | Messaging |
|----------|----------|-------|-----------|
| Task assignment | ✓ | ✗ | ✗ |
| Status updates | ✓ | ✓ | ✗ |
| Urgent alerts | ✗ | ✗ | ✓ |
| Research output | ✗ | ✓ | ✗ |
| Comms approval | ✓ | ✗ | ✗ |
| Bot config | ✗ | ✓ | ✗ |
| Cross-bot handoff | ✓ | ✗ | ✓ |

---

## 5. Cost Optimization

### Model Selection Per Bot

| Bot | Routine Tasks | Complex Tasks | External Data |
|-----|---------------|---------------|---------------|
| Rivet | Kimi K2 | Opus | Opus |
| Builder | Sonnet | Opus | Opus |
| Sales | Kimi K2 | Sonnet | Opus |
| Legal | Opus | Opus | Opus |
| Chief | Opus | Opus | Opus |
| Comms Gateway | Opus | Opus | Opus |

### Heartbeat Frequency

```json
{
  "heartbeatFrequencies": {
    "rivet": "15min",      // Operations monitoring
    "builder": "30min",    // Code work batching
    "sales": "10min",      // Lead response time
    "legal": "60min",      // Low frequency
    "chief": "30min",      // Strategic analysis
    "comms_gateway": "5min" // Message approval
  }
}
```

### Token Budget Limits

```javascript
// Monthly token budgets per bot
const tokenBudgets = {
  rivet: 5000000,        // 5M tokens
  builder: 3000000,      // 3M tokens  
  sales: 2000000,        // 2M tokens
  legal: 1000000,        // 1M tokens
  chief: 2000000,        // 2M tokens
  comms_gateway: 1000000 // 1M tokens
};
```

### Cost Monitoring

```sql
-- Monthly cost tracking view
CREATE VIEW monthly_bot_costs AS
SELECT 
  bot_id,
  date_trunc('month', created_at) as month,
  COUNT(*) as task_count,
  SUM(metadata->>'tokens_used')::int as total_tokens,
  CASE 
    WHEN bot_id IN ('legal', 'chief', 'comms_gateway') THEN 'opus'
    WHEN bot_id = 'builder' THEN 'sonnet'
    ELSE 'kimi'
  END as model_tier,
  COUNT(*) * CASE 
    WHEN bot_id IN ('legal', 'chief', 'comms_gateway') THEN 0.015
    WHEN bot_id = 'builder' THEN 0.003
    ELSE 0.0005
  END as estimated_cost
FROM bot_tasks 
WHERE status = 'completed'
GROUP BY bot_id, date_trunc('month', created_at);
```

---

## 6. Implementation Plan

### Phase 1: Schema + Migrations (Week 1)

**Tasks:**
1. Create Supabase tables and RLS policies
2. Set up database migrations in `/home/ccuser/rateright-growth/supabase/migrations/`
3. Test RLS policies with sample data
4. Document connection strings for each bot

**CC VPS Command:**
```bash
su - ccuser -c 'cd /home/ccuser/rateright-growth && claude --dangerously-skip-permissions -p "Create Supabase migrations for multi-agent schema including bot_tasks, bot_comms_queue, bot_handoffs, bot_audit_log, and bot_status tables with RLS policies"'
```

### Phase 2: Rivet Integration (Week 1-2)

**Tasks:**
1. Update Rivet heartbeat to write to `bot_status` table
2. Create task polling mechanism for Rivet
3. Implement audit logging for Rivet actions
4. Test database connectivity and RLS

### Phase 3: Sales Bot Setup (Week 2)

**Tasks:**
1. Create sales bot directory structure
2. Configure SOUL.md and HEARTBEAT.md for sales
3. Set up systemd service for sales bot
4. Implement basic task polling
5. Test inter-bot task assignment

### Phase 4: Chief of Staff / Comms Gateway (Week 3)

**Tasks:**
1. Create Chief of Staff bot for strategic analysis
2. Create Comms Gateway bot for message approval
3. Implement communication queue workflow
4. Set up daily briefing generation
5. Full system integration testing

### Phase 5: Builder & Legal Bots (Week 4)

**Tasks:**
1. Integrate existing Builder bot with database
2. Create Legal & Finance bot
3. Implement cross-bot handoff workflow
4. Performance optimization
5. Documentation and training

---

## Security Considerations

1. **Service Key Storage**: All service keys in `/root/.clawdbot/` with 600 permissions
2. **RLS Enforcement**: No table access without RLS policies
3. **Audit Trail**: All actions logged with bot_id and timestamp
4. **Network Isolation**: All bots on same VPS, no external access to DB
5. **Message Sanitization**: Comms Gateway validates all external messages

---

## Monitoring & Alerting

```sql
-- Failed tasks alert view
CREATE VIEW failed_tasks_alert AS
SELECT 
  bot_id,
  COUNT(*) as failed_count,
  MAX(updated_at) as last_failure
FROM bot_tasks 
WHERE status = 'failed' 
  AND updated_at > NOW() - INTERVAL '1 hour'
GROUP BY bot_id;

-- Offline bots view
CREATE VIEW offline_bots AS
SELECT 
  bot_id,
  last_heartbeat,
  EXTRACT(EPOCH FROM (NOW() - last_heartbeat))/60 as minutes_offline
FROM bot_status 
WHERE last_heartbeat < NOW() - INTERVAL '30 minutes';
```

---

## Next Steps

1. **Immediate**: Run Phase 1 migrations on CC VPS
2. **This Week**: Update Rivet to use database heartbeats
3. **Next Week**: Deploy Sales bot for testing
4. **Ongoing**: Monitor costs and adjust model usage

**Ready for implementation** - This spec provides all SQL, configuration, and setup instructions needed for CC VPS to begin building immediately.