Files
molecule-core/docs/guides/remote-workspaces.md
T
core-devops 73502db9f4
Lint shellcheck (arm64 pilot) / shellcheck-arm64 (pilot) (pull_request) Waiting to run
Block internal-flavored paths / Block forbidden paths (pull_request) Successful in 3s
CI / Detect changes (pull_request) Successful in 7s
CI / Python Lint & Test (pull_request) Successful in 10s
E2E API Smoke Test / detect-changes (pull_request) Successful in 10s
E2E Chat / detect-changes (pull_request) Successful in 8s
Handlers Postgres Integration / detect-changes (pull_request) Successful in 7s
E2E Staging Canvas (Playwright) / detect-changes (pull_request) Successful in 8s
Lint no tenant GITEA or GITHUB token write / Scan for repo-host token write into tenant workspace surface (pull_request) Successful in 5s
Lint forbidden tenant-env keys / Scan workspace_secrets writers for forbidden env keys (pull_request) Successful in 6s
Secret scan / Scan diff for credential-shaped strings (pull_request) Successful in 7s
qa-review / approved (pull_request) Failing after 9s
gate-check-v3 / gate-check (pull_request) Successful in 9s
sop-checklist / review-refire (pull_request) Has been skipped
sop-checklist / na-declarations (pull_request) N/A: (none)
security-review / approved (pull_request) Failing after 6s
sop-checklist / all-items-acked (pull_request) Successful in 3s
sop-tier-check / tier-check (pull_request) Successful in 4s
lint-required-no-paths / lint-required-no-paths (pull_request) Successful in 1m0s
CI / Platform (Go) (pull_request) Successful in 4s
CI / Canvas (Next.js) (pull_request) Successful in 2s
CI / Shellcheck (E2E scripts) (pull_request) Successful in 2s
E2E API Smoke Test / E2E API Smoke Test (pull_request) Successful in 2s
CI / all-required (pull_request) Successful in 1m36s
E2E Staging Canvas (Playwright) / Canvas tabs E2E (pull_request) Successful in 6s
Handlers Postgres Integration / Handlers Postgres Integration (pull_request) Successful in 5s
E2E Chat / E2E Chat (pull_request) Successful in 8s
CI / Canvas Deploy Reminder (pull_request) Has been skipped
audit-force-merge / audit (pull_request) Successful in 17s
docs: clarify multi external workspace config
2026-05-21 10:20:08 -07:00

6.7 KiB
Raw Blame History

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 or Cloudflare Tunnel.
Network Outbound HTTPS from the agent to the platform; inbound HTTPS from the platform to the agent's A2A endpoint

SDK Installation

pip install molecule-ai-sdk

Or from the repo checkout:

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

# 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.


Multi-Tenant Local MCP Bridge

For local MCP-driven agents, use the standalone runtime's molecule-mcp entrypoint. A single local bridge can serve multiple external workspaces by setting MOLECULE_WORKSPACES:

[
  {
    "id": "workspace-id-local-to-acme",
    "token": "...",
    "platform_url": "https://acme.moleculesai.app"
  },
  {
    "id": "different-workspace-id-local-to-ops",
    "token": "...",
    "platform_url": "https://ops.moleculesai.app"
  }
]

platform_url selects the tenant for registration, heartbeat, inbox polling, and outbound A2A routing. org_id is not required in this config, and the workspace IDs do not need to match across tenants.


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