fix(runtime): align PLATFORM_URL default to host.docker.internal across all modules
Some checks failed
ci / mirror-guard (pull_request) Failing after 2s
Secret scan / Scan diff for credential-shaped strings (pull_request) Successful in 2s

Unified the fallback default for PLATFORM_URL from `http://platform:8080`
(Docker Compose service name) to `http://host.docker.internal:8080`
across all 13 modules that declare it. This matches:
- The provisioner's default (buildContainerEnv injects PLATFORM_URL
  from cfg.PlatformURL, which defaults to host.docker.internal on the
  platform side — main.go:platformURL)
- The molecule-git-token-helper.sh script (already uses host.docker.internal)
- The MCP client (MOLECULE_URL injected by provisioner)

The provisioner always sets PLATFORM_URL in production containers, so
this is a development/Docker-only improvement: without this change,
a workspace started outside the Docker Compose network (e.g. via
`docker run` with `--network host`) would fail platform API calls
with "Connection refused" because `platform:8080` resolves nowhere.

13 modules updated: a2a_cli, a2a_client, a2a_mcp_server, adapters/base,
builtin_tools/a2a_tools, builtin_tools/approval, builtin_tools/delegation,
builtin_tools/hitl, builtin_tools/memory, consolidation, coordinator,
main, molecule_ai_status. All docstrings updated to match.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Molecule AI · infra-runtime-be 2026-05-11 03:12:37 +00:00
parent 67f71936fd
commit 62719490e8
13 changed files with 14 additions and 14 deletions

View File

@ -24,7 +24,7 @@ import httpx
from builtin_tools.validation import WorkspaceIdValidationError, get_validated_workspace_id
WORKSPACE_ID = os.environ.get("WORKSPACE_ID", "") # used for discover() headers only; URL uses validated version
PLATFORM_URL = os.environ.get("PLATFORM_URL", "http://platform:8080")
PLATFORM_URL = os.environ.get("PLATFORM_URL", "http://host.docker.internal:8080")
async def discover(target_id: str) -> dict | None:

View File

@ -16,7 +16,7 @@ from .platform_auth import auth_headers
logger = logging.getLogger(__name__)
WORKSPACE_ID = os.environ.get("WORKSPACE_ID", "")
PLATFORM_URL = os.environ.get("PLATFORM_URL", "http://platform:8080")
PLATFORM_URL = os.environ.get("PLATFORM_URL", "http://host.docker.internal:8080")
# Cache workspace ID → name mappings (populated by list_peers calls)
_peer_names: dict[str, str] = {}

View File

@ -14,7 +14,7 @@ the claude --print invocation.
Environment variables (set by the workspace container):
WORKSPACE_ID this workspace's ID
PLATFORM_URL platform API base URL (e.g. http://platform:8080)
PLATFORM_URL platform API base URL (default: http://host.docker.internal:8080)
"""
import argparse

View File

@ -229,7 +229,7 @@ class BaseAdapter(ABC):
from builtin_tools.memory import commit_memory, search_memory
from builtin_tools.sandbox import run_code
platform_url = os.environ.get("PLATFORM_URL", "http://platform:8080")
platform_url = os.environ.get("PLATFORM_URL", "http://host.docker.internal:8080")
# Load plugins from per-workspace dir first, then shared fallback
workspace_plugins_dir = os.path.join(config.config_path, "plugins")

View File

@ -11,7 +11,7 @@ import httpx
from builtin_tools.validation import WorkspaceIdValidationError, get_validated_workspace_id
PLATFORM_URL = os.environ.get("PLATFORM_URL", "http://platform:8080")
PLATFORM_URL = os.environ.get("PLATFORM_URL", "http://host.docker.internal:8080")
WORKSPACE_ID = os.environ.get("WORKSPACE_ID", "") # used only for tracing headers; URLs use validated version

View File

@ -32,7 +32,7 @@ RBAC denials emit an ``rbac / rbac.deny / denied`` event instead.
Environment variables
---------------------
PLATFORM_URL Platform base URL (default: http://platform:8080)
PLATFORM_URL Platform base URL (default: http://host.docker.internal:8080)
WORKSPACE_ID This workspace's ID (validated at startup by platform_auth)
APPROVAL_TIMEOUT Max wait in seconds (default: 300)
APPROVAL_POLL_INTERVAL Polling interval in seconds (default: 5, polling path only)
@ -55,7 +55,7 @@ from builtin_tools.validation import WorkspaceIdValidationError, get_validated_w
logger = logging.getLogger(__name__)
PLATFORM_URL = os.environ.get("PLATFORM_URL", "http://platform:8080")
PLATFORM_URL = os.environ.get("PLATFORM_URL", "http://host.docker.internal:8080")
from molecule_runtime.platform_auth import WORKSPACE_ID
APPROVAL_POLL_INTERVAL = float(os.environ.get("APPROVAL_POLL_INTERVAL", "5"))
APPROVAL_TIMEOUT = float(os.environ.get("APPROVAL_TIMEOUT", "300"))

View File

@ -30,7 +30,7 @@ from builtin_tools.telemetry import (
inject_trace_headers,
)
PLATFORM_URL = os.environ.get("PLATFORM_URL", "http://platform:8080")
PLATFORM_URL = os.environ.get("PLATFORM_URL", "http://host.docker.internal:8080")
from molecule_runtime.platform_auth import WORKSPACE_ID
DELEGATION_RETRY_ATTEMPTS = int(os.environ.get("DELEGATION_RETRY_ATTEMPTS", "3"))
DELEGATION_RETRY_DELAY = float(os.environ.get("DELEGATION_RETRY_DELAY", "5.0"))

View File

@ -177,7 +177,7 @@ async def _notify_channels(
Errors in individual channels are logged but never re-raised so that a
misconfigured Slack webhook cannot block the approval flow.
"""
platform_url = os.environ.get("PLATFORM_URL", "http://platform:8080")
platform_url = os.environ.get("PLATFORM_URL", "http://host.docker.internal:8080")
workspace_id = os.environ.get("WORKSPACE_ID", "")
for channel in cfg.channels:

View File

@ -42,7 +42,7 @@ try: # pragma: no cover - optional runtime dependency in lightweight test envs
except ImportError: # pragma: no cover
httpx = SimpleNamespace(AsyncClient=None)
PLATFORM_URL = os.environ.get("PLATFORM_URL", "http://platform:8080")
PLATFORM_URL = os.environ.get("PLATFORM_URL", "http://host.docker.internal:8080")
WORKSPACE_ID = os.environ.get("WORKSPACE_ID", "")

View File

@ -19,7 +19,7 @@ from .platform_auth import auth_headers
logger = logging.getLogger(__name__)
PLATFORM_URL = os.environ.get("PLATFORM_URL", "http://platform:8080")
PLATFORM_URL = os.environ.get("PLATFORM_URL", "http://host.docker.internal:8080")
WORKSPACE_ID = os.environ.get("WORKSPACE_ID", "")
CONSOLIDATION_INTERVAL = float(os.environ.get("CONSOLIDATION_INTERVAL", "300")) # 5 min
CONSOLIDATION_THRESHOLD = int(os.environ.get("CONSOLIDATION_THRESHOLD", "10")) # min memories before consolidating

View File

@ -23,7 +23,7 @@ from policies.routing import build_team_routing_payload
logger = logging.getLogger(__name__)
PLATFORM_URL = os.environ.get("PLATFORM_URL", "http://platform:8080")
PLATFORM_URL = os.environ.get("PLATFORM_URL", "http://host.docker.internal:8080")
WORKSPACE_ID = os.environ.get("WORKSPACE_ID", "")

View File

@ -63,7 +63,7 @@ from transcript_auth import transcript_authorized as _transcript_authorized
async def main(): # pragma: no cover
workspace_id = os.environ.get("WORKSPACE_ID", "workspace-default")
config_path = os.environ.get("WORKSPACE_CONFIG_PATH", "/configs")
platform_url = os.environ.get("PLATFORM_URL", "http://platform:8080")
platform_url = os.environ.get("PLATFORM_URL", "http://host.docker.internal:8080")
awareness_config = get_awareness_config()
# 0. Normalise LLM auth env vars based on token type.

View File

@ -25,7 +25,7 @@ import httpx
from builtin_tools.validation import WorkspaceIdValidationError, get_validated_workspace_id
WORKSPACE_ID = os.environ.get("WORKSPACE_ID", "")
PLATFORM_URL = os.environ.get("PLATFORM_URL", "http://platform:8080")
PLATFORM_URL = os.environ.get("PLATFORM_URL", "http://host.docker.internal:8080")
def set_status(task: str):