From 30ebe9baf3ddf9930ebb0405d49a75ff2d0fcba5 Mon Sep 17 00:00:00 2001 From: rabbitblood Date: Fri, 24 Apr 2026 02:06:04 -0700 Subject: [PATCH] =?UTF-8?q?fix:=20mount=20JSON-RPC=20at=20root=20=E2=80=94?= =?UTF-8?q?=20platform=20POSTs=20to=20/,=20not=20/api/v1/jsonrpc/?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Baseline restart 2026-04-24: every workspace came up healthy (uvicorn listening, agent-card serving) but produced zero delegations for two maintenance cycles. Tracing revealed platform's ProxyA2A POSTs to `http://ws-:8000/` (no path suffix, see workspace-server/internal/provisioner.InternalURL) while the runtime's JSON-RPC routes were mounted at `/api/v1/jsonrpc/` under the a2a-sdk 1.x API migration. Result was silent — every inbound A2A returned 404 Not Found, the platform logged "Not Found" at INFO level, but no error bubbled up because the SDK's jsonrpc route factory doesn't respond to root when mounted at a subpath. Agents stayed warm, crons fired, but no work flowed. Fix: `create_jsonrpc_routes(handler, "/")` — matches platform expectation and the agent-card self-advertisement (which also shows root as the JSON-RPC URL). Agent-card route keeps its hard-coded `/.well-known/agent-card.json` path so there's no collision. Bumped to 0.1.12. Co-Authored-By: Claude Opus 4.7 (1M context) --- molecule_runtime/main.py | 11 +++++++++-- pyproject.toml | 2 +- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/molecule_runtime/main.py b/molecule_runtime/main.py index df4d2ec..9926240 100644 --- a/molecule_runtime/main.py +++ b/molecule_runtime/main.py @@ -217,10 +217,17 @@ async def main(): # pragma: no cover agent_card=agent_card, ) - # Build Starlette app from route factory functions (a2a-sdk 1.x API) + # Build Starlette app from route factory functions (a2a-sdk 1.x API). + # JSON-RPC mounts at root because the platform's ProxyA2A (the only + # caller in this deployment) POSTs to `http://ws-:8000/` — no + # path suffix. See workspace-server/internal/provisioner.InternalURL + # which returns the Docker-DNS form without a path. Mounting + # anywhere else produces 404 on every inbound A2A and silent fleet- + # wide productivity loss (baseline restart 2026-04-24: 0 delegations + # for 2 cycles until this was traced to `/api/v1/jsonrpc/`). routes = [] routes.extend(create_agent_card_routes(agent_card)) - routes.extend(create_jsonrpc_routes(handler, "/api/v1/jsonrpc/")) + routes.extend(create_jsonrpc_routes(handler, "/")) app = Starlette(routes=routes) # 8. Register with platform diff --git a/pyproject.toml b/pyproject.toml index e908dd3..699cfc3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta" [project] name = "molecule-ai-workspace-runtime" -version = "0.1.11" +version = "0.1.12" description = "Molecule AI workspace runtime — shared infrastructure for all agent adapters" requires-python = ">=3.11"