Skip to main content

Overview

Every user interaction in OpenSail follows a consistent request/response pattern that flows through the frontend, orchestrator, database, and (optionally) the container runtime. This page documents the lifecycle of each major flow: general API requests, agent chat, file operations, container management, Git operations, deployments, and streaming patterns. If you are new to the codebase, start with the General API Request Flow to understand the common pattern, then explore the specific flows relevant to your work.

General API Request Flow

All user interactions follow this eight-step lifecycle.
1

User interaction

The user performs an action in the browser (click, type, navigate).
2

Frontend sends request

The React app sends an HTTP or WebSocket request to the Orchestrator. Authentication is included via Authorization: Bearer {jwt} header or session cookie.
3

Orchestrator validates auth

FastAPI middleware decodes the JWT token, verifies the user session, and checks permissions (RBAC).
4

Database query or update

The Orchestrator queries or updates PostgreSQL using async SQLAlchemy.
5

Perform operation

Depending on the request type, the Orchestrator delegates to the appropriate subsystem:
  • File operation: Container filesystem (direct in Docker, pod exec in K8s)
  • Container operation: Docker Compose or Kubernetes API
  • AI chat: LiteLLM proxy to OpenAI/Anthropic
  • Deployment: Vercel/Netlify/Cloudflare API
6

Build response

The Orchestrator assembles the JSON response from the operation result and database state.
7

Return to frontend

The response is sent back to the React app over the same HTTP connection (or as SSE/WebSocket events for streaming).
8

UI update

The frontend updates its state and re-renders the relevant components.

Request Flow Diagram

Agent Chat Flow

The agent chat is the most complex data flow, involving LLM calls, tool execution, and real-time streaming to the frontend via Server-Sent Events (SSE).
1

User types a message

The user enters a message in the chat UI (e.g., “Create a React component for a todo list”).
2

Frontend opens SSE connection

The frontend sends POST /api/chat/stream with { project_id, message, chat_id } and opens an EventSource for streaming.
3

Load chat history

The chat router loads previous messages from the database and builds conversation context.
4

Create agent instance

agent/factory.py instantiates a tesslate-agent with the appropriate system prompt, available tools (read_file, write_file, bash_exec, etc.), and LLM model.
5

Agent execution loop

The tesslate-agent enters a loop:
  1. Call the LLM with system prompt + conversation history
  2. If the LLM returns tool calls, execute them (e.g., write_file, bash_exec)
  3. Stream each tool execution event to the frontend
  4. Call the LLM again with tool results
  5. Repeat until the LLM produces a final text response
6

Stream final response

The agent streams its final message to the frontend, which renders it in real-time in the chat UI.

Agent Tool Execution Example

User prompt: “Create a React component for a todo list”

Available Agent Tools

File Operations Flow

File reads and writes differ depending on deployment mode. In Docker mode, the orchestrator accesses the filesystem directly. In Kubernetes mode, it executes commands inside the file-manager pod.

Container Operations Flow

Container start and stop operations are non-blocking. The Orchestrator returns immediately and the frontend polls for status updates.

Start Project Containers

1

User clicks Start

Frontend sends POST /api/projects/{id}/start.
2

Validation and background task

The Orchestrator validates auth, checks that the project is not already running, queues a background task for container setup, and returns { "status": "starting" } immediately.
3

Frontend polls for status

The frontend polls GET /api/projects/{id}/status every 2 seconds.
4

Background task executes (Kubernetes mode)

  1. Create namespace (proj-{uuid})
  2. Create PVC (shared storage, e.g. 10Gi RWO)
  3. Restore from VolumeSnapshot if hibernated (or hydrate from S3 for legacy projects)
  4. Create file-manager pod (always running)
  5. For each container: create Deployment + Service + Ingress
  6. Create NetworkPolicy for isolation
  7. Update project status in database to “running”
  8. Return container URLs
5

Frontend detects running state

Status poll detects “running”. The frontend displays container URLs and enables the live preview iframe.

Stop Project Containers

1

User clicks Stop (or navigates away)

Frontend sends POST /api/projects/{id}/stop.
2

Background task: dehydrate and delete

  1. Create VolumeSnapshot from PVC (under 5 seconds)
  2. Wait for snapshot readiness
  3. Delete namespace (cascades to all resources: Deployments, Services, Ingress, PVC, NetworkPolicy)
  4. Update project status to “hibernated”
3

Frontend detects stopped state

Status poll detects “stopped” or “hibernated”. Live preview is disabled and the Start button appears.
In Kubernetes mode, hibernation creates an EBS VolumeSnapshot that preserves the entire filesystem state including node_modules. No npm install is needed on restore. Projects restore in under 10 seconds thanks to EBS lazy-loading.

Git Operations Flow

Clone Repository

Commit and Push

Deployment Flow (External Providers)

External deployments to Vercel, Netlify, or Cloudflare follow a consistent non-blocking pattern.
1

User initiates deployment

Frontend sends POST /api/deployments with provider name, project ID, and configuration.
2

Retrieve OAuth credentials

The Orchestrator decrypts the user’s stored DeploymentCredential for the chosen provider.
3

Background build and deploy

  1. Build the project locally (e.g., npm run build)
  2. Push to Git if needed (create/update GitHub repo)
  3. Call provider API to create deployment
  4. Poll provider API until deployment status is “READY”
  5. Save deployment record to database
4

Notify frontend

A WebSocket message or status poll delivers the live URL to the frontend, which displays a success message with a link to the deployed application.

WebSocket and SSE Streaming Patterns

OpenSail uses two streaming mechanisms for real-time communication.
Backend (FastAPI):
Frontend (EventSource):
Use cases: Agent chat streaming, build output streaming.

Performance Optimizations

Long-running operations return immediately and execute in the background. The frontend polls for status.
Use selectinload() to prevent N+1 queries and load related objects in a single query.

Key Source Files