From 0aeabc53c49c496c6b08ea9e36873229dcc8933a Mon Sep 17 00:00:00 2001 From: "molecule-ai[bot]" <276602405+molecule-ai[bot]@users.noreply.github.com> Date: Tue, 21 Apr 2026 07:51:17 +0000 Subject: [PATCH] docs: add docs/agent-runtime/workspace-runtime.md --- .../docs/agent-runtime/workspace-runtime.md | 278 ++++++++++++++++++ 1 file changed, 278 insertions(+) create mode 100644 content/docs/agent-runtime/workspace-runtime.md diff --git a/content/docs/agent-runtime/workspace-runtime.md b/content/docs/agent-runtime/workspace-runtime.md new file mode 100644 index 0000000..72ad0da --- /dev/null +++ b/content/docs/agent-runtime/workspace-runtime.md @@ -0,0 +1,278 @@ +# Workspace Runtime + +The `workspace/` directory is Molecule AI's unified runtime image. Every provisioned workspace starts from this image, loads its own config, selects a runtime adapter, registers an Agent Card, exposes A2A, and joins the platform heartbeat/activity loop. + +## Runtime Matrix In Current `main` + +Current `main` ships six adapters: + +- `langgraph` +- `deepagents` +- `claude-code` +- `crewai` +- `autogen` +- `openclaw` + +This is the merged runtime surface today. Branch-level experiments such as NemoClaw are separate and should be treated as roadmap/WIP, not merged support. + +Adapter-specific behavior is documented in [Agent Runtime Adapters](./cli-runtime.md). + +## What The Runtime Is Responsible For + +- loading `config.yaml` +- running preflight checks before the workspace goes live +- selecting an adapter based on `runtime` +- loading local skills plus plugin-mounted shared rules/skills +- constructing an Agent Card +- serving A2A over HTTP +- registering with the platform and sending heartbeats +- reporting activity and task state +- integrating with awareness-backed memory when configured +- hot-reloading skills while the workspace is running + +## Environment Model + +Common runtime environment variables: + +```bash +WORKSPACE_ID=ws-123 +WORKSPACE_CONFIG_PATH=/configs +PLATFORM_URL=http://platform:8080 +PARENT_ID= +AWARENESS_URL=http://awareness:37800 +AWARENESS_NAMESPACE=workspace:ws-123 +LANGFUSE_HOST=http://langfuse-web:3000 +LANGFUSE_PUBLIC_KEY=... +LANGFUSE_SECRET_KEY=... +``` + +Important behavior: + +- `WORKSPACE_CONFIG_PATH` points at the mounted config directory for that workspace. +- `AWARENESS_URL` + `AWARENESS_NAMESPACE` enable workspace-scoped awareness-backed memory. +- If awareness is absent, runtime memory tools fall back to the platform memory endpoints for compatibility. + +## Startup Sequence + +At a high level, `workspace/main.py` does this: + +1. Initialize telemetry. +2. Load `config.yaml`. +3. Run preflight validation. +4. Build the heartbeat loop. +5. Resolve the adapter from `config.runtime`. +6. Let the adapter run `setup()` and build an executor. +7. Build the Agent Card from loaded skills and runtime config. +8. Register the workspace with `POST /registry/register`. +9. Start heartbeats. +10. Start the skill watcher when skills are configured. +11. Serve the A2A app through Uvicorn. + +## Core Runtime Pieces + +| File | Responsibility | +|---|---| +| `main.py` | Entry point, adapter bootstrap, Agent Card registration, heartbeat startup, initial prompt execution | +| `config.py` | Parses `config.yaml` into the runtime config dataclasses | +| `adapters/` | Adapter registry and adapter implementations | +| `claude_sdk_executor.py` | `ClaudeSDKExecutor` — Claude Code runtime via `claude-agent-sdk` (replaces subprocess) | +| `executor_helpers.py` | Shared helpers for all executors: memory, delegation, heartbeat, system prompt, error sanitization | +| `a2a_executor.py` | Shared LangGraph execution bridge and current-task reporting | +| `cli_executor.py` | `CLIAgentExecutor` — subprocess executor for Codex, Ollama, custom runtimes | +| `skills/loader.py` | Parses `SKILL.md`, loads tool modules, returns loaded skill metadata | +| `skills/watcher.py` | Hot reload path for skill changes | +| `plugins.py` | Scans mounted plugins for shared rules, prompt fragments, and extra skills | +| `tools/memory.py` | Agent memory tools | +| `tools/awareness_client.py` | Awareness-backed persistence wrapper | +| `coordinator.py` | Coordinator-only delegation path for team leads | + +## Skills, Plugins, And Hot Reload + +The runtime combines three sources of capability: + +1. **workspace-local skills** from `skills//SKILL.md` +2. **plugin-mounted rules and shared skills** from `/plugins` +3. **built-in tools** like delegation, approval, memory, sandbox, and telemetry helpers + +Hot reload matters because the runtime is designed to keep a workspace alive while its capability surface evolves: + +- edit `SKILL.md` +- add/remove skill files +- update tool modules +- modify config prompt references + +The watcher rescans the skill package, rebuilds the agent tool surface, and updates the Agent Card so peers and the canvas reflect the new capabilities. + +## Awareness And Memory Integration + +The runtime keeps the agent-facing contract stable: + +- `commit_memory(content, scope)` +- `search_memory(query, scope)` + +When awareness is configured: + +- the tools route durable facts to the workspace's own awareness namespace +- the namespace defaults to `workspace:` unless explicitly overridden + +When awareness is not configured: + +- the same tools fall back to the platform memory endpoints + +That design lets the platform improve the backend memory boundary without forcing every agent prompt or tool signature to change. + +## Coordinator Enforcement + +`coordinator.py` is not a generic “smart agent” mode. It is intentionally strict: + +- coordinators delegate +- coordinators synthesize +- coordinators do not quietly do the child work themselves + +This matters because Molecule AI wants hierarchy to remain operationally real, not cosmetic. + + +## Remote Agent Registration (External Workspaces) + +External workspaces run outside the platform's Docker infrastructure — on your laptop, a cloud VM, an on-prem server, or a CI/CD agent. They register via the platform API and send heartbeats to stay live on the canvas. + +### How it differs from Docker workspaces + +| | Docker workspace | External workspace | +|---|---|---| +| Provisioning | Platform spins up a container | You provide the machine; platform just tracks it | +| Liveness | Docker health sweep | Heartbeat TTL (90s offline threshold) | +| Registration | Automatic at container start | Manual: `POST /workspaces` + `POST /registry/register` | +| Token | Inherited from container env | Minted at registration, shown once | +| Secrets | Baked in image or env var | Pulled from platform at boot via `GET /workspaces/:id/secrets/values` | + +### Registration flow + +**1. Create the workspace:** + +```bash +curl -X POST http://localhost:8080/workspaces \ + -H "Authorization: Bearer " \ + -H "Content-Type: application/json" \ + -d '{ + "name": "my-remote-agent", + "runtime": "external", + "external": true, + "url": "https://my-agent.example.com/a2a", + "parent_id": "ws-pm-123" + }' +``` + +Returns `{ "id": "ws-xyz", "platform_url": "http://localhost:8080" }`. + +**2. Register the agent with the platform:** + +```bash +curl -X POST http://localhost:8080/registry/register \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer " \ + -d '{ + "workspace_id": "ws-xyz", + "name": "my-remote-agent", + "description": "Runs on a cloud VM in us-east-1", + "skills": ["research", "summarization"], + "url": "https://my-agent.example.com/a2a" + }' +``` + +The platform returns a 256-bit bearer token — save it, it is shown only once. + +**3. Pull secrets at boot:** + +```bash +curl http://localhost:8080/workspaces/ws-xyz/secrets/values \ + -H "Authorization: Bearer " +``` + +Returns `{ "ANTHROPIC_API_KEY": "...", "OPENAI_API_KEY": "..." }`. No credentials baked into images or env files. + +**4. Send heartbeats every 30 seconds:** + +```bash +curl -X POST http://localhost:8080/registry/heartbeat \ + -H "Authorization: Bearer " \ + -H "Content-Type: application/json" \ + -d '{ + "workspace_id": "ws-xyz", + "status": "online", + "task": "analyzing Q1 sales data", + "error_rate": 0.0 + }' +``` + +If the platform misses two consecutive heartbeats, the workspace shows offline on the canvas. + +**5. A2A with `X-Workspace-ID` header:** + +When sending A2A messages to sibling or parent workspaces, include the header so the platform can verify mutual auth: + +```bash +curl -X POST http://localhost:8080/workspaces/ws-pm-123/a2a \ + -H "Authorization: Bearer " \ + -H "X-Workspace-ID: ws-xyz" \ + -H "Content-Type: application/json" \ + -d '{"type": "status_report", "payload": {...}}' +``` + +### Behind NAT — Cloudflare Tunnel / ngrok + +If the agent machine has no public IP, use an outbound tunnel: + +```bash +# ngrok +ngrok http 8000 --url https://my-agent.ngrok.io + +# Cloudflare Tunnel +cloudflared tunnel run --token + +# Register the tunnel URL (not localhost) +curl -X POST http://localhost:8080/registry/update-card \ + -H "Authorization: Bearer " \ + -d '{"workspace_id": "ws-xyz", "url": "https://my-agent.ngrok.io/a2a"}' +``` + +The agent initiates the outbound WebSocket to the platform — no inbound ports need to be opened on the firewall. + +### Revocation and re-registration + +To revoke and re-register: + +```bash +# Delete the workspace +curl -X DELETE http://localhost:8080/workspaces/ws-xyz \ + -H "Authorization: Bearer " + +# Create fresh (new workspace_id, new token) +``` + +Re-registration with the same `workspace_id` does not issue a new token — use the token saved from first registration. + +### Related docs + +- Full step-by-step: [External Agent Registration Guide](../guides/external-agent-registration.md) +- Tutorial with CI/CD examples: [Register a Remote Agent](../tutorials/register-remote-agent.md) +- API reference: [Registry and Heartbeat](../api-protocol/registry-and-heartbeat.md) + +## A2A And Registration + +Each workspace exposes an A2A server, builds an Agent Card, and registers with the platform. The platform is used for: + +- discovery +- liveness +- event fanout +- proxying browser-initiated A2A calls + +But the long-term collaboration model remains direct workspace-to-workspace communication via A2A. + +## Related Docs + +- [Agent Runtime Adapters](./cli-runtime.md) +- [Skills](./skills.md) +- [Config Format](./config-format.md) +- [System Prompt Structure](./system-prompt-structure.md) +- [Memory Architecture](../architecture/memory.md)