Platform now wraps peer A2A responses in [A2A_RESULT_FROM_PEER]...
[/A2A_RESULT_FROM_PEER] markers (OFFSEC-003) to mark them as untrusted
third-party content. This change adds:
- strip_a2a_boundary(text): strips the wrapper and returns the interior
content. Safe on pre-OFFSEC-003 responses (returns input unchanged when
markers absent or malformed) and on None/empty.
Exported from molecule_agent/__init__.py and added to __all__.
README updated with a dedicated OFFSEC-003 section and call_peer() table
note pointing to strip_a2a_boundary().
8 new tests: basic, whitespace edges, no-markers passthrough, only-start,
only-end, empty/None, end-before-start edge case, multiline content.
305 total tests pass.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds optional org_id and origin constructor kwargs that inject
X-Molecule-Org-Id and Origin headers on every request, enabling
SDK use against multi-tenant SaaS deployments (*.moleculesai.app)
without needing a pre-configured requests.Session.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Exposes the two platform-supported filter parameters on
RemoteAgentClient.fetch_inbound():
- peer_id: narrow inbound events to a specific peer workspace UUID
- before_ts: RFC3339 cutoff timestamp for historical backlog replay
Also marks the corresponding README limitation as resolved (was documented as
"does not expose peer_id or before_ts filters" — both are now wired up).
New tests:
- test_fetch_inbound_peer_id_filter
- test_fetch_inbound_before_ts_filter
- test_fetch_inbound_combined_filters
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds the docs gaps that were left when several CP changes landed without
SDK-side coverage:
- "What this is / what this isn't" callout — distinguishes molecule_agent
(outside-workspace client SDK) from molecule-ai-workspace-runtime
(in-workspace runtime), with strong forward-pointer to the runtime docs
- Channel envelope (wire format) — including the three enrichment fields
added 2026-05-02 (peer_name, peer_role, agent_card_url)
- A2A reply transport table — explicit /notify vs /a2a routing per source
- Limitations & roadmap — names the SDK gaps so follow-up issues/PRs
are trivial to file:
* fetch_inbound() missing peer_id + before_ts filters (CP PRs #2472, #2476)
* InboundMessage missing typed peer_name/peer_role/agent_card_url
* RemoteAgentClient does not auto-inject X-Molecule-Org-Id + Origin
(with a session-based workaround)
Docs-only — no Python code touched. Code work for the named gaps is
deferred to follow-up PRs so reviewers can land docs first.
External agents that can't expose a public HTTP endpoint (laptops behind
NAT, ephemeral CI runners, hermes self-hosted, codex et al) had to reverse-
engineer the activity-poll loop from molecule-mcp-claude-channel/server.ts
because the SDK only shipped the push-mode `A2AServer` (Phase 30.8b).
This adds the complementary path:
- `RemoteAgentClient.fetch_inbound(since_id=…)` — one-shot GET against
`/workspaces/:id/activity?type=a2a_receive&since_id=…`. Cursor-loss (410)
surfaces as `CursorLostError`; caller resets and re-polls.
- `RemoteAgentClient.reply(msg, text)` — smart-routes to `/notify` for
canvas users, `/a2a` (JSON-RPC envelope + X-Source-Workspace-Id) for peer
agents. Hides the reply-path bifurcation from connector authors.
- `PollDelivery` / `PushDelivery` / `InboundDelivery` protocol — same
`MessageHandler` callback works for both transports.
- `RemoteAgentClient.run_agent_loop(handler, delivery=None)` — combined
heartbeat + state-poll + inbound dispatch. Defaults to `PollDelivery`.
Async handlers detected and `asyncio.run`'d (matches A2AServer pattern).
Sleep cadence = min(heartbeat_interval, delivery.interval).
- `python -m molecule_agent connect` CLI — one-line bootstrap. Loads a
user's `module:function` via importlib, registers, runs the loop until
pause/delete or SIGTERM. All flags also read from environment variables.
Tests: 50 new (test_inbound.py, test_cli_connect.py) covering every prod
branch — source normalization, cursor advancement, 410 reset, async/sync
handler dispatch, handler exception → log+continue+advance, smart-reply
routing for canvas vs peer vs unknown sources, run_agent_loop terminal
states, sleep-interval selection, CLI handler resolution failures.
Resolves#17.