# Architecture Overview

> How Aerostack's layers connect — functions, MCP servers, workspaces, bots, and the SDK.

Aerostack has four layers that compose together. Understanding how they connect will help you decide what to build and how.

## The Full Picture

```mermaid
graph TB
    subgraph USERS["Users & Clients"]
        TELEGRAM["Telegram"]
        DISCORD["Discord"]
        WHATSAPP["WhatsApp"]
        SLACK["Slack"]
        WEBAPP["Your Web App(SDK)"]
        CLAUDE["Claude Desktop/ Cursor"]
    end

    subgraph BOTS_LAYER["Bots Layer"]
        BOT_ENGINE["Bot Engine"]
        AGENT_LOOP["Agent Loop<small>LLM picks tools</small>"]
        WORKFLOW["Workflow Engine<small>You design the flow</small>"]
        AUTH_GATE["Auth Gate<small>OTP / Magic Link</small>"]
        HANDOFF["Human Handoff<small>Pause → Approve → Resume</small>"]
    end

    subgraph WORKSPACE_LAYER["Workspace Layer — Single Gateway URL"]
        direction LR
        WS_GATEWAY["Gateway Router"]
        MCP_HOSTED["Hosted MCP<small>on Aerostack</small>"]
        MCP_PROXY["Proxy MCP<small>your server</small>"]
        MCP_HUB["Hub MCP<small>community</small>"]
        SKILL["Skills<small>single-purpose</small>"]
        FN["Functions<small>fullstack edge</small>"]
    end

    subgraph EDGE["Edge Runtime — Native Bindings"]
        direction LR
        DB["Database"]
        CACHE["Cache"]
        QUEUE["Queue"]
        AI["AI Providers"]
        VECTOR["Vector Search"]
        STORAGE["Storage"]
    end

    TELEGRAM --> BOT_ENGINE
    DISCORD --> BOT_ENGINE
    WHATSAPP --> BOT_ENGINE
    SLACK --> BOT_ENGINE
    BOT_ENGINE --> AGENT_LOOP
    BOT_ENGINE --> WORKFLOW
    WORKFLOW --> AUTH_GATE
    WORKFLOW --> HANDOFF

    AGENT_LOOP --> WS_GATEWAY
    WORKFLOW --> WS_GATEWAY
    CLAUDE --> WS_GATEWAY
    WEBAPP --> EDGE

    WS_GATEWAY --> MCP_HOSTED
    WS_GATEWAY --> MCP_PROXY
    WS_GATEWAY --> MCP_HUB
    WS_GATEWAY --> SKILL
    WS_GATEWAY --> FN

    MCP_HOSTED --> EDGE
    FN --> EDGE
    SKILL --> EDGE

    style USERS fill:#0f172a,stroke:#6b7280,stroke-width:1px
    style BOTS_LAYER fill:#0f172a,stroke:#f97316,stroke-width:2px
    style WORKSPACE_LAYER fill:#0f172a,stroke:#8b5cf6,stroke-width:2px
    style EDGE fill:#0f172a,stroke:#10b981,stroke-width:2px
```

## Layer 1: Edge Runtime (Foundation)

Every function, MCP server, and skill runs on Cloudflare Workers with **native bindings** to platform primitives. These are not HTTP calls — they're direct in-process access.

| Primitive | Binding | What It Does | Latency |
|-----------|---------|-------------|---------|
| **Database** | `env.DB` | SQL (SQLite-compatible) + Postgres routing | ~0ms |
| **Cache** | `env.CACHE` | Key-value cache with TTL, atomic counters | ~0ms |
| **Queue** | `env.QUEUE` | Background jobs with status tracking | ~0ms |
| **AI** | `env.AI` | Multi-provider LLM (OpenAI, Anthropic, Google, Groq) | Provider RTT |
| **Vector Search** | `env.VECTORIZE` | Semantic similarity, embeddings | ~0ms |
| **Storage** | `env.STORAGE` | Object storage with CDN | ~0ms |

Compare this to traditional serverless:

| Traditional | Aerostack |
|---|---|
| Function → HTTP → Database API → response | Function → `env.DB.prepare()` → response |
| Function → HTTP → Redis → response | Function → `env.CACHE.get()` → response |
| Function → HTTP → SQS → response | Function → `env.QUEUE.send()` → response |
| 50-200ms per service call | ~0ms — all in-worker |

## Layer 2: Functions, MCP Servers & Skills

These are the **building blocks** you create and deploy:

### Functions

Fullstack edge functions that power everything. They can serve HTTP, process queue messages, run on cron schedules, or be called by other Aerostack components.

```
src/index.ts → aerostack deploy → runs on Cloudflare edge (300+ cities)
                                    ↓ native access to
                                    DB · Cache · Queue · AI · Vector · Storage
```

### MCP Servers

Expose tools that AI can call. Three deployment modes:

```mermaid
graph LR
    subgraph MODES["Three Ways to Add MCP Servers"]
        HOST["Host on Aerostack<small>Build + deploy your MCP</small>"]
        PROXY["Proxy Existing<small>Your server, our gateway</small>"]
        HUB["Install from Hub<small>Community one-click</small>"]
    end

    subgraph GATEWAY["Workspace Gateway"]
        SECRETS["Encrypted Secrets"]
        ANALYTICS["Per-User Analytics"]
        TOKENS["Team Tokens"]
    end

    HOST --> GATEWAY
    PROXY --> GATEWAY
    HUB --> GATEWAY

    style MODES fill:#0f172a,stroke:#8b5cf6,stroke-width:2px
    style GATEWAY fill:#0f172a,stroke:#3b82f6,stroke-width:2px
```

**Proxy mode** is key for teams: your MCP server stays on your infrastructure, but Aerostack handles secrets, access control, and monitoring. Team members never see API keys.

### Skills

Single-purpose tools (e.g., "send email", "generate PDF"). Lighter than a full MCP server. Deploy as a Worker, install into workspaces.

## Layer 3: Workspaces (Composition)

A workspace combines multiple MCP servers, skills, and functions behind **one gateway URL**. Any MCP-compatible client can connect to it.

```
Workspace "customer-tools"
├── Stripe MCP (proxy — keys in vault)
├── GitHub MCP (hosted on Aerostack)
├── Notion MCP (installed from Hub)
├── Skill: send-email
└── Function: order-lookup (fullstack edge)

Gateway URL: https://mcp.aerostack.dev/ws/customer-tools
Token: mwt_abc123...
```

**What connects to workspaces:**
- **Bots** — connect via `workspace_id`, get access to all tools
- **Claude Desktop / Cursor** — connect via gateway URL + bearer token
- **Any MCP client** — standard JSON-RPC 2.0 protocol
- **Other Aerostack workspaces** — composition of compositions

## Layer 4: Bots (Consumer-Facing AI)

Bots are the consumer-facing layer. They receive messages from platforms and use workspace tools to take action.

```mermaid
graph TB
    MSG["User sends message<small>Telegram / Discord / WhatsApp / Slack</small>"]

    MSG --> DECIDE{"workflow_enabled?"}

    DECIDE -->|No| AGENT["Agent Loop<small>LLM autonomously picks tools</small>"]
    DECIDE -->|Yes| WF["Workflow Engine"]

    WF --> AUTH["auth_gate<small>Verify identity (OTP/magic link)</small>"]
    WF --> LOGIC["logic<small>if/else, switch</small>"]
    WF --> LLM["llm_call<small>Generate text</small>"]
    WF --> MCP_TOOL["mcp_tool<small>Call any workspace tool</small>"]
    WF --> CODE["code_block<small>Run JavaScript</small>"]
    WF --> HANDOFF_NODE["human_handoff<small>Pause → notify → approve/reject</small>"]
    WF --> DELEGATE["delegate_to_bot<small>Call another bot</small>"]
    WF --> SEND["send_message<small>Respond to user</small>"]
    WF --> SCHEDULE["schedule_message<small>Send later</small>"]

    AGENT --> TOOLS["Workspace Tools<small>All MCPs + Skills + Functions</small>"]
    MCP_TOOL --> TOOLS

    style MSG fill:#0f172a,stroke:#6b7280,stroke-width:1px
    style DECIDE fill:#1e293b,stroke:#f97316,stroke-width:2px
    style AGENT fill:#0f172a,stroke:#3b82f6,stroke-width:2px
    style WF fill:#0f172a,stroke:#f97316,stroke-width:2px
    style TOOLS fill:#0f172a,stroke:#8b5cf6,stroke-width:2px
```

**Two modes serve different needs:**

| | Agent Loop | Workflow |
|---|---|---|
| **Best for** | Open-ended chat, Q&A | Deterministic flows, approvals |
| **Tool access** | LLM decides which tools | You place tools explicitly |
| **Auth** | Via tools | Native `auth_gate` node |
| **Human approval** | Via tools | Native `human_handoff` node |
| **Delegation** | No | Yes — call other bots |
| **Code execution** | No | Yes — sandboxed JavaScript |
| **Scheduled messages** | No | Yes — delay-based |

## The SDK (Client Access)

The SDK gives your frontend/mobile app direct access to the edge runtime primitives:

```mermaid
graph LR
    subgraph CLIENT["Your App"]
        REACT["React Hooks"]
        NODE["Node.js Client"]
        GO["Go Client"]
        PY["Python Client"]
        FLUTTER["Flutter Client"]
    end

    subgraph PRIMITIVES["Edge Runtime"]
        AUTH_P["Auth"]
        DB_P["Database"]
        RT["Realtime"]
        STORE["Storage"]
        AI_P["AI"]
        CACHE_P["Cache"]
        QUEUE_P["Queue"]
        VS["Vector Search"]
    end

    CLIENT --> PRIMITIVES

    style CLIENT fill:#0f172a,stroke:#3b82f6,stroke-width:2px
    style PRIMITIVES fill:#0f172a,stroke:#10b981,stroke-width:2px
```

One install, one provider — all primitives accessible:

```tsx
// React — one import, everything available
const { user, signIn } = useAuth()
const { query } = useDb()
const { messages } = useSubscription('chat/room-1')
```

## How the Layers Compose

Here's a real-world example — a **customer support system**:

```
User messages Telegram bot
  ↓
Bot (Workflow Mode)
  ↓ auth_gate → verify customer email via OTP
  ↓ mcp_tool → stripe__get_customer (Stripe MCP, proxied)
  ↓ mcp_tool → order-lookup (Function, queries DB natively)
  ↓ logic → order.total > $500?
  ↓   yes → human_handoff → notify manager on Slack
  ↓           manager approves → mcp_tool → stripe__create_refund
  ↓   no → mcp_tool → stripe__create_refund (auto-approve)
  ↓ send_message → "Your refund of $X has been processed"

Behind the scenes:
  - Stripe API key never left Aerostack's encrypted vault
  - Manager approved from their phone via Slack notification
  - order-lookup function queried the database natively (~0ms)
  - Every tool call logged with per-user analytics
  - Customer never left the Telegram chat
```

## Next Steps

Now that you understand the architecture, pick where to start:

- **[Functions](/functions)** — The foundation. Write fullstack edge functions.
- **[MCP Servers](/mcp)** — Host, proxy, or install AI tools.
- **[Workspaces](/workspaces)** — Compose tools behind one URL.
- **[Bots](/bots)** — Build intelligent bots with workflows.
- **[SDK](/sdk)** — Connect your frontend to the edge runtime.
