{"id":50940612,"url":"https://github.com/mindsdb/cowork-server","last_synced_at":"2026-06-17T14:02:09.069Z","repository":{"id":362360255,"uuid":"1238227810","full_name":"mindsdb/cowork-server","owner":"mindsdb","description":null,"archived":false,"fork":false,"pushed_at":"2026-06-11T14:39:48.000Z","size":1119,"stargazers_count":0,"open_issues_count":7,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-11T16:21:55.354Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mindsdb.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-13T23:54:05.000Z","updated_at":"2026-06-10T11:23:15.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/mindsdb/cowork-server","commit_stats":null,"previous_names":["mindsdb/cowork-server"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/mindsdb/cowork-server","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mindsdb%2Fcowork-server","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mindsdb%2Fcowork-server/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mindsdb%2Fcowork-server/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mindsdb%2Fcowork-server/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mindsdb","download_url":"https://codeload.github.com/mindsdb/cowork-server/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mindsdb%2Fcowork-server/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34451342,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-17T02:00:05.408Z","response_time":127,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-17T14:02:08.356Z","updated_at":"2026-06-17T14:02:09.057Z","avatar_url":"https://github.com/mindsdb.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Cowork Server\n\nFastAPI backend for [MindsHub Cowork](https://github.com/mindsdb/cowork). Manages projects, conversations, files, scheduling, memory, and agent orchestration with a SQLite-backed data layer.\n\nThis repo is the **Python backend**. The **frontend** (Electron shell + React SPA) lives in a separate repo: [`mindsdb/cowork`](https://github.com/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`).\n\n## Quick Start\n\nRequires Python 3.12+ and [uv](https://docs.astral.sh/uv/).\n\n```sh\n# Install and run\nuv tool install cowork-server\ncowork-server\n```\n\nThe server starts on `http://127.0.0.1:26866`. Confirm with:\n\n```sh\ncurl http://127.0.0.1:26866/api/v1/health/\n```\n\n## Development\n\n```sh\n# Run from source (auto-manages virtualenv + deps)\nuv run cowork-server\n```\n\nWhen 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`).\n\n### Dev setup helper\n\n```sh\nuv run cowork-dev-setup\n```\n\nInitializes the database and validates configuration.\n\n### Testing\n\n```sh\nuv run pytest\n```\n\nTests use an isolated in-memory database and temporary directories — no side effects on your local `~/.cowork/` data.\n\n### Logging\n\nSet `LOG_LEVEL` (default `INFO`) to control verbosity. Enable file logging with `ENABLE_FILE_LOGGING=true` (writes to `LOG_DIR`, defaults to `~/.cowork/logs/`).\n\n## Releasing\n\n1. Bump `version` in `pyproject.toml`\n2. Create a GitHub release with a matching tag (e.g. `v0.1.5`)\n3. The [`publish.yml`](.github/workflows/publish.yml) workflow builds and publishes to [PyPI](https://pypi.org/project/cowork-server/) via OIDC trusted publishing\n\nIn the packaged Electron app, a background updater checks PyPI on every launch and upgrades automatically (with rollback on failure). See [`server-updater.ts`](https://github.com/mindsdb/cowork/blob/main/src/main/server-updater.ts) in the frontend repo.\n\n## Architecture\n\n```\ncowork/\n  api/v1/endpoints/   # FastAPI route handlers\n  services/           # Business logic\n  models/             # SQLModel / DB models\n  schemas/            # Pydantic request/response schemas\n  db/                 # Database session and migrations\n  common/             # Shared utilities, settings\n  harnesses/          # Agent adapters (Anton, Hermes, etc.)\n```\n\nThe 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](docs/DESIGN.md) for the full architectural rationale.\n\n### Harness system\n\nA **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.\n\n### Streaming \u0026 scheduling\n\nAgent 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`).\n\nA 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`.\n\n## Data Layer\n\nData lives in two places: a **SQLite database** for structured records and the **filesystem** for project files and agent workspaces. Understanding both is essential.\n\n### SQLite database\n\n- **Location**: `~/.cowork/cowork.db` (override with `DATABASE_URI`)\n- **ORM**: [SQLModel](https://sqlmodel.tiangolo.com/) (SQLAlchemy + Pydantic)\n- **Migrations**: Alembic (`cowork/db/alembic/versions/`)\n\nKey tables:\n\n| Table | Purpose |\n|-------|---------|\n| `projects` | Project metadata and filesystem path |\n| `conversations` | Conversation threads, linked to a project |\n| `messages` | Individual messages with role, content (JSON), and harness tag |\n| `message_events` | Streaming event payloads for a message |\n| `files` | Metadata for uploaded files (path points to filesystem) |\n| `schedules` / `schedule_runs` | Recurring prompts and their execution history |\n| `skills` | Agent skill definitions (label, instructions, when-to-use) |\n| `settings` | Key-value user settings; sensitive values Fernet-encrypted |\n| `pins` | User-pinned items (conversations, artifacts, etc.) |\n| `channel_*` | Channel installations, bindings, sessions, and events |\n\nAll models use UUID primary keys with auto-tracked `created_at`/`modified_at` timestamps.\n\n### Filesystem storage\n\n```\n~/.cowork/\n├── cowork.db                       # SQLite database\n├── .master_key                     # Fernet encryption key for settings\n├── projects/                       # COWORK_PROJECTS_DIR\n│   ├── general/                    # Default project (always exists)\n│   └── \u003cproject-name\u003e/\n│       ├── \u003cuser \u0026 agent files\u003e    # Working directory visible to agents\n│       └── .anton/                 # Private agent workspace\n│           ├── artifacts/          # Agent-produced outputs (HTML apps, docs, etc.)\n│           │   └── \u003cslug\u003e/\n│           │       ├── metadata.json\n│           │       └── \u003cfiles\u003e\n│           ├── memory/             # Persistent agent memory by category\n│           └── context/            # Project context for agent runs\n├── files/                          # COWORK_FILES_DIR — uploaded files\n│   └── \u003cfile-id\u003e/\u003cfilename\u003e\n└── data-vault/                     # COWORK_VAULT_DIR — encrypted connector creds\n    └── \u003cengine\u003e/\u003cconnection-name\u003e/\n```\n\n### How the two layers relate\n\nThe **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.\n\nThis split is the result of an ongoing migration from a purely filesystem-based architecture (the original server stored conversations, settings, and skills as files). Structured data that benefits from querying and relationships — conversations, messages, settings, skills, schedules — has been moved into SQLite. Components that are inherently file-based — project working directories, agent artifacts, harness-managed memory, connector vault credentials — remain on the filesystem by design. See [docs/SERVER_MIGRATION.md](docs/SERVER_MIGRATION.md) for the full migration story.\n\nAgents (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.\n\n**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/`).\n\n## API\n\nAll endpoints live under `/api/v1/`. Key resource groups:\n\n| Path | Description |\n|------|-------------|\n| `/health` | Readiness probe |\n| `/projects` | Project CRUD and working-folder management |\n| `/conversations` | Conversation threads and message history |\n| `/responses` | Streaming agent responses (SSE) |\n| `/files` | OpenAI-compatible file uploads |\n| `/schedules` | Recurring task scheduling |\n| `/skills` | Agent skill definitions |\n| `/memory` | Persistent agent memory |\n| `/artifacts` | Agent-produced file previews |\n| `/publish` | Publish HTML artifacts to 4nton.ai |\n| `/connectors` | Third-party service connections and OAuth |\n| `/settings` | User preferences and API keys |\n\n## Configuration\n\nConfiguration 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/`.\n\nEnvironment variables fall into two namespaces:\n\n**Server-level** (`COWORK_*`) — control the cowork-server process itself:\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `COWORK_SERVER_PORT` | `26866` | Server port |\n| `COWORK_SERVER_HOST` | `127.0.0.1` | Bind address |\n| `COWORK_PROJECTS_DIR` | `~/.cowork/projects` | Project storage root |\n| `COWORK_FILES_DIR` | `~/.cowork/files` | Uploaded files root |\n| `COWORK_VAULT_DIR` | `~/.cowork/data-vault` | Connector credential vault |\n\n**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:\n\n| Variable | Harness | Description |\n|----------|---------|-------------|\n| `ANTON_PUBLISH_URL` | Anton | Artifact publish endpoint |\n| `ANTON_SKILLS_ROOT_DIR` | Anton | Skill file storage |\n| `ANTON_GLOBAL_MEMORY_ROOT_DIR` | Anton | Global memory files |\n| `HERMES_HOME` / `HERMES_ROOT_DIR` | Hermes | Hermes data root |\n\nIn 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.\n\n## Docs\n\n- [docs/DESIGN.md](docs/DESIGN.md) — Architectural overview and design decisions\n- [docs/MIGRATION.md](docs/MIGRATION.md) — Migration guide from the legacy server\n- [docs/MIGRATION_PROGRESS.md](docs/MIGRATION_PROGRESS.md) — Migration status tracker\n\n## License\n\nSee [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmindsdb%2Fcowork-server","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmindsdb%2Fcowork-server","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmindsdb%2Fcowork-server/lists"}