Merge pull request 'docs: update remote-agent tutorial to match SDK API' (#371) from docs/update-remote-agent-tutorial-sdk-api into main
Some checks failed
CI / Canvas Deploy Reminder (push) Blocked by required conditions
Block internal-flavored paths / Block forbidden paths (push) Successful in 16s
Secret scan / Scan diff for credential-shaped strings (push) Successful in 15s
E2E API Smoke Test / detect-changes (push) Successful in 1m11s
E2E Staging Canvas (Playwright) / detect-changes (push) Successful in 1m10s
CI / Detect changes (push) Successful in 1m18s
Handlers Postgres Integration / detect-changes (push) Successful in 1m10s
Runtime PR-Built Compatibility / detect-changes (push) Successful in 1m9s
Sweep stale Cloudflare DNS records / Sweep CF orphans (push) Failing after 28s
ci-required-drift / drift (push) Failing after 1m46s
E2E API Smoke Test / E2E API Smoke Test (push) Successful in 10s
CI / Platform (Go) (push) Successful in 10s
CI / Canvas (Next.js) (push) Successful in 11s
E2E Staging Canvas (Playwright) / Canvas tabs E2E (push) Successful in 12s
CI / Shellcheck (E2E scripts) (push) Successful in 5s
CI / Python Lint & Test (push) Successful in 7s
Handlers Postgres Integration / Handlers Postgres Integration (push) Successful in 8s
Runtime PR-Built Compatibility / PR-built wheel + import smoke (push) Successful in 7s
Continuous synthetic E2E (staging) / Synthetic E2E against staging (push) Has started running
Sweep stale e2e-* orgs (staging) / Sweep e2e orgs (push) Successful in 17s
Sweep stale AWS Secrets Manager secrets / Sweep AWS Secrets Manager (push) Failing after 18s
Canary — staging SaaS smoke (every 30 min) / Canary smoke (push) Failing after 15m59s
Some checks failed
CI / Canvas Deploy Reminder (push) Blocked by required conditions
Block internal-flavored paths / Block forbidden paths (push) Successful in 16s
Secret scan / Scan diff for credential-shaped strings (push) Successful in 15s
E2E API Smoke Test / detect-changes (push) Successful in 1m11s
E2E Staging Canvas (Playwright) / detect-changes (push) Successful in 1m10s
CI / Detect changes (push) Successful in 1m18s
Handlers Postgres Integration / detect-changes (push) Successful in 1m10s
Runtime PR-Built Compatibility / detect-changes (push) Successful in 1m9s
Sweep stale Cloudflare DNS records / Sweep CF orphans (push) Failing after 28s
ci-required-drift / drift (push) Failing after 1m46s
E2E API Smoke Test / E2E API Smoke Test (push) Successful in 10s
CI / Platform (Go) (push) Successful in 10s
CI / Canvas (Next.js) (push) Successful in 11s
E2E Staging Canvas (Playwright) / Canvas tabs E2E (push) Successful in 12s
CI / Shellcheck (E2E scripts) (push) Successful in 5s
CI / Python Lint & Test (push) Successful in 7s
Handlers Postgres Integration / Handlers Postgres Integration (push) Successful in 8s
Runtime PR-Built Compatibility / PR-built wheel + import smoke (push) Successful in 7s
Continuous synthetic E2E (staging) / Synthetic E2E against staging (push) Has started running
Sweep stale e2e-* orgs (staging) / Sweep e2e orgs (push) Successful in 17s
Sweep stale AWS Secrets Manager secrets / Sweep AWS Secrets Manager (push) Failing after 18s
Canary — staging SaaS smoke (every 30 min) / Canary smoke (push) Failing after 15m59s
This commit is contained in:
commit
deda8ddccf
@ -117,7 +117,7 @@ This keeps secrets out of environment blocks and allows rotation without restart
|
||||
|
||||
### Step 4: Start the heartbeat loop
|
||||
|
||||
The heartbeat keeps your agent visible on the canvas. Send it every **30 seconds**:
|
||||
The heartbeat keeps your agent visible on the canvas and reports runtime state to the platform. Send it every **30 seconds**:
|
||||
|
||||
```python
|
||||
import requests, time
|
||||
@ -130,7 +130,14 @@ while True:
|
||||
resp = requests.post(
|
||||
f"{PLATFORM_URL}/registry/heartbeat",
|
||||
headers={"Authorization": f"Bearer {AUTH_TOKEN}"},
|
||||
json={"workspace_id": WORKSPACE_ID},
|
||||
json={
|
||||
"workspace_id": WORKSPACE_ID,
|
||||
"active_tasks": 0, # number of tasks currently being processed
|
||||
"current_task": None, # optional: short description of what the agent is doing
|
||||
"uptime_seconds": 0, # optional: seconds since agent started
|
||||
"error_rate": 0.0, # optional: fraction of requests that errored in the last period
|
||||
"runtime_state": "idle", # one of: idle, working, paused, error
|
||||
},
|
||||
)
|
||||
if resp.status_code != 200:
|
||||
print(f"Heartbeat failed: {resp.status_code} {resp.text}")
|
||||
@ -139,29 +146,44 @@ while True:
|
||||
|
||||
If the platform misses three consecutive heartbeats (90 seconds), it marks the agent as `offline` on the canvas. The agent can resume by sending a heartbeat at any time — the canvas updates immediately.
|
||||
|
||||
> **Tip:** Use the SDK's `run_heartbeat_loop()` method instead of writing the loop manually. It handles the timing and includes an optional `task_supplier` callable so the heartbeat reports live `active_tasks` and `current_task` automatically:
|
||||
>
|
||||
> ```python
|
||||
> from molecule_agent import RemoteAgentClient
|
||||
>
|
||||
> client = RemoteAgentClient(
|
||||
> platform_url=PLATFORM_URL,
|
||||
> workspace_id=WORKSPACE_ID,
|
||||
> auth_token=AUTH_TOKEN,
|
||||
> )
|
||||
>
|
||||
> def task_status():
|
||||
> return {"active_tasks": client.get_active_task_count(), "current_task": client.get_current_task_name()}
|
||||
>
|
||||
> client.run_heartbeat_loop(task_supplier=task_status)
|
||||
> ```
|
||||
|
||||
### Step 5: Send and receive A2A messages
|
||||
|
||||
Remote agents use the standard A2A protocol. Your agent polls for inbound tasks:
|
||||
Remote agents use the standard A2A protocol. Use the SDK's `fetch_inbound()` method to poll for inbound tasks:
|
||||
|
||||
```bash
|
||||
curl -s -X POST "${PLATFORM_URL}/a2a" \
|
||||
-H "Authorization: Bearer ${AUTH_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "X-Workspace-ID: ${WORKSPACE_ID}" \
|
||||
-d '{
|
||||
"jsonrpc": "2.0",
|
||||
"id": 1,
|
||||
"method": "message/send",
|
||||
"params": {
|
||||
"message": {
|
||||
"role": "user",
|
||||
"parts": [{"kind": "text", "text": "Hello from a remote agent"}]
|
||||
}
|
||||
}
|
||||
}'
|
||||
```python
|
||||
from molecule_agent import RemoteAgentClient
|
||||
|
||||
client = RemoteAgentClient(
|
||||
platform_url=PLATFORM_URL,
|
||||
workspace_id=WORKSPACE_ID,
|
||||
auth_token=AUTH_TOKEN,
|
||||
)
|
||||
|
||||
# Poll for inbound tasks (call this in your agent's main loop)
|
||||
task = client.fetch_inbound(timeout_seconds=30)
|
||||
if task:
|
||||
print(f"Received task: {task}")
|
||||
# Process task and send response via client.send_result(...)
|
||||
```
|
||||
|
||||
The `X-Workspace-ID` header identifies which workspace the message originates from. Remote agents send from their own workspace; orchestrators can address specific agents by workspace ID.
|
||||
The SDK handles the `X-Workspace-ID` header automatically. Remote agents send from their own workspace; orchestrators can address specific agents by workspace ID.
|
||||
|
||||
### Step 6: Verify the agent appears on the canvas
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user