molecule-core/docs/tutorials/fly-machines-provisioner.md
devops-engineer 7a028953fa
Some checks failed
Block internal-flavored paths / Block forbidden paths (pull_request) Successful in 14s
Check merge_group trigger on required workflows / Required workflows have merge_group trigger (pull_request) Successful in 11s
CI / Detect changes (pull_request) Successful in 17s
E2E API Smoke Test / detect-changes (pull_request) Successful in 18s
E2E Staging Canvas (Playwright) / detect-changes (pull_request) Successful in 25s
Handlers Postgres Integration / detect-changes (pull_request) Successful in 21s
Harness Replays / detect-changes (pull_request) Successful in 19s
pr-guards / disable-auto-merge-on-push (pull_request) Failing after 6s
Lint curl status-code capture / Scan workflows for curl status-capture pollution (pull_request) Successful in 14s
Runtime PR-Built Compatibility / detect-changes (pull_request) Successful in 17s
Secret scan / Scan diff for credential-shaped strings (pull_request) Successful in 17s
CodeQL / Analyze (${{ matrix.language }}) (go) (pull_request) Failing after 2m2s
CodeQL / Analyze (${{ matrix.language }}) (javascript-typescript) (pull_request) Failing after 2m2s
CodeQL / Analyze (${{ matrix.language }}) (python) (pull_request) Failing after 2m2s
Ops Scripts Tests / Ops scripts (unittest) (pull_request) Successful in 1m4s
CI / Platform (Go) (pull_request) Successful in 11s
CI / Python Lint & Test (pull_request) Successful in 12s
CI / Shellcheck (E2E scripts) (pull_request) Successful in 31s
Harness Replays / Harness Replays (pull_request) Failing after 1m11s
Runtime PR-Built Compatibility / PR-built wheel + import smoke (pull_request) Successful in 3m40s
E2E API Smoke Test / E2E API Smoke Test (pull_request) Successful in 5m40s
E2E Staging Canvas (Playwright) / Canvas tabs E2E (pull_request) Successful in 6m55s
Handlers Postgres Integration / Handlers Postgres Integration (pull_request) Successful in 6m47s
CI / Canvas Deploy Reminder (pull_request) Has been skipped
CI / Canvas (Next.js) (pull_request) Failing after 10m3s
fix(post-suspension): migrate github.com/Molecule-AI refs to git.moleculesai.app (Class G #168)
The GitHub org Molecule-AI was suspended on 2026-05-06; canonical SCM
is now Gitea at https://git.moleculesai.app/molecule-ai/. Stale
github.com/Molecule-AI/... URLs return 404 and break tooling that
clones / pip-installs / curls them.

This bundles all non-Go-module URL fixes for this repo into a single PR.
Go module path references (in *.go, go.mod, go.sum) are out of scope
here -- tracked separately under Task #140.

Token-auth clone URLs also flip ${GITHUB_TOKEN} -> ${GITEA_TOKEN} since
the GitHub token does not auth against Gitea.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 13:07:25 -07:00

4.6 KiB
Raw Blame History

Provisioning Workspaces on Fly Machines (CONTAINER_BACKEND=flyio)

Molecule AI can provision agent workspaces on Fly Machines instead of local Docker containers. When CONTAINER_BACKEND=flyio is set, every POST /workspaces creates a Fly Machine and boots the workspace agent inside it — with tier-based resource limits, env-var injection, and A2A registration handled automatically. The platform manages the workspace (lifecycle, auth, routing); Fly manages the machine it runs on.

Scope note (PR #501): Workspace images must already be published to GHCR before provisioning. The delete and restart platform endpoints are not yet fully wired to the Fly provisioner — use flyctl machine stop/destroy for teardown until a follow-up PR lands.

What you'll need

  • A Molecule AI platform instance
  • A Fly.io account with a Fly app created for workspace machines
  • flyctl installed locally
  • curl + jq

Setup

# 1. Set CONTAINER_BACKEND and Fly credentials on your platform process
#    (add to your platform's .env or deployment config)
export CONTAINER_BACKEND=flyio
export FLY_API_TOKEN=<your-fly-deploy-token>      # flyctl tokens create deploy
export FLY_WORKSPACE_APP=my-molecule-workspaces   # fly app created for this purpose
export FLY_REGION=ord                             # optional, default: ord

# 2. Restart the platform so it picks up CONTAINER_BACKEND=flyio
#    (varies by your deployment — docker restart, systemd reload, etc.)

# 3. Verify the platform is using the Fly provisioner
curl -s http://localhost:8080/healthz | jq .

# 4. Create a workspace — the platform provisions it as a Fly Machine
WS=$(curl -s -X POST http://localhost:8080/workspaces \
  -H "Content-Type: application/json" \
  -d '{
    "name": "fly-worker",
    "role": "Fly-provisioned inference worker",
    "runtime": "hermes",
    "tier": 2
  }' | jq -r '.id')
echo "Workspace ID: $WS"

# 5. Watch the Fly Machine appear (~1530s)
flyctl machines list --app $FLY_WORKSPACE_APP

# 6. Poll until the workspace is ready
until curl -s http://localhost:8080/workspaces/$WS | jq -r '.status' | grep -q ready; do
  echo "Waiting..."; sleep 5
done

# 7. Smoke test — send an A2A task
curl -s -X POST http://localhost:8080/workspaces/$WS/a2a \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":"1","method":"message/send",
       "params":{"message":{"role":"user","parts":[{"kind":"text",
       "text":"What region are you running in?"}]}}}' \
  | jq '.result.parts[0].text'

# 8. Inspect the Fly Machine details
flyctl machines show --app $FLY_WORKSPACE_APP

# 9. Teardown (see scope note — use flyctl directly for now)
flyctl machines destroy --app $FLY_WORKSPACE_APP --force

Expected output

Step 5 (flyctl machines list) shows the new machine with a started state within ~30 seconds. The platform injects your workspace secrets, PLATFORM_URL, and workspace ID as environment variables on the machine, then issues an auth token so the agent registers on boot.

Step 7 returns the agent's reply — proof that A2A JSON-RPC is routing through the Fly Machine correctly. The FLY_REGION env var is visible inside the container, so asking the agent "What region are you running in?" should return ord (or whichever region you set).

Resource tiers

The Fly provisioner applies tier-based limits automatically — no manual machine sizing needed:

Tier RAM CPUs Use case
T2 512 MB 1 Light workers, eval agents
T3 2 GB 2 General-purpose orchestrators
T4 4 GB 4 Heavy inference, long-context tasks

Set "tier": 2, 3, or 4 in your POST /workspaces body. Runtime images are resolved from GHCR automatically (hermesghcr.io/molecule-ai/workspace-hermes:latest).

Why Fly Machines

Fly Machines start in milliseconds and run in 35+ regions. Provisioning agent workspaces on Fly means your inference workers can live close to your users with no infrastructure code changes — just set FLY_REGION per workspace. Because the Fly provisioner implements the same Provisioner interface as the Docker backend, the rest of the platform is unchanged: same REST API, same A2A protocol, same workspace management UI.