feat(cowork): add Cowork FastAPI server as packaged module#156
Conversation
Move the Cowork FastAPI server from cowork/server/ into `anton/cowork/server/`, making it launchable as: python -m anton.cowork.server This lets the desktop app receive server updates through Anton's existing release/self-update flow instead of requiring a new Electron app install for every Python change. Package structure: - anton/cowork/__init__.py — namespace package for Cowork interfaces - anton/cowork/server/__init__.py — exports COWORK_SERVER_VERSION and COWORK_SERVER_PROTOCOL_VERSION - anton/cowork/server/__main__.py — module entrypoint - anton/cowork/server/main.py — FastAPI app, /health, self-update, SPA serving, uvicorn boot - anton/cowork/server/anton_api/ — conversation manager, projects store, scratchpad runtime, cowork tools, data vault, models - anton/cowork/server/routes/ — all /v1/* API routes - anton/cowork/server/connectors/*.json — 150+ predefined connector definitions (shipped as package data) Other changes: - pyproject.toml: add `cowork-server` optional extra (fastapi, uvicorn, python-multipart), `anton-cowork-server` console script, explicit wheel packages list - anton/updater.py: accept `extras` parameter so the Cowork server can self-update with `anton[cowork-server]` instead of bare `anton` - All bare imports (from anton_api/routes) converted to relative imports (from .anton_api/from .routes) - tests/test_cowork_server_package.py: import smoke test, /health contract test, connector registry package-data test Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Cowork Server Packaging: Rationale and ApproachObjectiveGive the Python server that powers Cowork a real version and update path without creating another repository or another updater. The chosen approach is to package the Cowork FastAPI server inside the existing Current SystemCowork has three runtime pieces:
Before this migration, the server code lived in That created a split install model:
Anton already had a lightweight OTA path: check the latest GitHub release, compare it to New Startup and Update FlowAfter the migration, the server ships as part of Anton: Cowork installs Anton with the server extra: uv tool install "anton[cowork-server] @ git+https://github.com/mindsdb/anton.git" \
--force --reinstall --upgradeThe extra declares the FastAPI server dependencies in Anton's Electron then starts: python -m anton.cowork.serverOn boot, the server runs Anton's self-update check before uvicorn starts. In Cowork server context it calls os.execv(sys.executable, [sys.executable, "-m", "anton.cowork.server"])Electron waits for Version Selection and CompatibilityThere are two version decisions:
For v1, {
"anton_version": "...",
"cowork_server_version": "...",
"cowork_server_protocol_version": 1
}Electron has a required minimum protocol constant and refuses to treat the backend as ready if the reported protocol is too old. This lets server fixes ship through Anton without rebuilding Cowork, while still giving Electron a hard stop for breaking API changes. Filesystem and Data OwnershipMoving the package does not move user data:
Why the Server Belongs in AntonThe Cowork server is not an independent backend service. Its durable backend is mostly the local filesystem plus Anton's Python APIs. The FastAPI layer maps Cowork UI routes to Anton operations, constructs Anton chat sessions, invokes Anton tools, and adds Cowork-specific concepts such as pins, attachments, connector forms, artifact views, and UI-local state. Those Cowork concepts should not be promoted into The intended boundary is:
Options ConsideredOption A: Keep the server in Cowork and add a server update pipelineThis keeps source ownership simple, but requires a second executable-code updater inside Cowork: artifact hosting, version files, install logic, rollback behavior, CI, and compatibility rules. It also still has to coordinate with Anton releases because the server calls Anton internals directly. This adds operational complexity without removing the core coupling. Option B: Move the server into Anton with an optional extraThis is the chosen approach. It reuses Anton's existing GitHub-release-based updater, keeps the server versioned with the Python internals it wraps, avoids another repo/pipeline, and makes Electron a thinner shell: install Anton, spawn The tradeoffs are acceptable: CLI-only users receive inert server source files and connector JSONs on disk, server-only fixes require Anton version bumps, and maintainers must keep Cowork concepts scoped to Option C: Create a standalone server package or repositoryThis gives the cleanest artifact boundary, but creates another package/repo, another release process, another updater, and another local development surface. Because the server depends deeply on Anton internals and Electron process lifecycle, coordinated changes would become more error-prone. It optimizes for package purity over release and development reality. Option D: Move Cowork concepts into Anton coreThis maximizes reuse but pollutes Anton core with desktop UI concepts such as pins, attachment sidecars, connector form UX, artifact gallery APIs, and Cowork local state. It was rejected because the server is an interface layer, not evidence that every Cowork concept is a shared Anton abstraction. DecisionPackage the Cowork FastAPI server as This matches the dependency graph: Cowork's Python backend is a local HTTP adapter over Anton's Python runtime and the filesystem, not a separately operated service. The approach reuses Anton's release/update path, avoids another repo and updater, and lets server fixes ship without rebuilding the Electron app. The main discipline required is preserving the namespace boundary. Cowork routes, state, connector UX, and desktop-specific models stay under Risks and Mitigations
Operational Rule of Thumb
|
|
Closing for now -- may reopen once we have a clear path forward for the new cowork server repository |
Note
This PR enables OTA/hot updates for Cowork server code by moving it into anton. It is a tricky situation where cowork server code is strongly coupled to both
antonandcowork. Of the available options of a) keeping it in cowork, b) moving it to anton, and c) creating a new repo, this opts for option b. Please see the Cowork Server Packaging: Rationale and Approach comment, for further context.Description
Move the Cowork FastAPI server into the Anton package as
anton.cowork.server, launchable via:Previously, the server source lived in
cowork/server/and was bundled as raw.pyfiles inside the Electron app'sextraResources. The only way to deliver server changes to users was a full desktop app release. This migration puts the server on Anton's existing release/self-update flow so Python changes ship throughuv tool installupdates — no Electron reinstall needed.Companion PR (Cowork side): mindsdb/cowork#69
What's added
New package:
anton/cowork/server/__init__.py— exportsCOWORK_SERVER_VERSIONandCOWORK_SERVER_PROTOCOL_VERSION__main__.py— module entrypoint forpython -m anton.cowork.servermain.py— FastAPI app,/healthendpoint (with protocol version), self-update + re-exec, SPA serving, uvicorn bootanton_api/— conversation manager, projects store, scratchpad runtime, cowork tools, data vault agent/probe, models, formatterroutes/— all/v1/*API routes (artifacts, attachments, browse, connectors, conversations, cowork_state, datavault, integrations, pins, projects, responses, schedules, scratchpad, search, settings, utilities)connectors/*.json— 150+ predefined connector definitions (shipped as package data)pyproject.tomlchangescowork-server(fastapi, uvicorn, python-multipart)anton-cowork-server[tool.hatch.build.targets.wheel] packages = ["anton"]anton/updater.pychangescheck_and_update()now accepts anextrasparameteranton[cowork-server]instead of bareanton, preserving FastAPI/uvicorn deps across updatesImport migration
from anton_api ...,from routes ...) converted to relative imports (from .anton_api ...,from .routes ...)Architecture
Cowork-specific concepts (projects, pins, attachments, artifact gallery, connector forms, scheduled tasks) remain isolated in
anton.cowork.server— they are NOT promoted intoanton.core. The server is an alternate interface to Anton, parallel to the CLI.Alternatives considered
anton-cowork-serverrepo/package — rejected; increases repo sprawl, the server is too coupled to Anton internals for an independent release lineanton.core— rejected; would pollute core with desktop-specific modelsType of change
Testing / Verification
Included tests (
tests/test_cowork_server_package.py):test_cowork_server_modules_import— walks every module underanton.cowork.serverand verifies they all import cleanlytest_cowork_server_health_versions_and_protocol— calls the/healthendpoint function and asserts version + protocol fieldstest_cowork_connector_registry_loads_package_data— verifies 150+ connector JSONs load from the installed packageSteps to verify manually:
pip install -e ".[cowork-server]"(oruv pip install -e ".[cowork-server]")python -m anton.cowork.server— server should boot on127.0.0.1:26866curl http://127.0.0.1:26866/health— should returncowork_server_protocol_version: 1pytest tests/test_cowork_server_package.py -vhatch build— verify connector JSONs are included in the wheelChecklist: