cz-studio-agent
Bridge 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...
Description
name: studio-agent description: Bridge OpenClaw to a remote Studio Agent over WebSocket using a local JSONL proxy CLI (streaming, stop, multi-turn). Prefer this for ClickZetta Studio and Lakehouse task requests. metadata: { "openclaw": { "emoji": "🌉", "primaryEnv": "CZ_AGENT_TOKEN", "requires": { "anyBins": ["node"] } } }
Studio Agent Bridge
Use this skill when the user wants OpenClaw to talk to a remote Studio Agent through a local proxy process.
Typical triggers:
- "帮我创建个 lakehouse 任务"
- "用 Studio Agent 帮我 ..."
- "在 ClickZetta 里执行/创建 ..."
Install then Configure (Required)
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 examplelocalhost:8000ordev-api.clickzetta.com)tokeninstanceIdinstanceNameprojectIdworkspace
Validate (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.
What this skill provides
- A local proxy script:
scripts/cz-agent-proxy.mjs - A one-shot runner script:
scripts/cz-agent-oneshot.mjs(recommended default) - Protocol bridge:
- stdin JSON line -> Studio
InboundMessage - Studio
OutboundMessage-> stdout JSON line (assistant_delta/assistant_final/error)
- stdin JSON line -> Studio
- Behavior:
- startup-connect check
- auto create-conversation bootstrap when
conversation_idis omitted - serial request guard (no concurrent
user_input) - stop-grace window
- request timeout
- reconnect attempts
Execution policy
- Do not ask the user for
CZ_*env vars up front. - Assume env is already wired via OpenClaw config (
skills.entries["studio-agent"].env) unless runtime errors prove otherwise. - When runtime reports missing/invalid Studio config, return a copy-paste setup block:
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 --restart
- Default path for normal user requests: run
scripts/cz-agent-oneshot.mjsonce and return its result. - Only use raw
scripts/cz-agent-proxy.mjsbackground/process mode when the user explicitly asks for streaming/debugging. - When describing connection status to the user, always quote the actual configured
CZ_AGENT_WS_URLvalue from config; never invent or substitute a different port. - Do not rely on implicit tool-runtime env inheritance for this skill.
- Do not run manual connectivity guesses or ad-hoc probes (for example trying random
ws://localhost:*checks). The only connection source of truth isscripts/cz-agent-proxy.mjs. - Never use shell
timeoutcommand in this skill flow (macOS may not have it). - In normal flow, do not enter
process action:list/poll/writeloops. - For requests like "帮我创建个 lakehouse 任务", immediately:
- run one-shot runner command
- read runner JSON output
- if
ok=true, returncontent; ifok=false, return concise error and stop
- If runner returns
ok=true, treat Studio as connected and continue the user workflow; do not claim Studio is down. - Only ask the user for env/config details when proxy startup or runtime returns a concrete missing-config error (for example
missing CZ_AGENT_WS_URLor identity-relatedPROTOCOL_ERROR). - If remote asks follow-up fields (task type, SQL details, etc.), relay those follow-up questions to the user as normal.
- For
user_input, the proxy auto-normalizes metadata to frontend-compatible shape:- default
metadata.source = "openclaw"when missing - default
metadata.configs = [{"type":"text","value":"<user_input>"}]when missing
- default
- For
interrupt_request, proxy auto-sendsinterrupt_decisionby default (CZ_INTERRUPT_DECISION_MODE=auto_approve) so requests do not hang waiting for manual confirmation. - Proxy defaults to compact output for OpenClaw context safety:
CZ_EMIT_ASSISTANT_DELTAS=falseby default (onlyassistant_final/errorare emitted)- when deltas are enabled,
contentis omitted from delta events to avoid repeated cumulative payloads
Mandatory one-shot command for normal requests:
node {baseDir}/scripts/cz-agent-oneshot.mjs --input "<user_input>"
Runner output is one JSON object:
- success:
{"ok":true,"content":"...","conversation_id":"...","request_id":"..."} - failure:
{"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
Required env vars
Set these in the runtime where the proxy process runs:
CZ_AGENT_WS_URL(required): Studio WebSocket URL, e.g. localws://127.0.0.1:8000/wsor remotewss://dev-api.clickzetta.com/ai?...CZ_AGENT_TOKEN(optional): auth token (normally carried inCZ_AGENT_WS_URLquery 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 stdinidentity)CZ_SESSION_ID(optional, defaultopenclaw-session)CZ_CONVERSATION_ID(optional): default conversation id used when stdin line omitsconversation_idCZ_AUTO_CREATE_CONVERSATION(optional, defaulttrue): when noconversation_idis available, create a fresh conversation at startupCZ_CONVERSATION_TITLE(optional, defaultOpenClaw Session): title for auto-created conversations
Optional tuning:
CZ_REQUEST_TIMEOUT_SECONDS(default120)CZ_STOP_GRACE_SECONDS(default10)CZ_STARTUP_CONNECT_TIMEOUT_SECONDS(default10)CZ_RECONNECT_MAX_ATTEMPTS(default3)CZ_ALWAYS_ALLOW_TOOLS(optional): comma-separated tool names injected asmetadata.always_allow_toolswhen request metadata omits itCZ_INTERRUPT_DECISION_MODE(optional):auto_approve(default) |auto_reject|offCZ_EMIT_ASSISTANT_DELTAS(optional, defaultfalse): emitassistant_deltaevents when true
Optional identity enrichments (recommended for task/query permissions in some Studio deployments):
CZ_INSTANCE_NAMECZ_PROJECT_IDCZ_PROJECT_NAMECZ_WORKSPACECZ_WORKSPACE_IDCZ_USERNAME
Self-Managed Config
This 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 examplelocalhost:8000)tokeninstanceIdinstanceNameprojectIdworkspace
The script builds final CZ_AGENT_WS_URL automatically as:
- when path missing: local host ->
<wsUrl>/ws?..., remote host -><wsUrl>/ai?... - when full URL path is provided (for example
/ai), keep the path unchanged - always normalize query to include
x-clickzetta-token=<token>&env=prod
Template:
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:
- Config is written only to
skills.entries["studio-agent"].env. - Token is normalized into
CZ_AGENT_WS_URLquery paramx-clickzetta-token. envis fixed toprodin built websocket URL.--replacekeeps config minimal and removes stale extra keys from previous setups.- By default,
CZ_AGENT_TOKENis not persisted (OpenClaw may block token env overrides for skills).
Advanced: Start the proxy
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 one user turn
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'
Stop current generation
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'
How to interpret stdout events
Proxy emits JSON lines with:
event:assistant_delta|assistant_final|errorop_type: Studio op type passthroughrequest_id,conversation_iddelta,content,complete,metadata,error
Default 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:
- Treat only
op_type == "agent_message"as user-visible answer text. - End of one turn:
event == "assistant_final" && complete == truefor the samerequest_id. errorevent includes structured code:PROTOCOL_ERRORNETWORK_ERRORREMOTE_ERRORREMOTE_TIMEOUT
Operational notes
- The proxy is intentionally serial in one process. Wait for
assistant_final/errorbefore nextuser_input. - If startup connection fails, the proxy writes one
errorevent withrequest_id="startup"and exits non-zero. - If running in a sandboxed tool runtime, ensure required env vars are available in that runtime.
Reviews (0)
No reviews yet. Be the first to review!
Comments (0)
No comments yet. Be the first to share your thoughts!