Merge pull request 'docs(remote-workspaces): SDK Python new params + OFFSEC-003 strip_a2a_boundary()' (#13) from docs/sdk-python-new-remoteagent-params-from-sdk-5-6-7 into main
This commit is contained in:
commit
f98e8fa8fa
@ -90,6 +90,10 @@ Entries are published daily at 23:50 UTC.
|
||||
- **Static `.github-token` fallback to git credential helper**: workspace-server now falls back to a static `.github-token` value when no git credential helper is configured, enabling simpler air-gapped setups. (`molecule-core` [#219](https://git.moleculesai.app/molecule-ai/molecule-core/pull/219))
|
||||
- **Keyboard shortcuts in Toolbar help dialog**: all keyboard shortcuts are now documented in a Toolbar help dialog accessible from the canvas top bar. (`molecule-core` [#244](https://git.moleculesai.app/molecule-ai/molecule-core/pull/244))
|
||||
- **HTTP/SSE transport for Hermes MCP**: `a2a_mcp_server.py` now exposes `--transport=http --port=<N>` for Hermes workspaces that prefer HTTP + SSE over stdio. Endpoints: `POST /mcp` (JSON-RPC), `GET /mcp/stream` (SSE), `GET /health`. (`molecule-ai-workspace-runtime` [#5](https://git.moleculesai.app/molecule-ai/molecule-ai-workspace-runtime/pull/5))
|
||||
- **RemoteAgentClient `org_id` and `origin` kwargs**: `RemoteAgentClient` now accepts `org_id` (injected as `X-Molecule-Org-Id` header) and `origin` (injected as `Origin` header for request tracing) as constructor kwargs. Both propagate to all 14+ outbound call sites automatically via `_auth_headers()`. (`molecule-sdk-python` [#7](https://git.moleculesai.app/molecule-ai/molecule-sdk-python/pull/7))
|
||||
- **RemoteAgentClient `fetch_inbound()` filter params**: `fetch_inbound()` now accepts `peer_id` (narrow to a specific peer's messages) and `before_ts` (RFC3339 timestamp for cursor-based pagination). Enables agents to selectively consume inbound activity from known siblings. (`molecule-sdk-python` [#6](https://git.moleculesai.app/molecule-ai/molecule-sdk-python/pull/6))
|
||||
- **InboundMessage enrichment fields**: `InboundMessage` now exposes typed `peer_name`, `peer_role`, and `agent_card_url` attributes, surfaced from the platform's peer registry at dispatch time. Previously these were only accessible via the raw channel envelope. (`molecule-sdk-python` [#5](https://git.moleculesai.app/molecule-ai/molecule-sdk-python/pull/5))
|
||||
- **`strip_a2a_boundary()` — OFFSEC-003 trust-boundary SDK helper**: `molecule-sdk-python` now exports `strip_a2a_boundary(text)` to strip `[A2A_RESULT_FROM_PEER]...[/A2A_RESULT_FROM_PEER]` wrappers from peer-generated content. The platform wraps all external-peer responses in these markers so agents know not to re-inject the content as platform-native output. Safe on pre-OFFSEC-003 responses (returns input unchanged when markers absent) and on `None`/empty strings. (`molecule-sdk-python` [#8](https://git.moleculesai.app/molecule-ai/molecule-sdk-python/pull/8))
|
||||
|
||||
### 🔧 Fixes
|
||||
|
||||
|
||||
@ -110,7 +110,9 @@ import os, logging
|
||||
client = RemoteAgentClient(
|
||||
workspace_id = os.environ["WORKSPACE_ID"],
|
||||
platform_url = os.environ["PLATFORM_URL"],
|
||||
agent_card = {"name": "researcher", "skills": ["web-search", "research"]},
|
||||
org_id = os.environ["ORG_ID"], # optional — injected as X-Molecule-Org-Id header
|
||||
origin = "my-agent/1.0", # optional — injected as Origin header for tracing
|
||||
agent_card = {"name": "researcher", "skills": ["web-search", "research"]},
|
||||
)
|
||||
client.register() # Phase 30.1 — get + cache token
|
||||
secrets = client.pull_secrets() # Phase 30.2 — decrypt API keys
|
||||
@ -130,6 +132,84 @@ The agent appears on the canvas with a **purple REMOTE badge** within seconds. F
|
||||
|
||||
---
|
||||
|
||||
## RemoteAgentClient API Reference
|
||||
|
||||
### Constructor
|
||||
|
||||
```python
|
||||
from molecule_agent import RemoteAgentClient
|
||||
|
||||
client = RemoteAgentClient(
|
||||
workspace_id = "ws-...", # required — your workspace UUID
|
||||
platform_url = "https://...", # required — your platform base URL
|
||||
auth_token = "...", # optional — set to skip the register() step if you already have a token
|
||||
org_id = "org-...", # optional — injected as X-Molecule-Org-Id on every request
|
||||
origin = "my-agent/1.0", # optional — injected as Origin header for request tracing
|
||||
agent_card = {...}, # optional — updated on every heartbeat
|
||||
)
|
||||
```
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|---|---|---|
|
||||
| `workspace_id` | `str` | Your workspace UUID, obtained from `POST /workspaces`. |
|
||||
| `platform_url` | `str` | Your platform base URL, e.g. `https://acme.moleculesai.app`. |
|
||||
| `auth_token` | `str` | Pre-obtained bearer token. If omitted, call `register()` to fetch one. |
|
||||
| `org_id` | `str` | Optional org UUID. When set, injected as `X-Molecule-Org-Id` on every outbound request. |
|
||||
| `origin` | `str` | Optional UA string (e.g. `"researcher/2.1"`). Injected as `Origin` header for logging/tracing. |
|
||||
| `agent_card` | `dict` | Agent metadata broadcast to the canvas. Updated on every heartbeat. |
|
||||
|
||||
### fetch_inbound(peer_id=, before_ts=)
|
||||
|
||||
Poll for inbound A2A messages directed at this workspace:
|
||||
|
||||
```python
|
||||
messages = client.fetch_inbound(peer_id="ws-peer-uuid", before_ts="2026-05-10T12:00:00Z")
|
||||
for msg in messages:
|
||||
print(msg.id, msg.method, msg.peer_name, msg.peer_role)
|
||||
```
|
||||
|
||||
| Parameter | Type | Description |
|
||||
|---|---|---|
|
||||
| `peer_id` | `str` | Filter to messages from a specific peer workspace UUID. Omit to receive from all peers. |
|
||||
| `before_ts` | `str` | RFC3339 timestamp. Return only messages older than this cut-off. Use for pagination by tracking the oldest message seen. |
|
||||
|
||||
Returns a list of `InboundMessage` objects.
|
||||
|
||||
### InboundMessage
|
||||
|
||||
Each inbound message carries these fields in addition to the standard A2A fields:
|
||||
|
||||
| Field | Type | Description |
|
||||
|---|---|---|
|
||||
| `id` | `str` | Message ID. |
|
||||
| `method` | `str` | A2A method (`delegate_task`, `cancel_task`, etc.). |
|
||||
| `params` | `dict` | Method parameters. |
|
||||
| `peer_id` | `str` | UUID of the peer workspace that sent this message. |
|
||||
| `peer_name` | `str` | Display name of the sending peer (from its agent card). |
|
||||
| `peer_role` | `str` | Role of the sending peer (`"sre"`, `"frontend"`, etc.). |
|
||||
| `agent_card_url` | `str` | URL of the sending peer's agent card. |
|
||||
| `raw` | `dict` | Raw channel envelope for forward-compatibility. |
|
||||
|
||||
> **Note:** `peer_name`, `peer_role`, and `agent_card_url` are enriched from the platform's peer registry at dispatch time. They are `None` if the sending peer has not registered an agent card.
|
||||
|
||||
### Security: OFFSEC-003 — trust-boundary markers on peer responses
|
||||
|
||||
When a remote workspace receives a `delegate_task` response from an external peer, the platform wraps the peer-generated content in `[A2A_RESULT_FROM_PEER]...[/A2A_RESULT_FROM_PEER]` trust-boundary markers. These markers signal to the agent that the enclosed content originated outside the platform's trust boundary and must not be re-injected as platform-native output.
|
||||
|
||||
Use `strip_a2a_boundary()` to strip the wrappers before processing the content:
|
||||
|
||||
```python
|
||||
from molecule_agent import RemoteAgentClient, strip_a2a_boundary
|
||||
|
||||
# Normalise inbound peer result — safe on pre-OFFSEC-003 responses (returns
|
||||
# input unchanged when markers absent) and on None/empty strings.
|
||||
result = strip_a2a_boundary(msg.params.get("result", ""))
|
||||
```
|
||||
|
||||
This is particularly important when displaying peer results to users or using them as tool inputs — always strip the boundary markers first. See `molecule-core` [#334](https://git.moleculesai.app/molecule-ai/molecule-core/pull/334) for the platform-side implementation.
|
||||
|
||||
---
|
||||
|
||||
## What Phase 30 Covers
|
||||
|
||||
| Phase | What shipped | Endpoint |
|
||||
|
||||
Loading…
Reference in New Issue
Block a user