with one click
nodes
Interact with companion devices (phones, laptops, headless servers) connected to Suzent.
Menu
Interact with companion devices (phones, laptops, headless servers) connected to Suzent.
Become a helpful co-worker in the workspace. Use it whenever you need to access, manage, or reference files.
Access and maintain the notebook knowledge base with Obsidian markdown conventions.
Render rich interactive UI surfaces (tables, forms, cards, buttons) in the sidebar canvas or inline in chat using the render_ui tool.
Schedule recurring tasks (cron) and periodic agent check-ins (heartbeat).
Enables the agent to speak using text-to-speech.
Social messaging guidelines for Telegram, Slack, Discord, and Feishu. Best practices for formatting, character limits, and platform-specific features.
| name | nodes |
| description | Interact with companion devices (phones, laptops, headless servers) connected to Suzent. |
The Nodes skill lets you control remote companion devices connected to the Suzent server. Nodes connect via WebSocket and advertise capabilities (commands) you can invoke.
In sandbox mode, the suzent CLI is not available. Use the REST API via $SUZENT_BASE_URL.
Use this skill to:
| Action | Method | Path |
|---|---|---|
| List connected nodes | GET | /nodes |
| Describe node | GET | /nodes/{node_id_or_name} |
| Invoke command | POST | /nodes/{node_id_or_name}/invoke |
import os
import requests
base = os.environ["SUZENT_BASE_URL"]
# 1) List nodes
nodes_resp = requests.get(f"{base}/nodes", timeout=30)
nodes_resp.raise_for_status()
nodes = nodes_resp.json().get("nodes", [])
if not nodes:
print("No nodes connected")
else:
# 2) Choose a node (usually by display_name)
node = nodes[0]
node_id = node["node_id"]
# 3) Inspect capabilities
detail_resp = requests.get(f"{base}/nodes/{node_id}", timeout=30)
detail_resp.raise_for_status()
detail = detail_resp.json()
# 4) Invoke command
invoke_resp = requests.post(
f"{base}/nodes/{node_id}/invoke",
json={"command": "camera.snap", "params": {"format": "png"}},
timeout=60,
)
invoke_resp.raise_for_status()
result = invoke_resp.json()
print(result)
Endpoints accept either node_id or display name. Resolving the node first via GET /nodes is still recommended when names may be ambiguous:
target_name = "MyPhone"
target = next((n for n in nodes if n.get("display_name") == target_name), None)
if not target:
raise RuntimeError(f"Node not found: {target_name}")
node_id = target["node_id"]
If you are running on host and the CLI is installed, these commands are still valid:
suzent nodes list
suzent nodes status
suzent nodes describe <node_id_or_name>
suzent nodes invoke <node_id_or_name> <command> key=value [key2=value2 ...]
suzent nodes invoke <node_id_or_name> <command> --params '{"key": "value"}'
# Sandbox-safe invocation example
result = requests.post(
f"{base}/nodes/{node_id}/invoke",
json={"command": "speaker.speak", "params": {"text": "Hello world", "prompt": "cheerful"}},
timeout=60,
).json()
display_name, then use the resolved node_id for API calls.params JSON-serializable and explicit.