The future of AI Assistants and Workflow Automations.
Belgrade is a chat-based AI assistant platform powered by FastAPI (backend) and React (frontend). The system uses WebSocket for real-time bidirectional communication between the client and AI agents.
- Backend: FastAPI + SQLAlchemy + PostgreSQL/Supabase
- Frontend: React + TypeScript + Vite
- Database: PostgreSQL (via Supabase)
- AI Engine: CanvasAgent with tool execution capabilities
- Communication: WebSocket at
/ws/projects/{project_id}/chat
belgrade/
├── backend/ # FastAPI application
│ ├── app/
│ │ ├── api/ # REST & WebSocket endpoints
│ │ ├── model/ # SQLAlchemy models
│ │ ├── services/ # Business logic & AI agents
│ │ └── auth/ # Authentication
│ └── migrations/ # Alembic database migrations
├── frontend/ # React application
│ ├── api/ # API client code
│ ├── components/ # React components
│ └── pages/ # Page components
└── sync-env.sh # Utility to sync .env files for worktrees
- Python 3.11+ with Poetry
- Node.js 18+
- PostgreSQL database (or Supabase account)
- Install dependencies:
cd backend
poetry install- Configure environment:
# Copy .env.example to .env and configure:
# - Database URL (Supabase or local PostgreSQL)
# - API keys (Anthropic, OpenAI, etc.)- Run migrations:
poetry run alembic upgrade head- Start the server:
poetry run uvicorn app.main:app --reload --port 8000Backend will be available at http://localhost:8000
- Install dependencies:
cd frontend
npm install- Configure environment:
# Copy .env.example to .env.local and configure:
# - VITE_API_URL=http://localhost:8000- Start the dev server:
npm run devFrontend will be available at http://localhost:5173
- Real-time bidirectional communication via WebSocket
- Message history persistence
- Multi-modal message parts (text, tool calls, tool results)
- Human-in-the-loop (HITL) tool confirmation
- CanvasAgent: General-purpose agent with tool execution
- Tool system: Read files, write files, execute code, search web, etc.
- Model selection: Support for Claude, GPT-4, and other LLMs
- Multi-project workspace
- Project collaboration
- Code snapshot versioning
- Run logs and execution history
Chat
GET /api/chat/models- List available LLM modelsGET /api/chat/history/{project_id}- Get chat history
Projects
GET /api/projects- List user projectsPOST /api/projects- Create new projectGET /api/projects/{id}- Get project detailsPUT /api/projects/{id}- Update project
Code Snapshots
POST /api/projects/{id}/code_snapshot- Create code snapshotGET /api/projects/{id}/code_snapshots- List snapshots
Endpoint: /ws/projects/{project_id}/chat
Client → Server Messages:
{
type: "message",
content: string,
model?: string,
variables_continue?: { ... } // Resume agent execution
}Server → Client Messages:
{
type: "text" | "tool_call" | "tool_result" | "agent_done" | "error",
content: any,
metadata?: { ... }
}projects
id(UUID, PK)name(String)created_by(UUID, FK → users)example_prompts(JSONB) - LLM-generated example prompts
messages
id(UUID, PK)project_id(UUID, FK → projects)role(String: "user" | "assistant")message_parts(JSONB) - Structured message contentcreated_on(DateTime)
code_snapshots
id(UUID, PK)project_id(UUID, FK → projects)file_states(JSONB) - File system state at snapshot timecreated_at(DateTime)
run_logs
- Execution logs for agent runs
- Tool invocations and results
Create a new migration:
cd backend
alembic revision -m "description"Apply migrations:
alembic upgrade headCheck migration status:
alembic currentRollback one migration:
alembic downgrade -1If using git worktrees, use the sync-env.sh script to copy .env files:
./sync-env.shThis copies .env files from the main repository to the current worktree.
Backend (8000):
lsof -ti:8000 | xargs kill -9Frontend (5173):
lsof -ti:5173 | xargs kill -9Messages use a structured format with multiple parts:
message_parts = [
{ type: "text", content: "Hello" },
{ type: "tool_call", id: "...", name: "read_file", params: {...} },
{ type: "tool_result", tool_call_id: "...", result: {...} }
]This enables:
- Multi-modal messages (text + tool calls + results)
- Tool execution tracking
- Human-in-the-loop confirmations
- Precise message replay
- User sends message via WebSocket
- Backend creates Message record with role="user"
- CanvasAgent processes message:
- Generates response (text and/or tool calls)
- Executes tools (with HITL confirmation if needed)
- Streams results back to client
- Backend creates Message record with role="assistant"
- Client updates UI in real-time
The codebase underwent a significant cleanup to remove legacy v1 code:
Removed:
- Canvas visualization infrastructure (graph state, canvas_state columns)
- Snapshot table (replaced by code_snapshots)
- Broken SSE endpoints (replaced by WebSocket)
- Canvas utilities (canvas_utils.py, canvas_representation.py)
Impact: 447 lines deleted, 4 files removed, 3 database columns/table dropped
See .context/deep-cleanup-complete.md for detailed cleanup documentation.
If using worktrees and getting connection errors:
./sync-env.shIf migrations fail, check:
- Database connection in
.env - Migration history:
alembic current - Pending migrations:
alembic history
- Ensure backend is running on port 8000
- Check CORS settings in backend
- Verify WebSocket endpoint:
ws://localhost:8000/ws/projects/{id}/chat
- Create a feature branch from
master - Make changes
- Run tests
- Create pull request
Proprietary - All rights reserved