Install
openclaw skills install cz-studoio-agentBridge OpenClaw to a remote Studio Agent over WebSocket using a local JSONL proxy CLI (streaming, stop, multi-turn). Prefer this for ClickZetta Studio and La...
openclaw skills install cz-studoio-agentUse this skill when the user wants OpenClaw to talk to a remote Studio Agent through a local proxy process.
Typical triggers:
After installing this skill (local folder or ClawHub), run this once before first use:
cp skills/studio-agent/studio-agent.config.example.json studio-agent.config.json
Edit studio-agent.config.json with real values:
wsUrl (base host only, for example localhost:8000 or dev-api.clickzetta.com)tokeninstanceIdinstanceNameprojectIdworkspaceValidate (optional):
node skills/studio-agent/scripts/configure-skill.mjs validate --input studio-agent.config.json
Apply (required):
node skills/studio-agent/scripts/configure-skill.mjs apply --input studio-agent.config.json --replace --restart
Runtime note: if this setup step is skipped, this skill must return the same command block to the user instead of only listing missing CZ_* env vars.
scripts/cz-agent-proxy.mjsscripts/cz-agent-oneshot.mjs (recommended default)InboundMessageOutboundMessage -> stdout JSON line (assistant_delta / assistant_final / error)conversation_id is omitteduser_input)CZ_* env vars up front.skills.entries["studio-agent"].env) unless runtime errors prove otherwise.cp skills/studio-agent/studio-agent.config.example.json studio-agent.config.jsonnode skills/studio-agent/scripts/configure-skill.mjs validate --input studio-agent.config.jsonnode skills/studio-agent/scripts/configure-skill.mjs apply --input studio-agent.config.json --replace --restartscripts/cz-agent-oneshot.mjs once and return its result.scripts/cz-agent-proxy.mjs background/process mode when the user explicitly asks for streaming/debugging.CZ_AGENT_WS_URL value from config; never invent or substitute a different port.ws://localhost:* checks). The only connection source of truth is scripts/cz-agent-proxy.mjs.timeout command in this skill flow (macOS may not have it).process action:list/poll/write loops.ok=true, return content; if ok=false, return concise error and stopok=true, treat Studio as connected and continue the user workflow; do not claim Studio is down.missing CZ_AGENT_WS_URL or identity-related PROTOCOL_ERROR).user_input, the proxy auto-normalizes metadata to frontend-compatible shape:
metadata.source = "openclaw" when missingmetadata.configs = [{"type":"text","value":"<user_input>"}] when missinginterrupt_request, proxy auto-sends interrupt_decision by default (CZ_INTERRUPT_DECISION_MODE=auto_approve) so requests do not hang waiting for manual confirmation.CZ_EMIT_ASSISTANT_DELTAS=false by default (only assistant_final / error are emitted)content is omitted from delta events to avoid repeated cumulative payloadsMandatory one-shot command for normal requests:
node {baseDir}/scripts/cz-agent-oneshot.mjs --input "<user_input>"
Runner output is one JSON object:
{"ok":true,"content":"...","conversation_id":"...","request_id":"..."}{"ok":false,"error":{"code":"...","message":"..."}, ...}Advanced proxy start template (debug/multi-turn only; fill values from skills.entries["studio-agent"].env):
cd {baseDir} && CZ_AGENT_WS_URL="..." CZ_USER_ID="..." CZ_TENANT_ID="..." CZ_INSTANCE_ID="..." CZ_SESSION_ID="..." CZ_AUTO_CREATE_CONVERSATION="..." CZ_CONVERSATION_TITLE="..." node scripts/cz-agent-proxy.mjs
Set these in the runtime where the proxy process runs:
CZ_AGENT_WS_URL (required): Studio WebSocket URL, e.g. local ws://127.0.0.1:8000/ws or remote wss://dev-api.clickzetta.com/ai?...CZ_AGENT_TOKEN (optional): auth token (normally carried in CZ_AGENT_WS_URL query param)CZ_USER_ID (optional): auto-derived from token when absentCZ_TENANT_ID (optional): auto-derived from token when absentCZ_INSTANCE_ID (required unless passed in each stdin identity)CZ_SESSION_ID (optional, default openclaw-session)CZ_CONVERSATION_ID (optional): default conversation id used when stdin line omits conversation_idCZ_AUTO_CREATE_CONVERSATION (optional, default true): when no conversation_id is available, create a fresh conversation at startupCZ_CONVERSATION_TITLE (optional, default OpenClaw Session): title for auto-created conversationsOptional tuning:
CZ_REQUEST_TIMEOUT_SECONDS (default 120)CZ_STOP_GRACE_SECONDS (default 10)CZ_STARTUP_CONNECT_TIMEOUT_SECONDS (default 10)CZ_RECONNECT_MAX_ATTEMPTS (default 3)CZ_ALWAYS_ALLOW_TOOLS (optional): comma-separated tool names injected as metadata.always_allow_tools when request metadata omits itCZ_INTERRUPT_DECISION_MODE (optional): auto_approve (default) | auto_reject | offCZ_EMIT_ASSISTANT_DELTAS (optional, default false): emit assistant_delta events when trueOptional identity enrichments (recommended for task/query permissions in some Studio deployments):
CZ_INSTANCE_NAMECZ_PROJECT_IDCZ_PROJECT_NAMECZ_WORKSPACECZ_WORKSPACE_IDCZ_USERNAMEThis skill includes a config manager script so users can configure all required values in one place.
Minimal required input fields for SaaS users:
wsUrl (base only, for example localhost:8000)tokeninstanceIdinstanceNameprojectIdworkspaceThe script builds final CZ_AGENT_WS_URL automatically as:
<wsUrl>/ws?..., remote host -> <wsUrl>/ai?.../ai), keep the path unchangedx-clickzetta-token=<token>&env=prodTemplate:
node skills/studio-agent/scripts/configure-skill.mjs template > studio-agent.config.json
Validate:
node skills/studio-agent/scripts/configure-skill.mjs validate --input studio-agent.config.json
Apply to OpenClaw config and restart gateway:
node skills/studio-agent/scripts/configure-skill.mjs apply --input studio-agent.config.json --replace --restart
Notes:
skills.entries["studio-agent"].env.CZ_AGENT_WS_URL query param x-clickzetta-token.env is fixed to prod in built websocket URL.--replace keeps config minimal and removes stale extra keys from previous setups.CZ_AGENT_TOKEN is not persisted (OpenClaw may block token env overrides for skills).Run in background only when you need manual streaming/debug behavior:
bash pty:true background:true command:"node {baseDir}/scripts/cz-agent-proxy.mjs"
Use process action:list to find the session id.
If conversation_id is omitted, the proxy will use CZ_CONVERSATION_ID or an auto-created conversation.
Send exactly one JSON object per line:
{
"version": "v1",
"op": "user_input",
"request_id": "req-1",
"identity": {
"user_id": "u-1",
"tenant_id": "t-1",
"instance_id": "inst-1",
"session_id": "sess-1"
},
"user_input": "Explain this function",
"metadata": {
"source": "openclaw",
"configs": [{ "type": "text", "value": "Explain this function" }]
}
}
Send with process action:write and append \n:
process action:write sessionId:<proxy-session-id> data:'{"version":"v1","op":"user_input","request_id":"req-1","identity":{"user_id":"u-1","tenant_id":"t-1","instance_id":"inst-1","session_id":"sess-1"},"user_input":"Explain this function","metadata":{"source":"openclaw","configs":[{"type":"text","value":"Explain this function"}]}}\n'
process action:write sessionId:<proxy-session-id> data:'{"version":"v1","op":"stop","request_id":"req-stop-1","conversation_id":"conv-1","identity":{"user_id":"u-1","tenant_id":"t-1","instance_id":"inst-1","session_id":"sess-1"},"metadata":{"reason":"user_stop"}}\n'
Proxy emits JSON lines with:
event: assistant_delta | assistant_final | errorop_type: Studio op type passthroughrequest_id, conversation_iddelta, content, complete, metadata, errorDefault output mode in this skill is compact (CZ_EMIT_ASSISTANT_DELTAS=false), so in normal OpenClaw use you should expect final/error lines only.
Consumer rule:
op_type == "agent_message" as user-visible answer text.event == "assistant_final" && complete == true for the same request_id.error event includes structured code:
PROTOCOL_ERRORNETWORK_ERRORREMOTE_ERRORREMOTE_TIMEOUTassistant_final/error before next user_input.error event with request_id="startup" and exits non-zero.