Architecture
Components
| Component | Source | Responsibility |
|---|---|---|
| Desktop client | client/ (Electron) | The workspace people use. Its main process manages native features and the local runner; chats go through one agent-runtime layer |
| Hub | hub-backend/ (FastAPI) | The authority for accounts, organizations, tasks, workflows and permissions. app/api/ handles protocols and identity checks; app/services/ holds business logic; versioned migrations manage the database |
| Admin console | hub-frontend/ (React) | Configuration and governance. Its production build is served by the Hub |
| Runner | hub-backend/runner_main.py | Runs work. Built from the Hub's Python source and bundled with the client. The same runner program runs in three ways: started by the desktop client on this computer, on an authorized workstation, or on a cloud host. The computer or server it runs on is called the execution host |
| Skills | skills/ | Skills shared by the client and runners |
How work flows
- A person starts a chat, an issue or an automation in the client.
- The client talks to the Hub over HTTPS and a WebSocket. The Hub records the task.
- The Hub dispatches the work to a runner: the local runner in that person's client, or a workstation or cloud runner over the runner WebSocket.
- The runner starts the chosen harness (runtime) and injects the model settings and a short-lived credential for that run only.
- The harness calls the model and its tools: Skills, MCP servers, connectors and Git.
- Output and files go back to the Hub. Any client of that account can see progress and results.
Design rules
- The Hub is the single source of truth for tasks. The client keeps only a read cache and a queue of unsent operations. Tasks are created with an idempotent
PUT /tasks/{id}, changed field by field and deleted only by an explicitDELETE. A missing task in a client never means it was deleted. - One task record. Issues in the UI and tasks in the API are the same
Taskrecord. Attachments, approvals, comments and deliveries attach to it. - One harness list. The harness catalog (
agent_catalog.json) is shared by the client, Hub and runner. - Accounts, not devices. A device ID locates a machine; it never stands in for a user. The Hub checks both. Work stays with the account that owns it, even if someone else signs in on the same device.
- Database changes are migrations. Existing user data, device identities and protocol fields are never dropped to simplify a change.
Databases
| Use | Database |
|---|---|
| Development and the source launcher | SQLite |
| Docker and production | PostgreSQL |
Runner internals
- Connection. The runner connects to the Hub over a WebSocket. It receives dispatch, continue, stop and approval messages, and sends back events and heartbeats. When the desktop client manages the runner, its main process starts and stops it through a local process channel.
- Intake. Every dispatch carries an ID, so the same task is never taken twice. Chats come before background work, and resource budgets limit how much runs at once.
- Execution. Each harness (runtime) runs in its own subprocess. If the runner reconnects to the Hub, work in progress keeps running.
- Delivery. Events are saved on the execution host before they are sent, and the Hub acknowledges them after saving. After a disconnect they are sent again, and the runner recovers on its own after a restart.