molecule-core/docs/api-protocol/websocket-events.md
Hongming Wang 24fec62d7f initial commit — Molecule AI platform
Forked clean from public hackathon repo (Starfire-AgentTeam, BSL 1.1)
with full rebrand to Molecule AI under github.com/Molecule-AI/molecule-monorepo.

Brand: Starfire → Molecule AI.
Slug: starfire / agent-molecule → molecule.
Env vars: STARFIRE_* → MOLECULE_*.
Go module: github.com/agent-molecule/platform → github.com/Molecule-AI/molecule-monorepo/platform.
Python packages: starfire_plugin → molecule_plugin, starfire_agent → molecule_agent.
DB: agentmolecule → molecule.

History truncated; see public repo for prior commits and contributor
attribution. Verified green: go test -race ./... (platform), pytest
(workspace-template 1129 + sdk 132), vitest (canvas 352), build (mcp).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 11:55:37 -07:00

7.4 KiB

WebSocket Events

The canvas subscribes to the platform's WebSocket at /ws and receives real-time structure events as JSON messages.

Message Format

Every WebSocket message has this structure:

{
  "event": "EVENT_TYPE",
  "workspace_id": "ws-abc-123",
  "timestamp": "2026-03-30T12:00:00Z",
  "payload": { ... }
}

Event Reference

WORKSPACE_PROVISIONING

Workspace is being spun up. Canvas shows a spinner on the node.

{
  "event": "WORKSPACE_PROVISIONING",
  "workspace_id": "ws-abc-123",
  "timestamp": "2026-03-30T12:00:00Z",
  "payload": {
    "name": "Vancouver SEO Agent",
    "tier": 1,
    "config": "seo-agent"
  }
}

WORKSPACE_ONLINE

First heartbeat received, or workspace returned from offline.

{
  "event": "WORKSPACE_ONLINE",
  "workspace_id": "ws-abc-123",
  "timestamp": "2026-03-30T12:00:00Z",
  "payload": {
    "url": "http://ws-abc-123:8000",
    "agent_card": {
      "name": "Vancouver SEO Agent",
      "version": "1.0.0",
      "skills": ["generate-seo-page", "audit-seo-page"],
      "capabilities": { "streaming": true }
    }
  }
}

WORKSPACE_OFFLINE

Heartbeat TTL expired. Node turns gray.

{
  "event": "WORKSPACE_OFFLINE",
  "workspace_id": "ws-abc-123",
  "timestamp": "2026-03-30T12:01:00Z",
  "payload": {}
}

WORKSPACE_PROVISION_FAILED

Provisioning timed out or errored. Node turns red with retry button.

{
  "event": "WORKSPACE_PROVISION_FAILED",
  "workspace_id": "ws-abc-123",
  "timestamp": "2026-03-30T12:03:00Z",
  "payload": {
    "reason": "provisioning timeout -- no heartbeat received"
  }
}

WORKSPACE_DEGRADED

Workspace is online but experiencing errors. Node shows warning indicator.

{
  "event": "WORKSPACE_DEGRADED",
  "workspace_id": "ws-abc-123",
  "timestamp": "2026-03-30T12:05:00Z",
  "payload": {
    "error_rate": 0.87,
    "sample_error": "anthropic API rate limit exceeded"
  }
}

WORKSPACE_REMOVED

User deleted the workspace. Node removed from canvas.

{
  "event": "WORKSPACE_REMOVED",
  "workspace_id": "ws-abc-123",
  "timestamp": "2026-03-30T12:10:00Z",
  "payload": {
    "forwarded_to": null
  }
}

AGENT_REPLACED

AI model swapped inside a workspace.

{
  "event": "AGENT_REPLACED",
  "workspace_id": "ws-abc-123",
  "timestamp": "2026-03-30T12:00:00Z",
  "payload": {
    "old_model": "anthropic:claude-sonnet-4-6",
    "new_model": "openai:gpt-4o"
  }
}

AGENT_CARD_UPDATED

Workspace republished its Agent Card (new skill added, description changed, capabilities changed). The platform broadcasts this to all peer workspaces (siblings, children, parent) so they can rebuild their system prompts.

{
  "event": "AGENT_CARD_UPDATED",
  "workspace_id": "ws-abc-123",
  "timestamp": "2026-03-30T12:00:00Z",
  "payload": {
    "agent_card": {
      "name": "Vancouver SEO Agent",
      "version": "1.1.0",
      "skills": ["generate-seo-page", "audit-seo-page", "monitor-rankings"],
      "capabilities": { "streaming": true }
    }
  }
}

WORKSPACE_EXPANDED

Workspace expanded into a team of sub-workspaces.

{
  "event": "WORKSPACE_EXPANDED",
  "workspace_id": "ws-abc-123",
  "timestamp": "2026-03-30T12:00:00Z",
  "payload": {
    "sub_workspace_ids": [
      "ws-frontend-001",
      "ws-backend-001",
      "ws-qa-001"
    ]
  }
}

WORKSPACE_COLLAPSED

Team collapsed back to a single agent. Sub-workspaces are stopped and removed.

{
  "event": "WORKSPACE_COLLAPSED",
  "workspace_id": "ws-abc-123",
  "timestamp": "2026-03-30T12:00:00Z",
  "payload": {
    "removed_sub_workspace_ids": [
      "ws-frontend-001",
      "ws-backend-001",
      "ws-qa-001"
    ]
  }
}

WORKSPACE_MOVED

Workspace moved to a new parent (dragged into a different team on canvas).

{
  "event": "WORKSPACE_MOVED",
  "workspace_id": "ws-abc-123",
  "timestamp": "2026-03-30T12:00:00Z",
  "payload": {
    "old_parent_id": "ws-team-a",
    "new_parent_id": "ws-team-b"
  }
}

AGENT_ASSIGNED

A new AI agent assigned to a workspace (first time or after removal).

{
  "event": "AGENT_ASSIGNED",
  "workspace_id": "ws-abc-123",
  "timestamp": "2026-03-30T12:00:00Z",
  "payload": {
    "agent_id": "agent-xyz-789",
    "model": "anthropic:claude-sonnet-4-6"
  }
}

AGENT_REMOVED

Agent removed from a workspace (workspace becomes empty).

{
  "event": "AGENT_REMOVED",
  "workspace_id": "ws-abc-123",
  "timestamp": "2026-03-30T12:00:00Z",
  "payload": {
    "agent_id": "agent-xyz-789",
    "reason": "user removed"
  }
}

AGENT_MOVED

Agent moved from one workspace to another.

{
  "event": "AGENT_MOVED",
  "workspace_id": "ws-abc-123",
  "timestamp": "2026-03-30T12:00:00Z",
  "payload": {
    "agent_id": "agent-xyz-789",
    "from_workspace_id": "ws-abc-123",
    "to_workspace_id": "ws-def-456"
  }
}

TASK_UPDATED

Agent's current task changed (via heartbeat). WebSocket-only — not persisted to structure_events.

{
  "event": "TASK_UPDATED",
  "workspace_id": "ws-abc-123",
  "timestamp": "2026-03-30T12:00:00Z",
  "payload": {
    "current_task": "Analyzing quarterly report",
    "active_tasks": 2
  }
}

Canvas shows the current task as an amber banner on the workspace node and side panel header. Only broadcast when the task actually changes (not on every heartbeat).

ACTIVITY_LOGGED

New activity log entry created (A2A communication, webhook-triggered task ingress, agent log, error). WebSocket-only — not persisted to structure_events (stored in activity_logs table instead).

{
  "event": "ACTIVITY_LOGGED",
  "workspace_id": "ws-abc-123",
  "timestamp": "2026-03-30T12:00:00Z",
  "payload": {
    "activity_type": "a2a_receive",
    "method": "message/send",
    "summary": "message/send → ws-abc-123",
    "status": "ok",
    "source_id": "ws-def-456",
    "target_id": "ws-abc-123",
    "duration_ms": 1500
  }
}

Canvas ActivityTab uses this event as a refresh hint. The event is informational — the full activity details (request/response bodies) are fetched via GET /workspaces/:id/activity.

Subscribers

Both canvas clients and workspace agents subscribe to the same WebSocket endpoint (/ws):

Subscriber Identifies via Receives Purpose
Canvas client No header (unrestricted) All events UI updates
Workspace agent X-Workspace-ID header Filtered — only events about reachable peers System prompt rebuilds

The platform filters server-side using CanCommunicate() — each workspace only receives events about workspaces it can talk to.

Event Flow

Structure change occurs
      |
      v
Platform writes event to structure_events (Postgres)
      |
      v
Platform publishes to Redis pub/sub (events:broadcast)
      |
      v
WebSocket handler receives from Redis
      |
      v
WebSocket pushes JSON to subscribers (filtered per workspace)
      |
      +-> Canvas clients: update Zustand state -> React Flow re-renders
      +-> Workspace agents: rebuild system prompt if peer changed