Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
File renamed without changes.
41 changes: 0 additions & 41 deletions .claude/settings.local.json

This file was deleted.

21 changes: 9 additions & 12 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ ANTHROPIC_API_KEY=sk-ant-...
# Apps reference this as NEXT_PUBLIC_CONVEX_URL
CONVEX_URL=https://your-deployment.convex.cloud

# OpenClaw gateway authentication token
# Agency gateway authentication token
# Auto-generated by scripts/start.sh, or set your own secure random string
OPENCLAW_TOKEN=your-secure-token-here
AGENCY_TOKEN=your-secure-token-here

# =============================================================================
# OPTIONAL
Expand All @@ -27,19 +27,16 @@ OPENCLAW_TOKEN=your-secure-token-here
# Environment: dev or prod
ENVIRONMENT=dev

# OpenClaw gateway URL
# Agency gateway URL
# Development: http://localhost:18790 (Docker exposed on host)
# Production: http://openclaw:18789 (Docker internal network)
OPENCLAW_URL=http://localhost:18790
# Production: http://agency:18789 (Docker internal network)
AGENCY_URL=http://localhost:18790

# =============================================================================
# ADVANCED (usually don't need to change)
# =============================================================================

# OpenClaw gateway port (default: 18789)
# OPENCLAW_PORT=18789

# OpenClaw state directory (path to OpenClaw's config dir, mounted from Docker)
# Development: ./.openclaw/config (relative to project root)
# Production: /openclaw-data/config (shared Docker volume)
OPENCLAW_STATE_DIR=./.openclaw/config
# Agency state directory (path to config dir, mounted from Docker)
# Development: ./.agency/config (relative to project root)
# Production: /agency-data/config (shared Docker volume)
AGENCY_STATE_DIR=./.agency/config
16 changes: 8 additions & 8 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,16 @@ yarn-error.log*
.DS_Store
*.pem

convex/_generated
# Claude Code local settings (personal permissions)
.claude/settings.local.json

# Docker
docker/openclaw/data/
convex/_generated

# Local data directory (Clawe config)
.data/

# OpenClaw state directory (shared with Docker in dev)
.openclaw/*
!.openclaw/.gitkeep
.openclaw/logs/*
!.openclaw/logs/.gitkeep
# Agency state directory (shared with Docker in dev)
.agency/*
!.agency/.gitkeep
.agency/logs/*
!.agency/logs/.gitkeep
2 changes: 1 addition & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# Template files with shell variable substitution
docker/openclaw/templates/*.json
docker/agency/templates/*.json
6 changes: 3 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@ Core models: `agents`, `tasks`, `messages` (see `packages/backend/convex/schema.
## Environment Variables

- `NEXT_PUBLIC_CONVEX_URL`: Convex deployment URL (required)
- `ANTHROPIC_API_KEY`: Anthropic API key for AI operations (required, passed to OpenClaw)
- `OPENCLAW_TOKEN`: Authentication token for OpenClaw (required)
- `OPENCLAW_URL`: OpenClaw gateway URL (set in `.env.development` / `.env.production`)
- `ANTHROPIC_API_KEY`: Anthropic API key for AI operations (required, passed to agency)
- `AGENCY_TOKEN`: Authentication token for agency gateway (required)
- `AGENCY_URL`: Agency gateway URL (set in `.env.development` / `.env.production`)
- `NODE_ENV`: local (`development`) vs deployed (`production`) — controls dev tooling
- `ENVIRONMENT`: deployment target (`dev` / `prod`) — controls feature flags

Expand Down
30 changes: 15 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ Edit `.env`:
```bash
# Required
ANTHROPIC_API_KEY=sk-ant-...
OPENCLAW_TOKEN=your-secure-token
AGENCY_TOKEN=your-secure-token
CONVEX_URL=https://your-deployment.convex.cloud

# Optional
Expand All @@ -64,15 +64,15 @@ npx convex deploy
This script will:

- Create `.env` from `.env.example` if missing
- Auto-generate a secure `OPENCLAW_TOKEN`
- Auto-generate a secure `AGENCY_TOKEN`
- Validate all required environment variables
- Build necessary packages
- Start the Docker containers

**Development:**

```bash
# Start OpenClaw gateway only (use local web dev server)
# Start agency gateway only (use local web dev server)
pnpm dev:docker

# In another terminal, start web + Convex
Expand All @@ -81,7 +81,7 @@ pnpm dev

The production stack starts:

- **openclaw**: Gateway running all agents
- **agency**: Gateway running all agents
- **watcher**: Notification delivery + cron setup
- **clawe**: Web dashboard at http://localhost:3000

Expand Down Expand Up @@ -113,11 +113,11 @@ Schedule recurring tasks that automatically create inbox items:
┌─────────────────────────────────────────────────────────────┐
│ DOCKER COMPOSE │
├─────────────────┬─────────────────────┬─────────────────────┤
openclaw │ watcher │ clawe │
agency │ watcher │ clawe │
│ │ │ │
OpenClaw │ • Register agents │ Web Dashboard │
Gateway with │ • Setup crons │ • Squad status │
4 agents │ • Deliver notifs │ • Task board │
Agent Gateway │ • Register agents │ Web Dashboard │
│ with 4 agents │ • Setup crons │ • Squad status │
│ • Deliver notifs │ • Task board │
│ │ │ • Agent chat │
└────────┬────────┴──────────┬──────────┴──────────┬──────────┘
│ │ │
Expand All @@ -144,10 +144,10 @@ clawe/
├── packages/
│ ├── backend/ # Convex schema & functions
│ ├── cli/ # `clawe` CLI for agents
│ ├── shared/ # Shared OpenClaw client
│ ├── shared/ # Shared agency client
│ └── ui/ # UI components
└── docker/
└── openclaw/
└── agency/
├── Dockerfile
├── entrypoint.sh
├── scripts/ # init-agents.sh
Expand Down Expand Up @@ -214,8 +214,8 @@ Each agent has an isolated workspace with:

### Adding New Agents

1. Create workspace template in `docker/openclaw/templates/workspaces/{name}/`
2. Add agent to `docker/openclaw/templates/config.template.json`
1. Create workspace template in `docker/agency/templates/workspaces/{name}/`
2. Add agent to `docker/agency/templates/config.template.json`
3. Add agent to watcher's `AGENTS` array in `apps/watcher/src/index.ts`
4. Rebuild: `docker compose build && docker compose up -d`

Expand Down Expand Up @@ -245,13 +245,13 @@ pnpm install
# Terminal 1: Start Convex dev server
pnpm convex:dev

# Terminal 2: Start OpenClaw gateway in Docker
# Terminal 2: Start agency gateway in Docker
pnpm dev:docker

# Terminal 3: Start web dashboard
pnpm dev:web

# Or run everything together (Convex + web, but not OpenClaw)
# Or run everything together (Convex + web, but not agency)
pnpm dev
```

Expand All @@ -277,6 +277,6 @@ pnpm convex:deploy
| Variable | Required | Description |
| ------------------- | -------- | --------------------------------- |
| `ANTHROPIC_API_KEY` | Yes | Anthropic API key for Claude |
| `OPENCLAW_TOKEN` | Yes | Auth token for OpenClaw gateway |
| `AGENCY_TOKEN` | Yes | Auth token for agency gateway |
| `CONVEX_URL` | Yes | Convex deployment URL |
| `OPENAI_API_KEY` | No | OpenAI key (for image generation) |
4 changes: 2 additions & 2 deletions apps/watcher/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@

# Required variables (from root .env):
# - CONVEX_URL
# - OPENCLAW_URL
# - OPENCLAW_TOKEN
# - AGENCY_URL
# - AGENCY_TOKEN
2 changes: 1 addition & 1 deletion apps/watcher/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ WORKDIR /app
# Watcher
COPY apps/watcher/dist/ ./dist/

# Shared package (OpenClaw client)
# Shared package (agency client)
COPY packages/shared/package.json ./node_modules/@clawe/shared/package.json
COPY packages/shared/dist/ ./node_modules/@clawe/shared/dist/

Expand Down
16 changes: 8 additions & 8 deletions apps/watcher/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ This enables:

## Environment Variables

| Variable | Required | Description |
| ---------------- | -------- | ----------------------------- |
| `CONVEX_URL` | Yes | Convex deployment URL |
| `OPENCLAW_URL` | Yes | OpenClaw gateway URL |
| `OPENCLAW_TOKEN` | Yes | OpenClaw authentication token |
| Variable | Required | Description |
| -------------- | -------- | --------------------------- |
| `CONVEX_URL` | Yes | Convex deployment URL |
| `AGENCY_URL` | Yes | Agency gateway URL |
| `AGENCY_TOKEN` | Yes | Agency authentication token |

## Running

Expand Down Expand Up @@ -53,7 +53,7 @@ Schedules are staggered to avoid rate limits.
│ │
│ ┌─────────────┐ │
│ │ On Startup │──> Check/create heartbeat crons │
│ └─────────────┘ via OpenClaw cron API │
│ └─────────────┘ via agency cron API
│ │
│ ┌─────────────┐ ┌─────────────────────────┐ │
│ │ Poll Loop │───────>│ convex.query( │ │
Expand All @@ -62,13 +62,13 @@ Schedules are staggered to avoid rate limits.
│ │ └─────────────────────────┘ │
│ │ │
│ │ ┌─────────────────────────┐ │
│ └──────────────>│ openclaw.sessionsSend() │ │
│ └──────────────>│ agency.sessionsSend() │ │
│ └─────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
│ │
▼ ▼
┌───────────┐ ┌───────────────┐
│ CONVEX │ │ OPENCLAW
│ CONVEX │ │ AGENCY
│ (data) │ │ (delivery) │
└───────────┘ └───────────────┘
```
24 changes: 12 additions & 12 deletions apps/watcher/src/config.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ describe("config", () => {
describe("validateEnv", () => {
it("exits when CONVEX_URL is missing", async () => {
delete process.env.CONVEX_URL;
process.env.OPENCLAW_URL = "http://localhost:18789";
process.env.OPENCLAW_TOKEN = "test-token";
process.env.AGENCY_URL = "http://localhost:18789";
process.env.AGENCY_TOKEN = "test-token";

const mockExit = vi
.spyOn(process, "exit")
Expand All @@ -35,10 +35,10 @@ describe("config", () => {
mockError.mockRestore();
});

it("exits when OPENCLAW_URL is missing", async () => {
it("exits when AGENCY_URL is missing", async () => {
process.env.CONVEX_URL = "https://test.convex.cloud";
delete process.env.OPENCLAW_URL;
process.env.OPENCLAW_TOKEN = "test-token";
delete process.env.AGENCY_URL;
process.env.AGENCY_TOKEN = "test-token";

const mockExit = vi
.spyOn(process, "exit")
Expand All @@ -49,7 +49,7 @@ describe("config", () => {
validateEnv();

expect(mockError).toHaveBeenCalledWith(
expect.stringContaining("OPENCLAW_URL"),
expect.stringContaining("AGENCY_URL"),
);
expect(mockExit).toHaveBeenCalledWith(1);

Expand All @@ -59,8 +59,8 @@ describe("config", () => {

it("does not exit when all required vars are set", async () => {
process.env.CONVEX_URL = "https://test.convex.cloud";
process.env.OPENCLAW_URL = "http://localhost:18789";
process.env.OPENCLAW_TOKEN = "test-token";
process.env.AGENCY_URL = "http://localhost:18789";
process.env.AGENCY_TOKEN = "test-token";

const mockExit = vi
.spyOn(process, "exit")
Expand All @@ -78,14 +78,14 @@ describe("config", () => {
describe("config object", () => {
it("has correct default values", async () => {
process.env.CONVEX_URL = "https://test.convex.cloud";
process.env.OPENCLAW_URL = "http://custom:8080";
process.env.OPENCLAW_TOKEN = "my-token";
process.env.AGENCY_URL = "http://custom:8080";
process.env.AGENCY_TOKEN = "my-token";

const { config } = await import("./config.js");

expect(config.convexUrl).toBe("https://test.convex.cloud");
expect(config.openclawUrl).toBe("http://custom:8080");
expect(config.openclawToken).toBe("my-token");
expect(config.agencyUrl).toBe("http://custom:8080");
expect(config.agencyToken).toBe("my-token");
});
});

Expand Down
6 changes: 3 additions & 3 deletions apps/watcher/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ export const POLL_INTERVAL_MS = 2000; // Check every 2 seconds

// Environment validation
export function validateEnv(): void {
const required = ["CONVEX_URL", "OPENCLAW_URL", "OPENCLAW_TOKEN"];
const required = ["CONVEX_URL", "AGENCY_URL", "AGENCY_TOKEN"];
const missing = required.filter((key) => !process.env[key]);

if (missing.length > 0) {
Expand All @@ -17,7 +17,7 @@ export function validateEnv(): void {

export const config = {
convexUrl: process.env.CONVEX_URL || "",
openclawUrl: process.env.OPENCLAW_URL || "http://localhost:18789",
openclawToken: process.env.OPENCLAW_TOKEN || "",
agencyUrl: process.env.AGENCY_URL || "http://localhost:18789",
agencyToken: process.env.AGENCY_TOKEN || "",
pollIntervalMs: POLL_INTERVAL_MS,
};
Loading