Openclaw Deployment (Legacy) Overview
OpenClaw uses VAGUS through natural language. The user should not need terminal commands to install, pair, or use the phone capabilities. The agent retrieves files, installs dependencies, pairs with the app, and runs MCP operations autonomously.
Deprecation status: This page documents the legacy vagus-openclaw path.
Recommended integration: plugin-first OpenClaw integration from https://github.com/embodiedsystems-org/Somatic-Memory-for-Openclaw
User interface: natural-language prompts in OpenClaw
Agent execution: command + MCP orchestration under the hood
CLI Entry: scripts/vagus-connect.js
Managed streaming entry: scripts/vagus-manager.js
Long-lived model: one managed MCP session with runtime add/remove/list/status control
Session Store: ~/.openclaw/vagus-session.json
Pair Endpoint: https://relay.withvagus.com/pair
WebSocket Relay: wss://relay.withvagus.com/connect/<session_token>
Natural-Language Flow
Primary UX is conversational. A typical user flow:
- User asks OpenClaw to install VAGUS from the repository URL.
- Agent fetches skill files, installs Node dependency, and registers the skill.
- Agent asks user for the code from the VAGUS Android app.
- Agent pairs, verifies capabilities, and confirms connection in plain language.
- User asks for actions in natural language (notify, open URL, send SMS, create event, read context).
Pairing is a one-time bootstrap. Subsequent requests reuse the saved session token until expired or revoked.
Prompt Cookbook
| User Says | Expected Agent Behavior |
|---|---|
| Install Somatic Memory OpenClaw plugins from https://github.com/embodiedsystems-org/Somatic-Memory-for-Openclaw | Use plugin-first installation flow from the Somatic Memory repository root. |
Pair using code 584821 |
Call pair flow, persist session token, announce available resources/tools. |
Send a test notification |
Invoke notify, return success/failure naturally. |
Send an SMS to +15556667777 |
Invoke sms/send; handle approval prompts if required. |
Create a calendar event Sunday 3pm Event Name |
Map time intent to epoch ms, call calendar/create_event, report event result. |
Start screen and location subscriptions |
Run long-lived subscriptions, stream updates, and keep both active. |
This prompt-first contract is the primary documentation surface for OpenClaw operators.
User Journey
1. Install and Pair
User: Install Somatic Memory OpenClaw plugins from https://github.com/embodiedsystems-org/Somatic-Memory-for-Openclaw
Agent: I installed the plugin stack. Open the VAGUS app and share your pairing code.
User: 584821
Agent: Paired successfully. I can now access phone resources and tools.
2. Ask for Context
User: Are you tracking my screen state?
Agent: Yes. Your screen is currently on and unlocked.
User: Start tracking location too.
Agent: Done. I am now streaming screen and location context.
3. Trigger Actions
User: Send a test notification.
Agent: Sent.
User: Open withvagus.com.
Agent: Opened on your phone.
User: Add an event Sunday 3pm called Event Name.
Agent: Created the event.
4. Recover from Failures
User: Send the SMS again.
Agent: The device approval timed out. Please approve on your phone and I will retry once.
User: Retry.
Agent: Sent successfully.
These transcripts are the intended user-facing interaction model in OpenClaw. CLI details remain internal.
Architecture
| Component | Responsibility | Key Behavior |
|---|---|---|
vagus-connect.js |
CLI dispatcher and JSONL output contract. | Maps subcommands to session ops and normalizes error codes. |
lib/mcp-session.js |
MCP protocol state machine. | Initialize handshake, request/response correlation, list/read/call/subscribe. |
lib/ws-transport.js |
WebSocket transport and liveness checks. | Ping every 30s; terminate on missing pong after 10s. |
scripts/vagus-manager.js |
Persistent subscription owner. | One-session manager with singleton protection, runtime control, and freshness state. |
lib/managed-subscription-session.js |
Reconnect + resubscribe coordinator. | Re-establishes transport, re-runs MCP initialize, and re-subscribes active URIs. |
lib/adaptive-freshness.js |
Dynamic stream health model. | Learns stale thresholds from observed inter-arrival timing with no per-resource hard-coded cadence. |
lib/session-store.js |
Persist and load token metadata. | Reads/writes JSON to ~/.openclaw/vagus-session.json. |
lib/subscription-manager.js |
Tracks active subscriptions for re-subscribe flows. | Best-effort replay of subscribe calls after reconnect. |
Protocol Lifecycle
1. Pair
Client posts pairing code and receives session token.
POST https://relay.withvagus.com/pair
{"code":"ABC123"}
2. Connect + Initialize
Client opens WSS with the token and runs MCP initialization. Implementation sends compatibility variants:
initialized, notifications/initialized, and an initialized request.
connect WSS -> initialize -> initialized notifications
-> resources/list + tools/list
MCP responses and notifications now include request correlation metadata at:
metadata.requestId. This is emitted by the server for request/notification lineage.
{
"jsonrpc": "2.0",
"id": 2,
"metadata": {
"requestId": "43818824:resources/read:5545a8fa214dd67e:2c570c8b7e66e561"
},
"result": { "contents": [ ... ] }
}
3. Operate
Client executes reads, tool calls, or subscriptions. All stdout is JSONL for machine parsing.
Agent Execution Contract (Internal)
The following command interface is internal to agent implementation and diagnostics. End users should interact via natural language prompts.
Base invocation used by agent runtime:
node {baseDir}/scripts/vagus-connect.js <command> [args]
| Command | Arguments | Output Shape |
|---|---|---|
pair | <code> | paired then capabilities |
connect | none | connected then capabilities |
status | none | status object |
read | <uri> | resource object |
subscribe | <uri> | lifecycle/stream_state/update stream |
unsubscribe | <uri> | unsubscribed |
call | <tool> '<json>' | result object |
list-resources | none | resources array |
list-tools | none | tools array |
disconnect | none | disconnected and deletes local session file |
vagus-manager.js add | <uri> | Add URI to managed long-lived set |
vagus-manager.js remove | <uri> | Remove URI from managed long-lived set |
vagus-manager.js list | none | List active managed subscriptions |
vagus-manager.js status | none | Managed stream freshness and lifecycle status |
Streaming Model
Persistent streaming should be managed through one long-lived manager session. Direct
subscribe remains useful for ad hoc single-stream workflows, but it is no longer the preferred
pattern for multiple concurrent long-lived streams.
node {baseDir}/scripts/vagus-connect.js subscribe vagus://device/screen
{"type":"lifecycle","uri":"vagus://device/screen","event":{"type":"connected","subscriptions":["vagus://device/screen"]}}
{"type":"stream_state","uri":"vagus://device/screen","status":"warming","freshness_ms":null,"thresholds":null}
{"type":"update","uri":"vagus://device/screen","data":{"screen_on":true,"locked":false,"last_event":"init","ts":1772036194947},"freshness":{"status":"fresh"}}
On reconnect, the client emits session_reconnect, transitions streams through
grace/warming as needed, then resumes update delivery once fresh data arrives.
User-facing phrasing should remain natural: for example, "I am now tracking your screen and location state."
Freshness should be inferred from stream_state and recent update timing, not from log file activity.
node {baseDir}/scripts/vagus-manager.js
node {baseDir}/scripts/vagus-manager.js add vagus://sensors/location
node {baseDir}/scripts/vagus-manager.js status
Resources
Core URI groups:
- Session:
vagus://session/info - Sensors:
vagus://sensors/motion,activity,activity_recognition,location,environment - Inference:
vagus://inference/attention,indoor_confidence,sleep_likelihood,notification_timing - Device:
vagus://device/connectivity,screen,battery,clipboard,notifications
For inference URIs, subscription mode generally provides better quality than cold one-shot reads.
node {baseDir}/scripts/vagus-connect.js read vagus://inference/attention
node {baseDir}/scripts/vagus-connect.js subscribe vagus://sensors/location
Subscriptions vs Read-Only
Agents should choose read or subscribe per URI based on server support.
Attempting to subscribe to a read-only URI returns an MCP error.
| URI | Use read |
Use subscribe |
Guidance |
|---|---|---|---|
vagus://session/info | Yes | Yes | Useful for runtime/session health tracking. |
vagus://sensors/motion | Yes | Yes | Use subscribe for continuous motion context. |
vagus://sensors/location | Yes | Yes | Use subscribe for ongoing location tracking. |
vagus://device/connectivity | Yes | Yes | Event-driven connectivity updates. |
vagus://device/clipboard | Yes | No | Treat as point-in-time snapshot only. |
vagus://device/screen | Yes | Yes | Prefer subscribe for live state changes. |
vagus://device/notifications | Yes | Yes | Subscribe for posted/removed event stream. |
vagus://device/battery | Yes | Yes | Subscription updates are intentionally sparse (~5m cadence). |
vagus://sensors/activity, activity_recognition, environment, vagus://inference/* | Yes | Yes | Subscription cadence follows app Infer resolution setting. |
vagus://io/type_* | Yes | Yes | Subscription cadence follows app I/O resolution setting. |
Tools
Call pattern:
node {baseDir}/scripts/vagus-connect.js call <tool-name> '<json-params>'
| Tool | Purpose | Required Params | Constraints / Governance |
|---|---|---|---|
notify | Push local phone notification. | title, body | title/body max length 200/1000; requires notifications capability enabled. |
speak | TTS playback on device. | text | text max 5000; optional voice/language/rate/pitch/interrupt values are validated server-side. |
sms/send | Send SMS message. | to, body | body max 2000; Android SEND_SMS and SMS governance/policy must allow. |
intent/open_url | Open URL in browser. | url | URL must be http/https; policy may enforce HTTPS-only and consent/rate limits. |
calendar/create_event | Create calendar event. | title | Optional timing/location fields allowed; calendar permissions and calendar governance policy apply. |
clipboard/set | Write clipboard text. | content | content max 10000; blocked when clipboard capability is disabled. |
io/set_subscription_resolution | Set cadence for all vagus://io/type_* subscriptions. | resolutionMs | Allowed values: 1500, 10000, 30000, 60000, 90000, 120000, 300000; requires Allow agent to set resolution. |
infer/set_subscription_resolution | Set cadence for infer subscriptions (activity, environment, vagus://inference/*). | resolutionMs | Allowed values: 1500, 10000, 30000, 60000, 90000, 120000, 300000; requires Allow agent to set infer resolution. |
haptic/pulse | Single haptic pulse. | none | Optional durationMs (10-5000, default 120); requires haptics capability and Android vibrate permission. |
haptic/pattern | Pattern vibration. | none | Optional pattern integer array; requires haptics capability and Android vibrate permission. |
agent/set_name | Set device-side agent name. | name | Max 64 chars; empty string clears the stored name. |
Validated Examples
node {baseDir}/scripts/vagus-connect.js call sms/send '{"to":"+15556667777","body":"Test message from VAGUS OpenClaw"}'
node {baseDir}/scripts/vagus-connect.js call intent/open_url '{"url":"https://withvagus.com"}'
node {baseDir}/scripts/vagus-connect.js call io/set_subscription_resolution '{"resolutionMs":30000}'
node {baseDir}/scripts/vagus-connect.js call infer/set_subscription_resolution '{"resolutionMs":30000}'
node {baseDir}/scripts/vagus-connect.js call calendar/create_event '{"title":"Event Name","startTimeMs":1771772400000,"endTimeMs":1771776000000,"allDay":false}'
io/set_subscription_resolution only works when the app governance toggle
Allow agent to set resolution is enabled (default off).
infer/set_subscription_resolution only works when
Allow agent to set infer resolution is enabled (default off).
User Permissions (Server-Side)
Permission state is controlled by the user in the VAGUS Android app (server side), not by OpenClaw. OpenClaw can request reads/tool calls, but execution depends on enabled modules and approval outcomes.
| Control | Set By | Effect |
|---|---|---|
| Module/capability toggles | User in VAGUS app | Determines which resources/tools are exposed. |
| Runtime tool approvals | User in VAGUS app prompt | Approves or denies sensitive actions. |
| Agent identity label | agent/set_name + app context | Affects approval UI/session metadata context. |
If blocked, agent messaging should be explicit: ask the user to enable permission or approve on-device, then retry once.
Reliability and Timeouts
| Mechanism | Current Value | Where Implemented |
|---|---|---|
| MCP request timeout | 22000ms | lib/mcp-session.js |
| Initialize timeout | 20000ms | lib/mcp-session.js |
| Heartbeat interval | 30000ms | lib/ws-transport.js |
| Pong deadline | 10000ms | lib/ws-transport.js |
If no pong is received within the heartbeat deadline, the socket is force-terminated and upper layers must re-establish connection state.
Error Codes and Handling
| Code | Typical Cause | Action |
|---|---|---|
NO_COMMAND | Missing subcommand. | Use documented command shape. |
NO_SESSION | No local session file. | Run pair. |
PAIR_FAILED | Pair endpoint failed/rejected. | Check code and app connectivity. |
SESSION_EXPIRED | Token invalid/expired. | Delete session file, then re-pair. |
CONNECT_FAILED | WSS connection/initialize failure. | Check relay/network availability. |
BAD_JSON | Malformed JSON args for call. | Fix quoting and JSON payload. |
READ_FAILED | Read failed or unsupported URI. | Check active modules in session/info. |
CALL_FAILED | Tool call timeout or runtime failure. | Retry once, then inspect device approvals. |
PERMISSION_DENIED | Capability disabled or approval denied. | Enable permission or re-approve in app. |
FATAL | Unhandled client exception. | Capture logs and restart command. |
Operational Runbooks
Natural-Language Recovery Prompts
Your session expired. Please open VAGUS and share a new pairing code.I can’t reach the relay right now. Please confirm your phone has internet and VAGUS is running.This action needs permission in VAGUS. Please enable it, then I’ll retry once.
Session Repair
rm ~/.openclaw/vagus-session.json
node {baseDir}/scripts/vagus-connect.js pair <NEW_CODE>
node {baseDir}/scripts/vagus-connect.js status
Connectivity Probe
node {baseDir}/scripts/vagus-connect.js status
node {baseDir}/scripts/vagus-connect.js read vagus://session/info
node {baseDir}/scripts/vagus-connect.js list-tools
node {baseDir}/scripts/vagus-manager.js status
Permission Probe
node {baseDir}/scripts/vagus-connect.js call notify '{"title":"Permission Check","body":"Testing notify permission"}'
node {baseDir}/scripts/vagus-connect.js read vagus://device/notifications
Detailed schema references remain in references/mcp-resources.md,
references/mcp-tools.md, and references/troubleshooting.md.