fix: make Compose mode work end-to-end on Mac#30
Merged
Conversation
start-mac.sh runs uvicorn natively, which can hire agents but can't
dispatch tasks to them — Docker Desktop on Mac blocks the host from
reaching container bridge IPs. The Phase C autonomous PR-watcher
exposed this gap: every tick was correctly identifying unreviewed PRs
and timing out on dispatch.
Three issues blocking the Compose path:
- docker-compose.yml created the openclaw-agents network itself,
conflicting with the same network the orchestrator's Docker SDK
spawns agent containers onto. Marked external: true so Compose
attaches instead of owning it.
- pyproject.toml was missing the anthropic dep; the native venv
masked this because start-mac.sh pip-installs it explicitly, but
the Docker image bombed importing chat.py.
- No script for the Compose path. Added start-mac-compose.sh
mirroring start-mac.sh's shape (preflight, agent image, network
create, frontend launch, cleanup trap) but starting the platform
via `docker compose up -d --build` instead of native uvicorn.
Trade-off vs start-mac.sh: no --reload (code changes need
`docker compose up -d --build` again). For full end-to-end testing,
the dispatch-actually-works property is worth it. start-mac.sh stays
for fast inner-loop iteration.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
michaelzwang13
commented
May 24, 2026
Owner
Author
michaelzwang13
left a comment
There was a problem hiding this comment.
LGTM! This is a well-structured fix that addresses a real Mac-specific networking issue with Docker Desktop.
Highlights:
- The
external: truechange for the Docker network is the right call to avoid ownership conflicts between Compose and the orchestrator's Docker SDK calls. - Adding the missing
anthropicdependency topyproject.tomlfixes a legitimate gap between native and containerized installs. - The new
start-mac-compose.shscript is comprehensive with good preflight checks, health polling, and cleanup handling.
Minor suggestions (non-blocking):
- Consider adding a
--waitflag todocker compose upin the future to rely on Compose's native health checking instead of the manual curl loop. - The script could benefit from a
DOCKER_DEFAULT_PLATFORM=linux/arm64export for Apple Silicon users who might have Rosetta issues with multi-arch images.
Test plan looks solid and the smoke test verification gives confidence. Code looks ready to merge.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Surfaced while smoke-testing the Phase C autonomous PR-watcher (#9 / PR #29). The watcher correctly identified unreviewed PRs every tick and timed out on dispatch — because `start-mac.sh` runs uvicorn natively, and Docker Desktop on Mac blocks the host from reaching container bridge IPs.
The documented escape hatch is Compose mode (`backend/docker compose up`), which puts the platform on the same bridge network as the agent containers. Three things were broken along that path:
Fixes
1. `backend/docker-compose.yml` — network ownership.
The compose file declared the `openclaw-agents` network without `external: true`, so Compose tried to own a network that the orchestrator's Docker SDK is also writing to (spawning agents onto it). Marking it external means Compose attaches instead of owning — won't create or destroy, no label-mismatch warnings.
2. `backend/pyproject.toml` — missing `anthropic` dep.
`backend/app/routers/chat.py` imports `anthropic`. The native venv masked this because `start-mac.sh` explicitly `pip install`s it (lines 112, 117). The Docker image installs from `pyproject.toml` only, so it crashed on startup with `ModuleNotFoundError`. Added `anthropic>=0.40.0`.
3. `start-mac-compose.sh` — new launcher for Compose mode.
Mirrors `start-mac.sh` (preflight, agent image build, network create, frontend launch, cleanup trap) but starts the platform via `docker compose up -d --build` instead of native uvicorn. Cleanup runs `docker compose down`.
When to use which script
`start-mac.sh` stays as the default for development; reach for `start-mac-compose.sh` when exercising the hire → subscribe → dispatch → review loop.
Smoke
Verified end-to-end after this PR: `./start-mac-compose.sh` brings up the stack, hire a Code Review Engineer, subscribe to a repo, wait one tick, and the agent posts a real review on a real PR via the gateway. (Smoke confirmed: PR comment was posted to `#29` by the watcher loop.)
Test plan
Out of scope
🤖 Generated with Claude Code