Molecule AI

API Reference

Complete reference for all Molecule AI Platform HTTP and WebSocket endpoints.

API Reference

The Molecule AI Platform exposes a REST API (default port 8080) for workspace management, agent registry, communication, and administration. All endpoints return JSON unless otherwise noted.

Breaking changes — PR #701 (2026-04-17)

  • PATCH /workspaces/:id now requires authentication. Previously, requests without a bearer token could update cosmetic fields (name, x/y position). All PATCH calls now require Authorization: Bearer <workspace-token> or receive 401 Unauthorized.
  • GET /templates and GET /org/templates now require AdminAuth. Unauthenticated callers receive 401 Unauthorized.
  • All /workspaces/:id endpoints validate the :id path parameter as a UUID. Non-UUID values return 400 Bad Request before any database interaction.

Migration: add Authorization: Bearer <workspace-token> to all PATCH /workspaces/:id calls. Use an admin bearer token for GET /templates and GET /org/templates. Ensure :id values in automation scripts are valid UUIDs.

Base URL: http://localhost:8080 (self-hosted) or https://api.moleculesai.app (SaaS)


Authentication Model

The platform uses three authentication middleware variants depending on the sensitivity of the route.

AdminAuth

Strict bearer-token authentication. Required for any route where a forged request could leak prompts/memory, create/mutate workspaces, or leak operational data.

Authorization: Bearer <token>

Fail-open behavior: When no live tokens exist globally (fresh install), AdminAuth passes all requests through. Once the first token is created, all AdminAuth routes require a valid bearer.

WorkspaceAuth

Per-workspace bearer token binding. Workspace A's token cannot access workspace B's sub-routes. Used for the entire /workspaces/:id/* group (except the A2A proxy, which uses CanCommunicate).

Authorization: Bearer <workspace-token>

CanvasOrBearer

Accepts either a valid bearer token OR a request whose Origin header matches CORS_ORIGINS. Used only for cosmetic-only routes where a forged request has zero data/security impact.

Currently applies only to PUT /canvas/viewport. Do not extend to data-sensitive routes.


Health and Monitoring

MethodPathAuthDescription
GET/healthNoneReturns 200 OK if the platform is running. Use for load balancer health checks.
GET/metricsNonePrometheus text format (v0.0.4) metrics. Scrape-safe, no auth required.
GET/admin/livenessAdminAuthPer-subsystem supervised.Snapshot() ages. Check before debugging stuck scheduler/heartbeat goroutines.

Workspaces

Core workspace CRUD and lifecycle operations.

CRUD

MethodPathAuthDescription
POST/workspacesAdminAuthCreate a new workspace. Accepts name, runtime, template, parent_id, tier, workspace_dir, and other fields. Runtime is auto-detected from template config if omitted (defaults to langgraph).
GET/workspacesAdminAuthList all workspaces with status, runtime, agent card, position, and hierarchy info.
GET/workspaces/:idWorkspaceAuthGet a single workspace by ID.
PATCH/workspaces/:idWorkspaceAuthUpdate workspace fields. A workspace bearer token is always required — unauthenticated calls return 401. Validates field constraints: name ≤ 255 chars, role ≤ 1,000 chars, model and runtime ≤ 100 chars each; name and role must not contain newlines (\\n, \\r) or YAML-special characters (`[]
DELETE/workspaces/:idAdminAuthDelete a workspace. Stops the container, revokes all auth tokens, and removes all associated data.

Lifecycle

MethodPathAuthDescription
POST/workspaces/:id/restartWorkspaceAuthRestart the workspace container. Sends a restart_context A2A message after successful re-registration.
POST/workspaces/:id/pauseWorkspaceAuthStop the container and set status to paused. Paused workspaces skip health sweep, liveness monitor, and auto-restart.
POST/workspaces/:id/resumeWorkspaceAuthRe-provision a paused workspace. Status transitions to provisioning.

Registry

Workspace registration and heartbeat endpoints. Called by workspace runtimes, not by end users.

MethodPathAuthDescription
POST/registry/registerNoneRegister a workspace with the platform. Sets status to online. Body includes agent URL, agent card, capabilities.
POST/registry/heartbeatBearer (if token exists)Send a heartbeat. Updates Redis TTL key (60s expiry). Body can include active_tasks, current_task, error_rate. Triggers degraded status if error_rate > 0.5.
POST/registry/update-cardBearer (if token exists)Update the workspace's agent card (name, description, skills, etc.).

Discovery

Peer discovery and access control verification.

MethodPathAuthDescription
GET/registry/discover/:idBearer + X-Workspace-IDDiscover a workspace's agent card and URL. Requires caller identification. Fails open on DB hiccup since hierarchy check is primary.
GET/registry/:id/peersBearer + X-Workspace-IDList all peers (siblings, parent, children) that the caller can communicate with.
POST/registry/check-accessNoneCheck whether two workspaces can communicate. Body: { "caller_id": "...", "target_id": "..." }. Returns { "allowed": true/false }.

Communication

A2A Proxy

MethodPathAuthDescription
POST/workspaces/:id/a2aCanCommunicateProxy an A2A JSON-RPC message to the target workspace. Caller identified via X-Workspace-ID header. Canvas requests (no header) bypass access check. On connection error, checks if container is dead and triggers auto-restart.

Delegation

MethodPathAuthDescription
POST/workspaces/:id/delegateWorkspaceAuthAsync fire-and-forget delegation. Supports idempotency keys. Body includes target workspace, prompt, and metadata.
GET/workspaces/:id/delegationsWorkspaceAuthList delegation status for a workspace. Returns delegation rows with status, result, timestamps.

Configuration

MethodPathAuthDescription
GET/workspaces/:id/configWorkspaceAuthGet the workspace's config.yaml contents.
PATCH/workspaces/:id/configWorkspaceAuthUpdate the workspace config. "Save & Restart" writes config and auto-restarts; "Save" writes only and shows a restart banner in the Canvas.

Secrets

Per-Workspace Secrets

MethodPathAuthDescription
GET/workspaces/:id/secretsWorkspaceAuthList secret keys for a workspace (keys only, values masked).
POST/workspaces/:id/secretsWorkspaceAuthSet a secret { "key": "...", "value": "..." }. Auto-restarts the workspace.
PUT/workspaces/:id/secretsWorkspaceAuthAlias for POST (upsert semantics). Auto-restarts the workspace.
DELETE/workspaces/:id/secrets/:keyWorkspaceAuthDelete a secret by key. Auto-restarts the workspace.
GET/workspaces/:id/modelWorkspaceAuthReturn the model configuration derived from available API keys (which provider keys are set).

Global Secrets

MethodPathAuthDescription
GET/settings/secretsAdminAuthList global secrets (keys only, values masked).
PUT/settings/secretsAdminAuthSet a global secret { "key": "...", "value": "..." }. Auto-restarts every non-paused/non-removed workspace that does not shadow the key with a workspace-level override.
POST/settings/secretsAdminAuthAlias for PUT.
DELETE/settings/secrets/:keyAdminAuthDelete a global secret. Same auto-restart fan-out as PUT.

Legacy aliases GET/POST/DELETE /admin/secrets[/:key] also exist and behave identically.


Memory

Key-Value Memory

MethodPathAuthDescription
GET/workspaces/:id/memoryWorkspaceAuthList all key-value memory entries for a workspace.
POST/workspaces/:id/memoryWorkspaceAuthSet a memory entry { "key": "...", "value": "..." }.
DELETE/workspaces/:id/memory/:keyWorkspaceAuthDelete a memory entry by key.

Agent Memories (HMA-scoped)

MethodPathAuthDescription
GET/workspaces/:id/memoriesWorkspaceAuthList or search agent memories. Supports ?q= for semantic search (see below).
POST/workspaces/:id/memoriesWorkspaceAuthCreate an agent memory entry.
DELETE/workspaces/:id/memories/:idWorkspaceAuthDelete an agent memory by ID.

Semantic search (?q=)

When a platform-level embedding function is configured, passing ?q=<text> on GET /workspaces/:id/memories triggers vector similarity search instead of the default full-text / ILIKE path:

GET /workspaces/{id}/memories?q=authentication+flow&limit=10
Authorization: Bearer {token}

Matching entries are returned ordered by cosine similarity (most similar first). Each row includes an additional similarity_score field (0–1, higher is closer):

[
  {
    "id": "mem_abc123",
    "key": "auth-design",
    "value": "We use short-lived JWTs issued by the platform and refreshed via /auth/token.",
    "similarity_score": 0.91,
    "created_at": "2026-04-10T14:22:00Z"
  }
]

Graceful fallback: if no embedding function is configured, or if the embedding call fails for a given query, the platform falls back transparently to the text-search path. The similarity_score field is absent in fallback responses. You do not need to change client code to handle both modes.


Files

Workspace file management. Files are stored in the workspace's config directory.

MethodPathAuthDescription
GET/workspaces/:id/filesWorkspaceAuthList files in the workspace config directory.
GET/workspaces/:id/files/*pathWorkspaceAuthRead a specific file.
PUT/workspaces/:id/files/*pathWorkspaceAuthWrite a file. Creates parent directories as needed.
DELETE/workspaces/:id/files/*pathWorkspaceAuthDelete a file.
GET/workspaces/:id/shared-contextWorkspaceAuthGet the shared context files for a workspace (aggregated from parent hierarchy).

Activity

Activity logging and search for A2A communications, task updates, and agent logs.

MethodPathAuthDescription
GET/workspaces/:id/activityWorkspaceAuthList activity logs for a workspace. Supports ?source=canvas or ?source=agent filter, and ?type=delegation for A2A topology overlay polling.
POST/workspaces/:id/activityWorkspaceAuthLog an activity entry (used by workspace runtimes to self-report).
POST/workspaces/:id/notifyWorkspaceAuthAgent-to-user push message via WebSocket. Delivers a notification to connected Canvas clients.

Audit Ledger

Tamper-evident audit trail for workspace events. Used by the Canvas Audit Trail panel.

MethodPathAuthDescription
GET/workspaces/:id/auditWorkspaceAuthList audit entries for a workspace. Supports ?event_type=delegation|decision|gate|hitl, ?cursor=<cursor>, and ?limit=<n> (default 50).

Audit entry schema

FieldTypeDescription
idstringUnique entry ID
event_typestringdelegation, decision, gate, or hitl
actorstringWorkspace ID that generated the event
summarystringHuman-readable event description
chain_validboolfalse if the entry's hash does not match the prior chain — indicates possible tampering
created_atstring (ISO 8601)Event timestamp
cursorstring | nullOpaque pagination cursor; null when there are no more entries

Example response:

{
  "entries": [
    {
      "id": "aud_xyz789",
      "event_type": "delegation",
      "actor": "ws_abc123",
      "summary": "Delegated task 'fix CI' to Backend Engineer",
      "chain_valid": true,
      "created_at": "2026-04-17T14:05:00Z"
    }
  ],
  "cursor": "eyJpZCI6ImF1ZF94eXo3ODkifQ"
}
MethodPathAuthDescription
GET/workspaces/:id/session-searchWorkspaceAuthSearch activity logs with filters for type, date range, and text content. Returns paginated results.

Workflow Checkpoints

Step-level progress persistence for long-running Temporal workflows. Workspaces with runtime: langgraph (Temporal) automatically save a checkpoint after each of the three workflow stages (task_receive, llm_call, task_complete) and resume from the last completed stage on restart.

Automatic resume behavior (runtime: langgraph only)

When a Temporal workspace restarts mid-workflow, the runtime reads the highest-index checkpoint and sets resume_from_step accordingly. Already-completed stages are skipped — the agent picks up exactly where it left off without re-running earlier steps.

Checkpoint I/O is non-fatal: network errors are silently swallowed. A crashed or unreachable platform never prevents the agent from running.

MethodPathAuthDescription
POST/workspaces/:id/checkpointsWorkspaceAuthUpsert a step checkpoint. Body: { "workflow_id": "...", "step_name": "task_receive|llm_call|task_complete", "step_index": 0, "payload": {...} }. Uses ON CONFLICT DO UPDATE — safe to call multiple times.
GET/workspaces/:id/checkpoints/:wfidWorkspaceAuthReturn all checkpoints for a workflow, ordered by step_index DESC. Returns 404 if no checkpoints exist for the workflow.
DELETE/workspaces/:id/checkpoints/:wfidWorkspaceAuthClear all checkpoints for a workflow. Called by the runtime on clean task completion. Returns 404 if none exist.

Step names and indices:

Stepstep_indexMeaning
task_receive0Task received from A2A message
llm_call1LLM inference completed
task_complete2Task result sent back to caller

Schedules

Cron-based scheduled tasks per workspace.

MethodPathAuthDescription
GET/workspaces/:id/schedulesWorkspaceAuthList all schedules for a workspace.
POST/workspaces/:id/schedulesWorkspaceAuthCreate a schedule. Body: { "expression": "0 */6 * * *", "timezone": "UTC", "prompt": "...", "enabled": true }.
PATCH/workspaces/:id/schedules/:scheduleIdWorkspaceAuthUpdate a schedule (expression, timezone, prompt, enabled).
DELETE/workspaces/:id/schedules/:scheduleIdWorkspaceAuthDelete a schedule.
POST/workspaces/:id/schedules/:scheduleId/runWorkspaceAuthManually trigger a schedule immediately.
GET/workspaces/:id/schedules/:scheduleId/historyWorkspaceAuthList past runs for a schedule. Includes status (success, error, skipped) and error_detail.

Schedule source field: template for org/import-seeded schedules, runtime for Canvas/API-created. The last_status includes skipped when the scheduler concurrency-aware-skips a busy workspace.


Channels

Social channel integrations (Telegram, Slack, etc.) for workspace agents.

Per-Workspace Channels

MethodPathAuthDescription
GET/workspaces/:id/channelsWorkspaceAuthList channels for a workspace.
POST/workspaces/:id/channelsWorkspaceAuthCreate a channel. Body includes platform type, JSONB config, and allowlist.
PATCH/workspaces/:id/channels/:channelIdWorkspaceAuthUpdate a channel's config or allowlist.
DELETE/workspaces/:id/channels/:channelIdWorkspaceAuthDelete a channel.
POST/workspaces/:id/channels/:channelId/sendWorkspaceAuthSend an outbound message through the channel.
POST/workspaces/:id/channels/:channelId/testWorkspaceAuthTest the channel connection (send a test message).

Global Channel Endpoints

MethodPathAuthDescription
GET/channels/adaptersNoneList available social platform adapters (Telegram, Slack, etc.).
POST/channels/discoverAdminAuthAuto-detect available chats/groups for a bot token.
POST/webhooks/:typeNoneIncoming webhook endpoint for social platforms. The :type parameter identifies the platform (e.g., telegram, slack).

Plugins

Plugin registry and per-workspace plugin management.

Global Plugin Registry

MethodPathAuthDescription
GET/pluginsNoneList all plugins in the registry. Supports ?runtime= filter to show only compatible plugins.
GET/plugins/sourcesNoneList registered install-source schemes (e.g., github://, local://).

Per-Workspace Plugins

MethodPathAuthDescription
GET/workspaces/:id/pluginsWorkspaceAuthList installed plugins for a workspace.
POST/workspaces/:id/pluginsWorkspaceAuthInstall a plugin. Body: { "source": "github://org/repo" }. Safeguards: 64 KiB body limit, 5 min fetch timeout, 100 MiB max staged-tree.
DELETE/workspaces/:id/plugins/:nameWorkspaceAuthUninstall a plugin by name.
GET/workspaces/:id/plugins/availableWorkspaceAuthList plugins available for this workspace (filtered by workspace runtime).
GET/workspaces/:id/plugins/compatibilityWorkspaceAuthPreflight runtime-change check. Query: ?runtime=X. Returns which currently-installed plugins would be incompatible with the target runtime.

Auth Tokens

Bearer token management for workspaces.

MethodPathAuthDescription
GET/workspaces/:id/tokensWorkspaceAuthList active tokens for a workspace (token values are masked).
POST/workspaces/:id/tokensWorkspaceAuthCreate a new bearer token for the workspace.
DELETE/workspaces/:id/tokens/:tokenIdWorkspaceAuthRevoke a specific token.

Test Token (Development Only)

MethodPathAuthDescription
GET/admin/workspaces/:id/test-tokenNoneMint a fresh bearer token for E2E scripts. Returns 404 unless MOLECULE_ENV != production or MOLECULE_ENABLE_TEST_TOKENS=1.

Teams

Expand and collapse team views in the Canvas hierarchy.

MethodPathAuthDescription
POST/workspaces/:id/expandWorkspaceAuthExpand a team workspace to show its children on the canvas.
POST/workspaces/:id/collapseWorkspaceAuthCollapse a team workspace to hide its children.

Templates and Bundles

Templates

MethodPathAuthDescription
GET/templatesAdminAuthList available workspace templates with their runtime, description, and config schema.
POST/templates/importAdminAuthImport a workspace template from a github:// source URL.

Org Templates

MethodPathAuthDescription
GET/org/templatesAdminAuthList available organization templates.
POST/org/importAdminAuthImport an org template. Applies resolveInsideRoot path sanitization. Creates the full workspace hierarchy defined in org.yaml.

Bundles

MethodPathAuthDescription
GET/bundles/export/:idAdminAuthExport a workspace (or workspace tree) as a portable bundle. Includes config, secrets (keys only), memory, schedules, and hierarchy.
POST/bundles/importAdminAuthImport a previously-exported bundle. Recreates the workspace tree with all associated data.

Approvals

Human-in-the-loop approval system for agent actions.

MethodPathAuthDescription
POST/workspaces/:id/approvalsWorkspaceAuthCreate an approval request. Body includes the action description, metadata, and options.
GET/workspaces/:id/approvalsWorkspaceAuthList approval requests for a workspace.
POST/workspaces/:id/approvals/:id/decideWorkspaceAuthApprove or reject an approval request. Body: { "decision": "approve" } or { "decision": "reject" }.
GET/approvals/pendingAdminAuthList all pending approval requests across all workspaces.

Canvas

Canvas viewport persistence (cosmetic only).

MethodPathAuthDescription
GET/canvas/viewportNoneGet the saved canvas viewport (zoom, pan position). Open endpoint for bootstrap-friendliness.
PUT/canvas/viewportCanvasOrBearerSave the canvas viewport. Accepts bearer OR matching Origin header. Worst case on forgery: viewport corruption, recovered by page refresh.

Traces

LLM trace retrieval from Langfuse.

MethodPathAuthDescription
GET/workspaces/:id/tracesWorkspaceAuthList LLM traces for a workspace from Langfuse.

Audit Ledger

HMAC-SHA256-chained immutable agent event log for compliance record-keeping (EU AI Act Art. 12 / Art. 13). Each event is cryptographically chained to the previous one — tampering with any record breaks all subsequent HMACs.

AUDIT_LEDGER_SALT required. The platform and workspace containers must share the same AUDIT_LEDGER_SALT environment variable to compute and verify event HMACs. Set it in both your platform env and workspace container env. If the variable is absent, chain_valid returns null (not false) — no records are lost, verification is simply unavailable.

Query

MethodPathAuthDescription
GET/workspaces/:id/auditWorkspaceAuthQuery the audit ledger for a workspace. Returns events in descending chronological order with inline chain verification.

Query parameters:

ParameterTypeDescription
agent_idstringFilter to a specific agent.
session_idstringFilter to a specific session.
fromRFC 3339Start of time range (e.g. 2026-04-01T00:00:00Z).
toRFC 3339End of time range.
limitintMax records to return. Capped at 500.
offsetintPagination offset.

Response shape:

{
  "events": [
    {
      "id": "uuid",
      "workspace_id": "uuid",
      "agent_id": "my-researcher",
      "session_id": "sess_abc123",
      "event_type": "tool_call",
      "payload": { "tool": "bash", "input": "ls /workspace" },
      "hmac": "sha256hex...",
      "prev_hmac": "sha256hex...",
      "created_at": "2026-04-17T12:00:00Z"
    }
  ],
  "chain_valid": true
}

chain_valid values:

  • true — all HMACs verified; ledger is intact.
  • false — at least one HMAC mismatch; possible tampering.
  • nullAUDIT_LEDGER_SALT is absent from the platform env; verification skipped.

Workspace-side: recording events

In your workspace template, wire LedgerHooks into the agent pipeline:

from molecule_audit.hooks import LedgerHooks

hooks = LedgerHooks(agent_id="my-researcher", session_id=session_id)

async with hooks:
    # hooks.on_task_start / on_llm_call / on_tool_call / on_task_end
    # fire automatically at each pipeline stage
    result = await agent.run(task)

LedgerHooks is exception-safe — a failed ledger write never aborts the agent task.

CLI chain verification

# Verify the full chain for an agent; exit 0 = intact
python -m molecule_audit.verify --agent-id my-researcher

# Custom DB URL
python -m molecule_audit.verify --agent-id my-researcher --db postgresql://user:pass@host/db

Exit codes: 0 = chain valid · 1 = broken chain · 2 = AUDIT_LEDGER_SALT missing · 3 = DB error.


Events

Append-only event log for structure changes.

MethodPathAuthDescription
GET/eventsAdminAuthList all structure events across all workspaces.
GET/events/:workspaceIdAdminAuthList structure events for a specific workspace.

Terminal

WebSocket-based terminal access to workspace containers.

MethodPathAuthDescription
WS/workspaces/:id/terminalWorkspaceAuthOpen a WebSocket terminal session to the workspace container. Provides interactive shell access.

WebSocket

Real-time event streaming for Canvas clients.

MethodPathAuthDescription
WS/wsNoneConnect to the WebSocket hub. Receives all structure events (WORKSPACE_ONLINE, WORKSPACE_OFFLINE, HEARTBEAT, CONFIG_UPDATED, A2A_RESPONSE, AGENT_MESSAGE, etc.). Canvas clients connect here for real-time updates.

Server-Sent Events (AG-UI)

Per-workspace SSE stream compatible with the AG-UI protocol. Use this endpoint to consume structured agent events from a web client or external tool without a WebSocket library.

MethodPathAuthDescription
GET/workspaces/:id/events/streamWorkspaceAuthOpen an SSE stream for the workspace. Returns Content-Type: text/event-stream. Sends an initial : ping comment on connect, then delivers every event emitted by the workspace in AG-UI envelope format. Events from other workspaces are filtered out. Returns 404 if the workspace does not exist.

Event envelope format

Each event is delivered as an SSE data: line containing a JSON object:

{
  "type": "AGENT_MESSAGE",
  "timestamp": 1713398400000,
  "data": { ... }
}
  • type — event type string (e.g. AGENT_MESSAGE, A2A_RESPONSE, TASK_UPDATED)
  • timestamp — Unix milliseconds at time of broadcast
  • data — event-specific payload (same payload as the WebSocket hub delivers)

Event types streamed

All event types emitted by RecordAndBroadcast and BroadcastOnly reach the SSE stream. The BroadcastOnly path is important: events like AGENT_MESSAGE, A2A_RESPONSE, and TASK_UPDATED skip Redis and would be invisible to a Redis-only subscriber — the in-process SSE layer catches them.

Example: connect with curl

curl -N \
  -H "Authorization: Bearer <workspace-token>" \
  http://localhost:8080/workspaces/<id>/events/stream
: ping

data: {"type":"AGENT_MESSAGE","timestamp":1713398401234,"data":{"text":"Starting task..."}}

data: {"type":"TASK_UPDATED","timestamp":1713398405678,"data":{"status":"running"}}

Example: connect from JavaScript

const es = new EventSource(
  `/workspaces/${workspaceId}/events/stream`,
  { headers: { Authorization: `Bearer ${token}` } }
);

es.onmessage = (e) => {
  const event = JSON.parse(e.data);
  console.log(event.type, event.data);
};

The SSE endpoint uses WorkspaceAuth — the bearer token must be bound to the :id in the path. A token for workspace A cannot open a stream for workspace B.


Error Responses

All endpoints return standard HTTP status codes:

StatusMeaning
200Success
201Created
400Bad request (malformed body, missing required fields)
401Unauthorized (missing or invalid bearer token)
403Forbidden (valid token but insufficient access)
404Not found (workspace, schedule, channel, etc. does not exist)
409Conflict (idempotency key collision on delegation)
429Rate limited (exceeds RATE_LIMIT requests/min)
500Internal server error

Error response body format:

{
  "error": "human-readable error message"
}

Rate Limiting

All endpoints are subject to a global rate limit of RATE_LIMIT requests per minute (default: 600). When exceeded, the platform returns 429 Too Many Requests with a Retry-After header.


CORS

The platform sets CORS headers based on the CORS_ORIGINS environment variable (comma-separated list, default: http://localhost:3000,http://localhost:3001). Preflight (OPTIONS) requests are handled automatically by the Gin CORS middleware.

On this page