FastAPI backend for the MindsHub Cowork desktop app
Project description
Cowork Server
FastAPI backend for MindsHub Cowork. Manages projects, conversations, files, scheduling, memory, and agent orchestration with a SQLite-backed data layer.
This repo is the Python backend. The frontend (Electron shell + React SPA) lives in a separate repo: mindsdb/cowork. They are developed and released independently. At runtime, the frontend spawns cowork-server as a local sidecar and communicates over HTTP (127.0.0.1:26866).
Quick Start
Requires Python 3.12+ and uv.
# Install and run
uv tool install cowork-server
cowork-server
The server starts on http://127.0.0.1:26866. Confirm with:
curl http://127.0.0.1:26866/api/v1/health/
Development
# Run from source (auto-manages virtualenv + deps)
uv run cowork-server
When running alongside the Electron app in dev mode, the app spawns the server automatically — no manual start needed. The Electron app looks for a sibling cowork-server/ directory by convention (override with COWORK_SERVER_DIR).
Dev setup helper
uv run cowork-dev-setup
Initializes the database and validates configuration.
Testing
uv run pytest
Tests use an isolated in-memory database and temporary directories — no side effects on your local ~/.cowork/ data.
Logging
Set LOG_LEVEL (default INFO) to control verbosity. Enable file logging with ENABLE_FILE_LOGGING=true (writes to LOG_DIR, defaults to ~/.cowork/logs/).
Releasing
- Bump
versioninpyproject.toml - Create a GitHub release with a matching tag (e.g.
v0.1.5) - The
publish.ymlworkflow builds and publishes to PyPI via OIDC trusted publishing
In the packaged Electron app, a background updater checks PyPI on every launch and upgrades automatically (with rollback on failure). See server-updater.ts in the frontend repo.
Architecture
cowork/
api/v1/endpoints/ # FastAPI route handlers
services/ # Business logic
models/ # SQLModel / DB models
schemas/ # Pydantic request/response schemas
db/ # Database session and migrations
common/ # Shared utilities, settings
harnesses/ # Agent adapters (Anton, Hermes, etc.)
The server is designed to be agent-agnostic — core features (projects, conversations, files) are shared across agents, while agent-specific behavior lives in harness adapters. See docs/DESIGN.md for the full architectural rationale.
Harness system
A harness adapts an external agent library (Anton, Hermes, etc.) to the cowork-server interface. All harnesses implement the HarnessProvider protocol (harnesses/base.py), which exposes streaming responses, skill sync, and memory operations. The active harness is selected via the harness user setting. To add a new agent, implement the protocol and register it with the @register decorator.
Streaming & scheduling
Agent responses stream to clients via Server-Sent Events (SSE) on POST /responses/. The server tracks in-flight streams and supports cancellation (/responses/cancel) and late-join tailing (/responses/tail).
A background scheduler loop polls the database every 30 seconds for due schedules, supporting once, hourly, daily, and weekly cadences. Each run creates a conversation and is tracked in schedule_runs.
Data Layer
Data lives in two places: a SQLite database for structured records and the filesystem for project files and agent workspaces. Understanding both is essential.
SQLite database
- Location:
~/.cowork/cowork.db(override withDATABASE_URI) - ORM: SQLModel (SQLAlchemy + Pydantic)
- Migrations: Alembic (
cowork/db/alembic/versions/). Startup runsalembic upgrade head(singular), so the graph must have exactly ONE head: if two branches each added a migration on the same parent, every fresh boot aborts with "Multiple head revisions". After merging or rebasing, checkalembic heads; if it prints two revisions, add a no-op merge revision whosedown_revisionis the tuple of both heads (seef4e2c1a9d3b7for the pattern).
Key tables:
| Table | Purpose |
|---|---|
projects |
Project metadata and filesystem path |
conversations |
Conversation threads, linked to a project |
messages |
Individual messages with role, content (JSON), and harness tag |
message_events |
Streaming event payloads for a message |
files |
Metadata for uploaded files (path points to filesystem) |
schedules / schedule_runs |
Recurring prompts and their execution history |
settings |
Key-value user settings; sensitive values Fernet-encrypted |
pins |
User-pinned items (conversations, artifacts, etc.) |
channel_* |
Channel installations, bindings, sessions, and events |
All models use UUID primary keys with auto-tracked created_at/modified_at timestamps.
Filesystem storage
~/.cowork/
├── cowork.db # SQLite database
├── .master_key # Fernet encryption key for settings
├── skills/ # COWORK_SKILLS_DIR — canonical SKILL.md store
│ └── <slug>/SKILL.md # one folder per skill (see docs/SKILLS.md)
├── projects/ # COWORK_PROJECTS_DIR
│ ├── general/ # Default project (always exists)
│ └── <project-name>/
│ ├── <user & agent files> # Working directory visible to agents
│ ├── skills/ # symlinks to skills enabled for this project
│ │ └── <slug> -> ~/.cowork/skills/<slug>
│ └── .anton/ # Private agent workspace
│ ├── artifacts/ # Agent-produced outputs (HTML apps, docs, etc.)
│ │ └── <slug>/
│ │ ├── metadata.json
│ │ └── <files>
│ ├── memory/ # Persistent agent memory by category
│ └── context/ # Project context for agent runs
├── files/ # COWORK_FILES_DIR — uploaded files
│ └── <file-id>/<filename>
└── data-vault/ # COWORK_VAULT_DIR — encrypted connector creds
└── <engine>/<connection-name>/
How the two layers relate
The database holds structured metadata and relationships (which messages belong to which conversation, which conversation belongs to which project). The filesystem holds the actual content agents work with — project files, artifacts, memory entries, and uploaded documents. The files and projects DB tables store filesystem paths that point into the directory tree above.
This split is the result of an ongoing migration from a purely filesystem-based architecture. Structured data that benefits from querying and relationships — conversations, messages, settings, schedules — lives in SQLite. Components that are inherently file-based — project working directories, agent artifacts, harness-managed memory, connector vault credentials, and skills — remain on the filesystem by design. (Skills briefly lived in a DB table; they were moved back to canonical SKILL.md files so they can be edited, uploaded, and distributed per project — see docs/SKILLS.md.) See docs/SERVER_MIGRATION.md for the full migration story.
Agents (via their harness) have read/write access to their project's working directory and the private .anton/ subdirectory. They do not access the SQLite database directly — all DB interaction flows through the service layer.
Settings use a hybrid approach: user preferences and API keys are stored in the settings DB table (with Fernet encryption for secrets), while connector credentials live in the filesystem vault (data-vault/).
API
All endpoints live under /api/v1/. Key resource groups:
| Path | Description |
|---|---|
/health |
Readiness probe |
/projects |
Project CRUD and working-folder management |
/conversations |
Conversation threads and message history |
/responses |
Streaming agent responses (SSE) |
/files |
OpenAI-compatible file uploads |
/schedules |
Recurring task scheduling |
/skills |
Agent skill definitions |
/memory |
Persistent agent memory |
/artifacts |
Agent-produced file previews |
/publish |
Publish HTML artifacts to 4nton.ai |
/connectors |
Third-party service connections and OAuth |
/settings |
User preferences and API keys |
Configuration
Configuration is read from the database (UserSettings table) and can be managed through the Settings UI in the desktop app or via PUT /api/v1/settings/.
Environment variables fall into two namespaces:
Server-level (COWORK_*) — control the cowork-server process itself:
| Variable | Default | Description |
|---|---|---|
COWORK_LISTEN_PORT |
26866 |
Server port |
COWORK_SERVER_HOST |
127.0.0.1 |
Bind address |
COWORK_PROJECTS_DIR |
~/.cowork/projects |
Project storage root |
COWORK_FILES_DIR |
~/.cowork/files |
Uploaded files root |
COWORK_VAULT_DIR |
~/.cowork/data-vault |
Connector credential vault |
Harness-level (ANTON_*, HERMES_*) — configure a specific agent harness. These are read by the harness adapter, not by cowork-server core. They use the harness prefix because the upstream agent libraries (anton, hermes-agent) define them:
| Variable | Harness | Description |
|---|---|---|
ANTON_PUBLISH_URL |
Anton | Artifact publish endpoint |
ANTON_SKILLS_ROOT_DIR |
Anton | Skill file storage |
ANTON_GLOBAL_MEMORY_ROOT_DIR |
Anton | Global memory files |
HERMES_HOME / HERMES_ROOT_DIR |
Hermes | Hermes data root |
In Docker/Lightsail deployments, the container also receives ANTON_MINDS_API_KEY, ANTON_OPENAI_API_KEY, etc. — these are consumed by the Anton agent library directly (not by cowork-server settings), and are injected by the provisioning lambda via cloud-init user-data.
Docs
- docs/DESIGN.md — Architectural overview and design decisions
- docs/MIGRATION.md — Migration guide from the legacy server
- docs/MIGRATION_PROGRESS.md — Migration status tracker
License
See LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cowork_server-0.26.7.23.1rc2.tar.gz.
File metadata
- Download URL: cowork_server-0.26.7.23.1rc2.tar.gz
- Upload date:
- Size: 786.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7ac5dc3d8bdd7e68d49dcbc964c1e0816503e1ef74741325cef1c8c282b69477
|
|
| MD5 |
939e41dadffa9f398e23a753dd7a0fb6
|
|
| BLAKE2b-256 |
253c861b2ac7dd98174206d188b5c27ce4f1ec3ae58bb94c10212569df58a6ff
|
Provenance
The following attestation bundles were made for cowork_server-0.26.7.23.1rc2.tar.gz:
Publisher:
publish-staging.yml on mindsdb/cowork-server
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cowork_server-0.26.7.23.1rc2.tar.gz -
Subject digest:
7ac5dc3d8bdd7e68d49dcbc964c1e0816503e1ef74741325cef1c8c282b69477 - Sigstore transparency entry: 2229169589
- Sigstore integration time:
-
Permalink:
mindsdb/cowork-server@93a58452fc179bfa197c8d851bc67c01f214b2a6 -
Branch / Tag:
refs/heads/staging - Owner: https://github.com/mindsdb
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-staging.yml@93a58452fc179bfa197c8d851bc67c01f214b2a6 -
Trigger Event:
push
-
Statement type:
File details
Details for the file cowork_server-0.26.7.23.1rc2-py3-none-any.whl.
File metadata
- Download URL: cowork_server-0.26.7.23.1rc2-py3-none-any.whl
- Upload date:
- Size: 838.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5adf85b0ac9a3edca9407313a00f8756e4cd58967c1d704e8eb49a39a03afb79
|
|
| MD5 |
1dc2d575693bc5afeeb49693f0fb4f6f
|
|
| BLAKE2b-256 |
d9eda34b190085d2ee1bb11e2b23ee7f29ca55fbec800f80c96ae99121962c8c
|
Provenance
The following attestation bundles were made for cowork_server-0.26.7.23.1rc2-py3-none-any.whl:
Publisher:
publish-staging.yml on mindsdb/cowork-server
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
cowork_server-0.26.7.23.1rc2-py3-none-any.whl -
Subject digest:
5adf85b0ac9a3edca9407313a00f8756e4cd58967c1d704e8eb49a39a03afb79 - Sigstore transparency entry: 2229170063
- Sigstore integration time:
-
Permalink:
mindsdb/cowork-server@93a58452fc179bfa197c8d851bc67c01f214b2a6 -
Branch / Tag:
refs/heads/staging - Owner: https://github.com/mindsdb
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-staging.yml@93a58452fc179bfa197c8d851bc67c01f214b2a6 -
Trigger Event:
push
-
Statement type: