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-<id>: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) <noreply@anthropic.com> |
||
|---|---|---|
| .github/workflows | ||
| molecule_runtime | ||
| tests | ||
| .gitignore | ||
| pyproject.toml | ||
| README.md | ||
molecule-ai-workspace-runtime
Shared Python runtime infrastructure for all Molecule AI agent adapters.
This package provides the core machinery that every Molecule AI workspace container needs:
- A2A server — Registers with the platform, heartbeats, serves A2A JSON-RPC
- Adapter interface —
BaseAdapter/AdapterConfig/SetupResult - Built-in tools — delegation, memory, approvals, sandbox, telemetry
- Skill loader — loads and hot-reloads skill modules from
/configs/skills/ - Plugin system — per-workspace + shared plugin discovery and install
- Config / preflight — YAML config loading with validation
Installation
pip install molecule-ai-workspace-runtime
Adapter Discovery
The runtime discovers adapters in two ways:
-
ADAPTER_MODULEenv var (standalone adapter repos):ADAPTER_MODULE=my_adapter molecule-runtimeThe module must export an
Adapterclass extendingBaseAdapter. -
Built-in subdirectory scan (monorepo local dev): Scans
molecule_runtime/adapters/subdirectories forAdapterclasses.
Writing an Adapter
from molecule_runtime.adapters.base import BaseAdapter, AdapterConfig
from a2a.server.agent_execution import AgentExecutor
class Adapter(BaseAdapter):
@staticmethod
def name() -> str:
return "my-runtime"
@staticmethod
def display_name() -> str:
return "My Runtime"
@staticmethod
def description() -> str:
return "My custom agent runtime"
async def setup(self, config: AdapterConfig) -> None:
result = await self._common_setup(config)
# Store result attributes for create_executor
async def create_executor(self, config: AdapterConfig) -> AgentExecutor:
# Return an AgentExecutor instance
...
Set ADAPTER_MODULE=my_package.adapter and run molecule-runtime.
License
BSL-1.1 — see LICENSE for details.