molecule-core/docs/guides/remote-workspaces.md
documentation-specialist 26afbbfdf4
Some checks failed
Block internal-flavored paths / Block forbidden paths (pull_request) Successful in 5s
CI / Detect changes (pull_request) Successful in 5s
E2E API Smoke Test / detect-changes (pull_request) Successful in 6s
E2E Staging Canvas (Playwright) / detect-changes (pull_request) Successful in 6s
Handlers Postgres Integration / detect-changes (pull_request) Successful in 6s
Runtime PR-Built Compatibility / detect-changes (pull_request) Successful in 5s
Secret scan / Scan diff for credential-shaped strings (pull_request) Successful in 5s
CI / Platform (Go) (pull_request) Successful in 3s
CI / Canvas (Next.js) (pull_request) Successful in 5s
CI / Python Lint & Test (pull_request) Successful in 3s
E2E API Smoke Test / E2E API Smoke Test (pull_request) Successful in 4s
CI / Shellcheck (E2E scripts) (pull_request) Successful in 8s
CI / Canvas Deploy Reminder (pull_request) Has been skipped
E2E Staging Canvas (Playwright) / Canvas tabs E2E (pull_request) Successful in 4s
Handlers Postgres Integration / Handlers Postgres Integration (pull_request) Successful in 4s
Runtime PR-Built Compatibility / PR-built wheel + import smoke (pull_request) Successful in 3s
Ops Scripts Tests / Ops scripts (unittest) (pull_request) Failing after 12s
CodeQL / Analyze (${{ matrix.language }}) (go) (pull_request) Failing after 51s
CodeQL / Analyze (${{ matrix.language }}) (javascript-typescript) (pull_request) Failing after 1m20s
CodeQL / Analyze (${{ matrix.language }}) (python) (pull_request) Failing after 1m20s
docs(internal): bulk-sed molecule-core .md docs → Gitea (#37 final molecule-core sweep)
Mass-sed across 17 files / 38 active refs in molecule-core .md docs
(README + CONTRIBUTING + docs/architecture/ + docs/blog/ + docs/guides/
+ docs/integrations/ + docs/quickstart.md + scripts/README.md).

Driver: /tmp/sweep_core.py — same pattern set as the
internal-marketing bulk-sed (PR #50). 4 url-substitution patterns +
SKIP_PATTERN preserves /pull/<n> /issues/<n> /commit/<sha>
/releases/... historical refs.

Files NOT touched in this PR:
- docs/workspace-runtime-package.md — owned by molecule-core#15
  (workspace-runtime source-edit per #41). Reverted my bulk-sed of
  that file to avoid merge conflict.
- 2 Go-import-path refs in docs/memory-plugins/testing-your-plugin.md
  (github.com/Molecule-AI/molecule-monorepo/platform/internal/...) —
  Q5 cross-repo Go-module migration territory.
- 1 GitHub Gist link in docs/guides/external-workspace-quickstart.md
  (gist.github.com/molecule-ai/...) — no Gitea equivalent;
  consistent with the same handling in docs#1.

Manual fixes (2):
- docs/blog/2026-04-20-chrome-devtools-mcp-seo/index.md:306 —
  GitHub Discussions (no Gitea equivalent) → issue tracker link
- docs/guides/external-workspace-quickstart.md:218 — tracking-issue
  ?q= query-string url (regex didn't catch) → reformulated text +
  Gitea search-by-query approach

Pattern matches my docs#1 (public docs site) PR + internal#50
(internal/marketing bulk-sed). Standard substitutions:
- https://github.com/Molecule-AI/<repo> → https://git.moleculesai.app/molecule-ai/<repo>
- /blob/<branch>/ + /tree/<branch>/ → /src/branch/<branch>/

Refs: molecule-ai/internal#37, molecule-ai/internal#38
2026-05-07 01:27:50 -07:00

148 lines
6.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Remote Workspaces — Run Agents Anywhere, Govern From One Platform
> Phase 30: agents running outside the platform's Docker network can now join
> your Molecule AI org, appear on the canvas, receive A2A tasks from parent
> agents, and report status — all with the same auth, lifecycle, and
> observability as containerized workspaces.
**Phase 30 GA:** 2026-04-20 | PRs: #1075#1083, #1085#1100 (monorepo)
---
## What Problem This Solves
Most agent platforms assume all agents run in the same environment as the
control plane. Molecule AI supported external agents as a development escape
hatch, but the production story was "all agents on this Docker network."
Phase 30 changes that. Your org can now include agents running on:
- A developer's laptop across the internet
- A server in a different cloud region
- An on-premises machine behind a NAT
- A third-party SaaS bot with an HTTP endpoint
From the canvas and from other agents, they're indistinguishable from
containerized workspaces. They have the same auth contract, the same A2A
interface, the same lifecycle controls. Where they run is a deployment
detail — not an architectural constraint.
---
## Prerequisites
| Requirement | Details |
|---|---|
| **Platform** | Molecule AI platform running v0.30+ (`go run ./cmd/server` from `workspace-server/` or the current `main` image) |
| **Admin access** | An `ADMIN_TOKEN`, org API key, or session cookie with permission to create workspaces |
| **Python ≥ 3.11** | For the `molecule-sdk-python` client (`pip install molecule-ai-sdk`) |
| **Publicly reachable endpoint** | The agent's host must be reachable from the platform over HTTPS. If behind NAT, use [ngrok](https://ngrok.com) or [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/). |
| **Network** | Outbound HTTPS from the agent to the platform; inbound HTTPS from the platform to the agent's A2A endpoint |
### SDK Installation
```bash
pip install molecule-ai-sdk
```
Or from the repo checkout:
```bash
pip install -e sdk/python/
```
The SDK includes `RemoteAgentClient` — a dependency-light Python client (only `requests`) that wraps all Phase 30 endpoints.
---
## Architecture at a Glance
```
Laptop (remote agent) Molecule AI Platform
│ │
│ POST /workspaces │
│ POST /registry/register ────────────► │ ← admin token (one-time)
│ ←─ auth_token (256-bit) ◄────────── │ ← shown once, saved to disk
│ │
│ GET /workspaces/:id/secrets/values │ ← bearer: auth_token
│ POST /registry/heartbeat (30s loop) │
│ GET /workspaces/:id/state (30s loop)│
│ │
│ ◄── A2A task dispatch ────────────── │ ← platform → laptop (HTTPS)
│ ──► A2A response ──────────────────► │ ← laptop → platform
│ │
Canvas (any browser) ◄── WebSocket ─────► Platform
│ fanout
└─── sees: researcher [ONLINE] [REMOTE] badge
```
**Key properties:**
- The agent **pulls** its secrets at boot (not baked into the container at provision time)
- Liveness is maintained by **heartbeat + state polling** (no WebSocket required from the agent side)
- The platform **proxies A2A calls** to the agent's registered URL — no inbound firewall rules on the platform
- The auth token is **workspace-scoped**: a leaked token can't impersonate another workspace
---
## Quick Start
```bash
# 1. Create the workspace (admin side)
WORKSPACE=$(curl -s -X POST https://acme.moleculesai.app/workspaces \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"researcher","runtime":"external","tier":2}')
WORKSPACE_ID=$(echo $WORKSPACE | jq -r '.id')
# 2. Run the agent (any machine that can reach the platform)
pip install molecule-ai-sdk
python3 - <<'EOF'
from molecule_agent import RemoteAgentClient
import os, logging
client = RemoteAgentClient(
workspace_id = os.environ["WORKSPACE_ID"],
platform_url = os.environ["PLATFORM_URL"],
agent_card = {"name": "researcher", "skills": ["web-search", "research"]},
)
client.register() # Phase 30.1 — get + cache token
secrets = client.pull_secrets() # Phase 30.2 — decrypt API keys
print("Secrets:", list(secrets.keys()))
# Keep alive + respond to platform commands
client.run_heartbeat_loop(
task_supplier = lambda: {
"current_task": "idle",
"active_tasks": 0,
}
)
EOF
```
The agent appears on the canvas with a **purple REMOTE badge** within seconds. From there it behaves identically to any other workspace: receive A2A tasks, update its agent card, report status.
---
## What Phase 30 Covers
| Phase | What shipped | Endpoint |
|---|---|---|
| 30.1 | Workspace auth tokens | `POST /registry/register`, `POST /registry/heartbeat` |
| 30.2 | Token-gated secrets pull | `GET /workspaces/:id/secrets/values` |
| 30.3 | Plugin tarball download (remote install) | `GET /plugins/:name/download` |
| 30.4 | Workspace state polling (no WebSocket needed) | `GET /workspaces/:id/state` |
| 30.5 | A2A proxy enforces caller token | `POST /workspaces/:id/a2a` |
| 30.6 | Sibling discovery + URL caching | `GET /registry/:id/peers` |
| 30.7 | Poll-liveness for external runtime | Redis TTL (90s timeout) |
| 30.8 | Remote-agent SDK + docs | `molecule-sdk-python` |
---
## Next Steps
- **[External Agent Registration Guide →](/docs/guides/external-agent-registration)** — full endpoint reference, Python + Node.js examples, troubleshooting
- **[molecule-sdk-python →](https://git.moleculesai.app/molecule-ai/molecule-sdk-python)** — SDK source, `RemoteAgentClient` API docs
- **[SDK Examples →](https://git.moleculesai.app/molecule-ai/molecule-sdk-python/src/branch/main/examples/remote-agent)** — `run.py` demo script, annotated walkthrough