Architecture
Uranus follows a serverless, edge-first architecture built entirely on Cloudflare's infrastructure.
System Overview
┌──────────────────────────────────────────────────────────────────┐
│ Cloudflare Edge Network │
├──────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ Static Assets │ │ Worker Entry │ │
│ │ (React SPA) │ │ (src/worker.ts)│ │
│ └────────┬────────┘ └────────┬─────────┘ │
│ │ │ │
│ │ ┌─────────────────┼─────────────────┐ │
│ │ │ │ │ │
│ ▼ ▼ ▼ ▼ │
│ ┌──────────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ API Routes │ │ WebSocket │ │ Queue │ │
│ │ (/api/agents/*) │ │ (/agent/*) │ │ Consumer │ │
│ └────────┬─────────┘ └──────┬───────┘ └──────┬───────┘ │
│ │ │ │ │
│ └────────────────────┼──────────────────┘ │
│ │ │
│ ┌───────────▼───────────┐ │
│ │ Durable Object │ │
│ │ (DashboardAgent) │ │
│ │ │ │
│ │ • WebSocket Handler │ │
│ │ • State Management │ │
│ │ • Alarm Scheduler │ │
│ │ • API Router │ │
│ └───────────┬───────────┘ │
│ │ │
│ ┌───────────────────────┼───────────────────────┐ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ D1 │ │ R2 │ │ Vectorize│ │
│ │ Database │ │ Storage │ │ Embeddings│ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ │
└──────────────────────────────────────────────────────────────────┘Core Components
Worker Entry Point
The main src/worker.ts handles all incoming requests:
typescript
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext) {
// Route handling
// - Static assets (from Vite build)
// - API routes (/api/*)
// - WebSocket connections (/agent/*)
},
async queue(batch: MessageBatch, env: Env) {
// Async workflow execution
}
}Durable Objects
Each agent is a separate DashboardAgent Durable Object instance:
typescript
export class DashboardAgent implements DurableObject {
// Persistent state
private state: DurableObjectState;
// Handle HTTP requests
async fetch(request: Request): Promise<Response>;
// Handle WebSocket messages
async webSocketMessage(ws: WebSocket, message: string);
// Execute scheduled tasks
async alarm(): Promise<void>;
}Key Properties:
- Isolation - Each agent has its own instance
- State - Persistent storage via
this.state.storage - Alarms - Built-in scheduling mechanism
- WebSockets - Native real-time support
Database Layer
D1 (SQLite) stores all persistent data:
| Table | Purpose |
|---|---|
agents | Agent registry |
agent_settings | Per-agent configuration |
workflows | Visual workflow definitions |
schedules | Cron and one-time tasks |
chat_messages | Conversation history |
browser_sessions | Browser automation sessions |
contacts | Contact directory |
data_sources | RAG source files |
Storage Layer
R2 handles file storage:
- Uploaded documents for RAG
- Browser screenshots
- Workflow artifacts
Vector Database
Vectorize enables semantic search:
- Document embeddings
- RAG query matching
- Content similarity search
Request Flow
API Request
Client Request
│
▼
┌─────────────┐
│ Worker │
│ (Routing) │
└──────┬──────┘
│
▼
┌─────────────┐ ┌─────────────┐
│ Pages │────▶│ Durable │
│ Functions │ │ Object │
└─────────────┘ └──────┬──────┘
│
▼
┌─────────────┐
│ D1 │
│ Database │
└─────────────┘WebSocket Connection
Client WebSocket
│
▼
┌─────────────┐
│ Worker │
│ (Upgrade) │
└──────┬──────┘
│
▼
┌─────────────────────────┐
│ Durable Object │
│ │
│ • Accept connection │
│ • Add to client set │
│ • Handle messages │
│ • Broadcast updates │
└─────────────────────────┘Scheduled Task
┌─────────────────────────┐
│ Durable Object │
│ │
│ alarm() triggered │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ Get pending │ │
│ │ schedules │ │
│ └──────┬──────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ Execute │ │
│ │ workflow │ │
│ └──────┬──────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ Update next │ │
│ │ run time │ │
│ └─────────────┘ │
└─────────────────────────┘Multi-Tenancy Model
Each agent operates in isolation:
┌─────────────────────────────────────────────┐
│ Cloudflare Workers │
├──────────────┬──────────────┬───────────────┤
│ Agent A │ Agent B │ Agent C │
│ │ │ │
│ ┌──────────┐ │ ┌──────────┐ │ ┌──────────┐ │
│ │ Durable │ │ │ Durable │ │ │ Durable │ │
│ │ Object │ │ │ Object │ │ │ Object │ │
│ └──────────┘ │ └──────────┘ │ └──────────┘ │
│ │ │ │ │ │ │
│ ▼ │ ▼ │ ▼ │
│ ┌───────┐ │ ┌───────┐ │ ┌───────┐ │
│ │State A│ │ │State B│ │ │State C│ │
│ └───────┘ │ └───────┘ │ └───────┘ │
└──────────────┴──────────────┴───────────────┘
│
▼
┌─────────────────────────┐
│ Shared D1 Database │
│ │
│ WHERE agent_id = ? │
└─────────────────────────┘Security Architecture
Access Control Layers
Cloudflare Access (Optional)
- JWT validation
- Identity provider integration
Email-Based Access
- Role-based permissions (owner, admin, viewer)
- Per-agent access control
Agent Isolation
- Data scoped by agent_id
- Separate Durable Object instances
Authentication Flow
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Client │────▶│ Worker │────▶│ Durable │
│ Request │ │ (Auth) │ │ Object │
└─────────────┘ └──────┬──────┘ └─────────────┘
│
┌────────────┼────────────┐
│ │ │
▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│ CF │ │ Email │ │ Agent │
│ Access │ │ Check │ │ Access │
└─────────┘ └─────────┘ └─────────┘Technology Choices
| Component | Technology | Rationale |
|---|---|---|
| Runtime | Cloudflare Workers | Edge deployment, low latency |
| State | Durable Objects | Stateful compute, WebSocket support |
| Database | D1 (SQLite) | Edge-native, SQL interface |
| Storage | R2 | S3-compatible, no egress fees |
| Vectors | Vectorize | Native integration, fast similarity search |
| AI | Workers AI | Edge inference, multiple models |
| Frontend | React + Vite | Modern DX, fast builds |
| UI | Radix + Tailwind | Accessible, customizable |