← back

Autobot

Nov 2025

Self-hosted Replit / Loveable / Bolt clone: chat with a coding agent and ship the result as a live preview URL

Autobot is a Replit / Lovable / Bolt-style platform.

User Journey

The user opens a chat and describes the app they want. Within a few seconds a live preview URL appears - they can click around the running app, ask for changes in chat, and see the diff applied. When they're happy with it, they hit "deploy" and get a persistent url.

Implementation

The system is built from a handful of building blocks:

  • GraphQL API - what the frontend talks to.
  • Temporal workers - run the long-running orchestration: provisioning the sandbox, brokering messages between the user and the agent, building and pushing the Docker image at deploy time. Workflow state is durable via event-sourced replay; activities are retried per their RetryPolicy.
  • Agent sandbox (runs on Modal) - one per chat. Holds /work/repo, runs the Claude Code Agents SDK as the OS user agent, and exposes dev servers on :3000 / :8000 (plus :5173 for Vite) through Modal's encrypted port tunnels. A per-workspace GCS prefix is mounted into the sandbox as a Modal cloud bucket mount at /cloud/source so the workspace survives sandbox restarts. Sandboxes shut down after 30 minutes of idle and are re-hydrated from GCS on the next message.
  • LLM proxy (on backend-go) - sandboxes never see the real Anthropic key. They authenticate to the proxy with their per-sandbox token; the proxy resolves it to a workspace, swaps in the real x-api-key (or a Vertex bearer token), and forwards to api.anthropic.com. Because every request is tied to a workspace, per-workspace metering, rate-limiting, and provider switching can live here.
  • Caddy - reverse-proxies the public *.preview subdomain to the per-sandbox Modal tunnel URLs.
  • Fly.io - target for production deployments. Each deploy creates a Fly app with its own secrets, machine, and *.fly.dev hostname.

Chat → sandbox provisioning

browser
frontendGraphQL client
1mutation: sendMessage(SendMessageInput)
backend-goautobot control plane
GraphQL APIauth, billing, persistence
Temporal workerPreviewWorkflow · DeploymentWorkflow
LLM proxyreverse proxy → api.anthropic.com
2client.ExecuteWorkflow("PreviewWorkflow", input) · TaskQueue: default
agent-sandboxruns on Modal · one per chat · 1 vCPU · 4 GiB · 30m idle shutdown
sdk_executorlong-polls backend for messages, drives Claude SDK
/work/repofrontend/ · backend/
dev servers:3000 / :5173 / :8000 · Modal encrypted tunnels
/cloud/sourceModal cloud bucket mount
/cloud/configModal cloud bucket mount
sync_daemonrepo → /cloud/source every 5s
3bucket mount: workspaces/<id>/{source,config}/
gcs://autobot-storagesource of truth · survives sandbox restart
workspaces/<id>/source/codebase
workspaces/<id>/config/agent state, MCP config
autobot-public/<id>/screenshots, uploads

LLM call: credential interception

The sandbox never sees the real Anthropic key. It authenticates to the backend's reverse proxy with a per-sandbox token; the proxy resolves it to a workspace, swaps in the real credentials server-side, and forwards upstream.

claude-agents-sdkANTHROPIC_BASE_URL = backend-go/anthropic
x-api-key: <per-sandbox token>
LLM proxyhttputil.ReverseProxy on backend-go
resolve token → workspace
swap in real x-api-key (or Vertex bearer)
set anthropic-version: 2023-06-01
api.anthropic.comauthenticated request
streamed response back through proxy

Going live

workspacesnapshot pulled from GCS
imageDockerfile generated, built, pushed
fly machineenv vars set, container released
persistent urllong-running container

Technology

Go, GraphQL, Postgres, Temporal, NATS, Python, Modal (sandbox runtime, cloud bucket mounts), Claude Code Agents SDK, GCS, Fly.io, Caddy.

← back