Engineering
Three A2A proxy reliability fixes: silent truncation, sender identity, and system-caller wedge
Three molecule-core A2A proxy fixes: larger body caps, verified canvas-user sender identity, and a system-caller source-ID wedge fix.
Three A2A proxy fixes shipped close together in molecule-core. Each one addresses a different failure mode in the delivery layer; together they represent a meaningful step toward reliable message passing at scale.
Fix 1: silent body truncation → loud 413 (core#2677)
Before: the A2A proxy capped request bodies at 1 MB and response bodies at 10 MB using io.LimitReader. When a body exceeded the cap, LimitReader returned a truncated read with no error — the proxy forwarded a silently-cut message without any indication that data was missing. The receiving workspace got a partial JSON body. This was essentially invisible at the call site.
After (PR #2686):
- A new
readBodyWithLimithelper wrapsio.LimitReaderand returns an expliciterrA2ABodyTooLargeerror when the body hits the cap. - Oversize A2A requests now return HTTP 413 with
truncated=trueandmax_bytesin the error body — the caller knows immediately and can adapt. - Oversize responses from the downstream workspace return a structured 502 with
truncated=true,max_bytes, anddelivery_confirmed— the sender knows the message was not forwarded intact. - The caps were raised substantially: request cap 1 MB → 16 MB, response cap 10 MB → 64 MB, so normal delegations and large agent replies deliver intact rather than hitting the new loud path.
The key shift: silent data loss was worse than a clear error. Agents working with large context windows, file contents, or batch outputs were silently receiving partial data. Now they get a deterministic failure they can handle.
Fix 2: canvas_user messages now carry verified sender identity (core#2691)
Before: a human typing in the Molecule AI canvas sent messages over the canvas A2A path, but those messages arrived at the workspace with no sender identity — empty peer_id, no email. Agents that needed to verify who sent a message (for permission checks, audit logs, or routing) had no reliable signal.
After (PR #2698):
A new middleware.VerifiedCPIdentity component does a short-cached lookup against the control-plane auth endpoint and injects identity fields into the A2A envelope’s params.metadata on every canvas-path request:
source: canvas_user
user_identity_status: AUTHENTICATED
user_id: <cp user id>
email: <cp email>
username: <cp email>
When identity cannot be resolved (auth call fails, session invalid), the middleware stamps user_identity_status: UNAUTHENTICATED rather than passing an empty identity through — fail-closed, not fail-open.
peer_agent messages were already enriched with peer_id via registry lookup. Social-channel adapters (Telegram, Slack, and others) already injected user_id/username through their own path. This fix closes the gap for canvas users, making all three message sources — peer agents, social channels, and direct canvas input — carry a verified sender.
Fix 3: system-caller source_id normalization removes the restart wedge (core#2680)
Before: when a workspace restarted, the platform generated a synthetic system:restart-context caller ID for the restart-context message. This string was written verbatim into activity_logs.source_id, which is a UUID column. The raw string passed schema validation at write time but broke every downstream JOIN and index lookup that keyed on source_id — the activity row became unreadable to the canvas feed filter, and the queue-fallback recovery path couldn’t find the row either. The result was a workspace that could not recover from a restart: the wedge detector fired, the workspace flipped to degraded, and it stayed there past the recovery timeout.
After (PR #2701):
The nilIfEmpty helper in the A2A proxy was extended to also return nil for any system-caller prefix (matching isSystemCaller). System-caller messages now write NULL to source_id instead of the non-UUID string. The activity row is readable by the canvas feed filter, the recovery path can find it, and the workspace exits the restart cycle cleanly.
Why these fixes matter for agent developers
All three failures were silent or confusing at the call site:
- A truncated message looked like a valid (if wrong) response.
- A canvas message with no sender identity silently failed any identity-keyed permission check (see also: why every agent mode needs a gate-raising primitive).
- A restarted workspace stuck in
degradedhad no clear signal pointing to a stale source_id.
If you’re building on Molecule AI, these fixes are in the current platform image — no SDK or config change required. The practical effect: delegations with large payloads now either succeed cleanly or fail with a clear error; canvas-user messages now carry verified identity that your agent can act on; and workspace restarts are more reliable.