The design constraint is simple: the agent execution stays local, but the phone still needs a fast, reliable, public edge. Cloudflare is where that edge lives. It starts sessions, terminates public WebSockets, runs low-latency intent analysis, synthesizes spoken receipts, stores just enough indexed state to reconnect cleanly, and forwards heavier work back to the desktop listener when the request needs the actual local agent.
The mental model is not “host the agent on Cloudflare.” The mental model is “use Cloudflare as the voice and rendezvous layer in front of a local bridge.”
- 1. The phone creates or resumes a voice session through the Worker and attaches to
AmplinkSession. - 2. A voice input arrives and the Session DO acknowledges immediately.
- 3. Workers AI classifies the utterance.
- 4. The Session DO generates a short overlay reply and optionally synthesizes it with ElevenLabs.
- 5. If the request needs the local agent, the Session DO dispatches a task to the desktop listener through the Control Hub DO.
- 1. The desktop listener receives a queued task and proxies it into the local bridge.
- 2. The local bridge executes the real request against the actual desktop agent.
- 3. The desktop listener sends
task.resultback to the Control Hub DO. - 4. The Session DO summarizes the result with Workers AI and applies the saved voice profile.
- 5. The phone receives a compact
voice.resultevent containing overlay text and optional audio.
- 1. The bridge connects outbound to the relay as
role=bridge. The phone connects asrole=client. - 2. The Relay Room DO tracks active bridge and client connections to ignore stale frames.
- 3. The bridge public key to room mapping is stored in KV so the phone can resolve the latest room.
- 4. The relay only forwards bytes while Noise keeps the real session traffic opaque.
The Worker is a router, not the product
The public Worker is intentionally thin. handleWorkerFetch delegates almost immediately: voice admin routes go to the admin handler, desktop control routes go to the control handler, relay routes go to the relay handler, and only then do the basic REST endpoints like /start-session, /sessions, and /ws run.
GET /sessions
POST /start-session
GET /ws
GET /listen
GET /relay
POST /relay/resolve
GET /admin
GET /api/voice-profile
PUT /api/voice-profile
POST /api/voice-preview
Why the voice session is a Durable Object
AmplinkSession owns one voice conversation. It accepts the mobile WebSocket, keeps recent conversation history in memory, updates session status in D1, snapshots the voice profile into DO storage, and runs the voice turn pipeline end to end.
Why the control hub is separate from the session
AmplinkControlHub exists because the desktop listener is long-lived, token-scoped, and should stay stable even while voice sessions come and go. It enforces one active listener per token and forwards queued tasks and results.
The relay room exists for rendezvous, not business logic
AmplinkRelayRoom accepts one bridge and one client, tracks which connection is active, forwards frames between them, and stores the bridge-public-key to room mapping used for reconnect. It is supposed to stay operationally boring.
What lives in D1, KV, and Durable Object storage
D1 stores session rows and timestamps. AMPLINK_DESKTOPS KV stores desktop registrations and relay-room lookup. AMPLINK_VOICE_PROFILES stores voice profiles and cached TTS. Durable Object storage holds object-local operational state like active connection IDs, queued tasks, and the current session voice profile snapshot.
Where Workers AI and ElevenLabs fit
Workers AI handles the low-latency edge reasoning that belongs close to the socket: intent parsing on the way in and result summarization on the way out. ElevenLabs handles the voice layer that turns those short, purpose-built strings into spoken feedback.
What Cloudflare is not doing
Cloudflare is not where Codex, Claude Code, or your OpenAI-compatible backend runs. It is not where your repo is mounted. The actual coding session still belongs to the local bridge and adapters on your machine.
Why this architecture fits Amplink
Amplink is a viewport, not a hosted agent platform. Once you accept that, the Cloudflare side becomes a set of narrowly scoped edge primitives: routing, voice runtime, control dispatch, secure rendezvous, session indexing, and user voice preferences.
Failure and recovery model
If the phone disconnects, the Session DO can recover without disturbing the desktop listener. If the desktop listener disappears, the Control Hub can reject dispatches cleanly. If the bridge rotates to a new room, the phone can resolve it from KV by bridge identity instead of rescanning a QR code.
The one-sentence version
Amplink uses Cloudflare as a voice-aware, reconnect-friendly edge control plane in front of a local bridge, not as a place to host the agent itself.