Ai-Mee Help Centre
Home
Features
How-To Guides
FAQ
Need Help?
Home
Features
How-To Guides
FAQ
Need Help?

Phase 0: Foundation & Infrastructure

Timeline: Week 1-2
Objective: Wire GoClaw to Supabase and establish the base configuration.


0.1 — GoClaw Managed Mode + Supabase

Tasks

  • [x] Set GoClaw database.mode: "managed" and point GOCLAW_POSTGRES_DSN at the Supabase Postgres connection string
  • [x] Create new Supabase tables for GoClaw multi-tenant state (auto-created by managed mode migrations into the bot schema — 38 tables total)
  • [x] Enable the pgvector extension in Supabase
  • [x] Create a unified docker-compose.dev.yml at the repo root that brings up GoClaw + API + Supabase together
  • [x] Install GoClaw UI (ai-marketing-goclaw-ui Docker image built from goclaw/ui/web)

Database Setup (Automated via Supabase Migration)

The setup that was previously a manual SQL editor step is now fully automated. The migration front-end/supabase/migrations/20260308000000_create_bot_schema.sql runs as part of supabase db reset (local) or supabase db push (cloud) and handles everything:

-- Enables extensions
CREATE EXTENSION IF NOT EXISTS vector;
CREATE EXTENSION IF NOT EXISTS pgcrypto;

-- Dedicated schema for all GoClaw tables
CREATE SCHEMA IF NOT EXISTS bot;

-- Dedicated role — password stored in GOCLAW_POSTGRES_DSN
CREATE ROLE goclaw_bot WITH LOGIN PASSWORD 'goclaw_bot_dev';   -- change in production!

-- Pin search_path at the role level so golang-migrate always targets bot
ALTER ROLE goclaw_bot SET search_path TO bot, public;

-- Privileges
GRANT USAGE, CREATE ON SCHEMA bot    TO goclaw_bot;
GRANT USAGE         ON SCHEMA public TO goclaw_bot;
GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA public TO goclaw_bot;

Why a dedicated role and schema?golang-migrate (used by GoClaw's auto-upgrade) respects the connection's search_path. By pinning search_path TO bot, public on the goclaw_bot role, all 38 GoClaw tables (agents, llm_providers, sessions, schema_migrations, etc.) are created in the bot schema automatically — no schema-qualification needed in queries and no risk of colliding with the app's public schema.

⚠️ GOCLAW_POSTGRES_DSN must connect as goclaw_bot — not postgres or the Supabase service-role user — otherwise tables will be created in public instead of bot.

For full step-by-step instructions (including Supabase cloud production setup, password rotation, and troubleshooting), see docs/SUPABASE_BOT_SCHEMA_SETUP.md.

Resetting the Database

Use the script at scripts/reset-and-migrate.sh to reset Supabase and re-run GoClaw migrations in one step:

bash scripts/reset-and-migrate.sh

This script:

  1. Runs supabase db reset --yes from front-end/ (applies all Supabase migrations)
  2. Runs docker run ai-marketing-goclaw:latest migrate up to apply GoClaw's own migrations as the goclaw_bot user
  3. Prints the bot schema and all tables to confirm success

GoClaw Config (bot/data/config.json)

{
  "database": {
    "mode": "managed"
  },
  "channels": {
    "telegram": {
      "enabled": true,
      "token": "${GOCLAW_TELEGRAM_TOKEN}",
      "dm_policy": "pairing",
      "group_policy": "disabled",
      "require_mention": false,
      "stream_mode": "partial",
      "history_limit": 50,
      "media_max_bytes": 20971520
    }
  },
  "bindings": [
    {
      "agentId": "liaison-agent",
      "match": { "channel": "telegram" }
    }
  ]
}

GOCLAW_POSTGRES_DSN is never stored in config.json — it is injected via the environment only.

Connection String Format

The connection string must use the goclaw_bot role (not postgres).
The goclaw_bot role has search_path pinned to bot, public, which causes GoClaw's golang-migrate to create all tables in the bot schema. Using any other role will silently create tables in public.

# Local dev (port 54322 = local Supabase direct connection)
# Password 'goclaw_bot_dev' is set by the Supabase migration — do not change for local.
GOCLAW_POSTGRES_DSN=postgresql://goclaw_bot:[email protected]:54322/postgres?sslmode=disable

# Production (Supabase cloud, Session mode port 5432)
# Replace [PASSWORD] with the value set via: ALTER ROLE goclaw_bot PASSWORD '...';
GOCLAW_POSTGRES_DSN=postgresql://goclaw_bot:[PASSWORD]@db.[PROJECT-REF].supabase.co:5432/postgres?sslmode=disable

See docs/SUPABASE_BOT_SCHEMA_SETUP.md for the complete cloud production setup walkthrough including password rotation, verification, and troubleshooting.

Docker Compose

docker-compose.dev.yml at repo root brings up GoClaw + GoClaw UI + API together. Key GoClaw service settings:

goclaw:
  environment:
    - GOCLAW_MODE=managed
    - GOCLAW_AUTO_UPGRADE=true      # runs migrate up automatically on start
    - GOCLAW_POSTGRES_DSN=${GOCLAW_POSTGRES_DSN}
  volumes:
    - ./bot/data:/app/data          # config.json lives here
    - ./bot/workspace:/app/workspace

GOCLAW_AUTO_UPGRADE=true means the container will run goclaw upgrade before starting the gateway, so migrations stay in sync whenever the image is rebuilt.


0.2 — Telegram Bot Setup

Tasks

  • [x] Create a Telegram bot via BotFather → get GOCLAW_TELEGRAM_TOKEN
  • [x] Configure GoClaw channels.telegram in config.json
  • [x] Set up GoClaw bindings to route Telegram messages to the liaison-agent
  • [ ] Test basic Telegram ↔ GoClaw message round-trip

Create Telegram Bot

  1. Open Telegram and message @BotFather
  2. Send /newbot
  3. Follow prompts to choose name and username
  4. Copy the API token provided
  5. Store in .env: GOCLAW_TELEGRAM_TOKEN=your_token_here

Configure GoClaw Telegram Channel

Update goclaw/data/config.json:

{
  "channels": {
    "telegram": {
      "enabled": true,
      "token": "${GOCLAW_TELEGRAM_TOKEN}",
      "dm_policy": "pairing",
      "group_policy": "disabled",
      "require_mention": false,
      "stream_mode": "partial",
      "history_limit": 50,
      "media_max_bytes": 20971520
    }
  }
}

Note: dm_policy: "pairing" means users must pair with a client ID before the bot responds in DMs.

Set Up Agent Bindings

Add to goclaw/data/config.json:

{
  "bindings": [
    {
      "agentId": "liaison-agent",
      "match": {
        "channel": "telegram"
      }
    }
  ]
}

This routes all Telegram messages to the liaison-agent (which we'll create in Phase 1).

Test Telegram Connection

  1. Restart GoClaw with the new config
  2. Message your bot on Telegram: /start
  3. Check GoClaw logs for incoming message
  4. Bot should respond with "Agent not found" (expected — Phase 1 creates the agent)

0.3 — Environment & Config Unification

Tasks

  • [x] Create a root-level .env.example documenting all env vars across services
  • [x] Add GOCLAW_API_URL to api/src/config/env.ts for API→GoClaw communication
  • [x] Add API_BASE_URL to GoClaw env for GoClaw→API tool calls
  • [x] Set up shared Docker network between GoClaw and API containers

Root .env.example

Create /code/ai-marketing/.env.example:

# ===== Supabase =====
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_KEY=your-anon-key
SUPABASE_SERVICE_KEY=your-service-role-key

# ===== API Service =====
API_KEY=your-internal-api-key
WORKER_API_JWT_SECRET=your-worker-secret
PORT=8000
HOST=0.0.0.0

# LLM Provider (ollama or gemini)
LLM_PROVIDER=gemini
GOOGLE_API_KEY=your-google-api-key
OLLAMA_BASE_URL=http://localhost:11434
OLLAMA_MODEL=llama2

# Unsplash
UNSPLASH_ACCESS_KEY=your-unsplash-key

# Ghost CMS
GHOST_API_URL=https://your-ghost-site.com
GHOST_ADMIN_API_KEY=your-ghost-key

# GoClaw API URL (for API → GoClaw calls)
GOCLAW_API_URL=http://goclaw:18790

# ===== GoClaw Service =====
GOCLAW_HOST=0.0.0.0
GOCLAW_PORT=18790
GOCLAW_POSTGRES_DSN=postgresql://user:[email protected]:5432/postgres

# GoClaw LLM Providers
GOCLAW_PROVIDER=anthropic
GOCLAW_MODEL=claude-sonnet-4-20250514
GOCLAW_ANTHROPIC_API_KEY=your-anthropic-key
GOCLAW_GEMINI_API_KEY=your-gemini-key

# GoClaw Channels
GOCLAW_TELEGRAM_TOKEN=your-telegram-bot-token

# API Base URL (for GoClaw → API tool calls)
API_BASE_URL=http://api:8000

Update API Config

Edit api/src/config/env.ts:

export const env = {
  API_KEY: process.env.API_KEY,
  
  LLM_PROVIDER: process.env.LLM_PROVIDER || 'ollama',
  
  NODE_ENV: process.env.NODE_ENV || 'development',
  PORT: parseInt(process.env.PORT || '8000', 10),
  HOST: process.env.HOST || '0.0.0.0',
  
  // Supabase configuration
  SUPABASE_URL: process.env.SUPABASE_URL || '',
  SUPABASE_KEY: process.env.SUPABASE_KEY || '',
  
  // Google Gemini configuration
  GOOGLE_API_KEY: process.env.GOOGLE_API_KEY || '',
  
  // Ollama configuration
  OLLAMA_BASE_URL: process.env.OLLAMA_BASE_URL || 'http://localhost:11434',
  OLLAMA_MODEL: process.env.OLLAMA_MODEL || 'llama2',
  
  // SerpAPI configuration
  SERPAPI_API_KEY: process.env.SERPAPI_API_KEY || '',
  
  // Unsplash configuration
  UNSPLASH_ACCESS_KEY: process.env.UNSPLASH_ACCESS_KEY || '',
  
  // Ghost CMS configuration
  GHOST_API_URL: process.env.GHOST_API_URL || '',
  GHOST_ADMIN_API_KEY: process.env.GHOST_ADMIN_API_KEY || '',
  
  // GoClaw API (NEW)
  GOCLAW_API_URL: process.env.GOCLAW_API_URL || 'http://localhost:18790',
  
  // API Base URL for GoClaw tools (NEW)
  API_BASE_URL: process.env.API_BASE_URL || 'http://localhost:8000'
};

Verify Docker Network

The docker-compose.dev.yml created in step 0.1 already defines ai-marketing-network. Verify services can reach each other:

docker-compose -f docker-compose.dev.yml up -d
docker-compose -f docker-compose.dev.yml exec api curl http://goclaw:18790/
# Should return GoClaw gateway response

New Tooling Required

  • docker-compose.dev.yml — Multi-service orchestration
  • Supabase migration for pgvector extension
  • Root .env file with all service configurations

Verification Checklist

  • [x] GoClaw starts in managed mode and connects to Supabase
  • [x] pgvector extension is enabled in Supabase
  • [x] Telegram bot receives and logs messages
  • [x] Docker network allows API ↔ GoClaw communication
  • [x] All environment variables are documented in .env.example
  • [x] .env file exists locally (not committed) with actual values

Next Steps

Proceed to Phase 1: Agent Team Architecture to define the three-agent team and create their skill files.