Nodes and media

Node

Node는 Gateway WebSocket(operator와 동일한 포트)에 role: "node"로 연결하고 node.invoke를 통해 명령 표면(예: canvas.*, camera.*, device.*, notifications.*, system.*)을 노출하는 동반 장치(macOS/iOS/Android/headless)입니다. 프로토콜 세부 정보: Gateway 프로토콜.

레거시 전송: 브리지 프로토콜 (TCP JSONL; 현재 Node에는 기록 용도로만 해당).

macOS도 Node 모드로 실행할 수 있습니다. 메뉴바 앱이 Gateway의 WS 서버에 연결하고 로컬 canvas/camera 명령을 Node로 노출합니다(따라서 openclaw nodes …가 이 Mac에 대해 동작합니다). 원격 Gateway 모드에서는 브라우저 자동화가 네이티브 앱 Node가 아니라 CLI Node 호스트(openclaw node run 또는 설치된 Node 서비스)에서 처리됩니다.

참고:

  • Node는 Gateway가 아니라 주변 장치입니다. Gateway 서비스를 실행하지 않습니다.
  • Telegram/WhatsApp 등 메시지는 Node가 아니라 Gateway에 도착합니다.
  • 문제 해결 런북: /nodes/troubleshooting

페어링 + 상태

WS Node는 장치 페어링을 사용합니다. Node는 connect 중에 장치 ID를 제시하고, Gateway는 role: node에 대한 장치 페어링 요청을 생성합니다. devices CLI(또는 UI)를 통해 승인하세요.

빠른 CLI:

openclaw devices list
openclaw devices approve <requestId>
openclaw devices reject <requestId>
openclaw nodes status
openclaw nodes describe --node <idOrNameOrIp>

Node가 변경된 인증 세부 정보(role/scopes/public key)로 재시도하면 이전의 대기 중인 요청이 대체되고 새 requestId가 생성됩니다. 승인하기 전에 openclaw devices list를 다시 실행하세요.

참고:

  • nodes status는 장치 페어링 role에 node가 포함된 경우 Node를 paired로 표시합니다.
  • 장치 페어링 레코드는 승인된 role에 대한 지속 계약입니다. 토큰 회전은 그 계약 안에 머무르며, 페어링 승인이 부여한 적 없는 다른 role로 paired Node를 승격할 수 없습니다.
  • node.pair.*(CLI: openclaw nodes pending/approve/reject/remove/rename)는 별도의 Gateway 소유 Node 페어링 저장소입니다. WS connect 핸드셰이크를 차단하지 않습니다.
  • openclaw nodes remove --node <id|name|ip>는 해당 별도 Gateway 소유 Node 페어링 저장소에서 오래된 항목을 삭제합니다.
  • 승인 범위는 대기 중인 요청이 선언한 명령을 따릅니다.
    • 명령 없는 요청: operator.pairing
    • 비 exec Node 명령: operator.pairing + operator.write
    • system.run / system.run.prepare / system.which: operator.pairing + operator.admin

원격 Node 호스트(system.run)

Gateway가 한 머신에서 실행되고 명령은 다른 머신에서 실행되게 하려면 Node 호스트를 사용하세요. 모델은 여전히 Gateway와 대화하며, host=node가 선택되면 Gateway가 exec 호출을 Node 호스트로 전달합니다.

어디서 무엇이 실행되는지

  • Gateway 호스트: 메시지를 수신하고, 모델을 실행하며, 도구 호출을 라우팅합니다.
  • Node 호스트: Node 머신에서 system.run/system.which를 실행합니다.
  • 승인: Node 호스트에서 ~/.openclaw/exec-approvals.json을 통해 적용됩니다.

승인 참고:

  • 승인 기반 Node 실행은 정확한 요청 컨텍스트에 바인딩됩니다.
  • 직접 shell/runtime 파일 실행의 경우 OpenClaw는 또한 하나의 구체적인 로컬 파일 피연산자를 최선으로 바인딩하고, 실행 전에 해당 파일이 변경되면 실행을 거부합니다.
  • OpenClaw가 interpreter/runtime 명령에 대해 정확히 하나의 구체적인 로컬 파일을 식별할 수 없으면 전체 runtime 범위를 가장하는 대신 승인 기반 실행이 거부됩니다. 더 넓은 interpreter 의미론에는 sandboxing, 별도 호스트, 또는 명시적인 신뢰 allowlist/전체 워크플로를 사용하세요.

Node 호스트 시작(포그라운드)

Node 머신에서:

openclaw node run --host <gateway-host> --port 18789 --display-name "Build Node"

SSH 터널을 통한 원격 Gateway(loopback 바인드)

Gateway가 loopback(gateway.bind=loopback, 로컬 모드의 기본값)에 바인딩하면 원격 Node 호스트는 직접 연결할 수 없습니다. SSH 터널을 만들고 Node 호스트가 터널의 로컬 끝을 가리키게 하세요.

예시(Node 호스트 -> Gateway 호스트):

# Terminal A (keep running): forward local 18790 -> gateway 127.0.0.1:18789
ssh -N -L 18790:127.0.0.1:18789 user@gateway-host

# Terminal B: export the gateway token and connect through the tunnel
export OPENCLAW_GATEWAY_TOKEN="<gateway-token>"
openclaw node run --host 127.0.0.1 --port 18790 --display-name "Build Node"

참고:

  • openclaw node run은 토큰 또는 비밀번호 인증을 지원합니다.
  • 환경 변수가 권장됩니다: OPENCLAW_GATEWAY_TOKEN / OPENCLAW_GATEWAY_PASSWORD.
  • 구성 fallback은 gateway.auth.token / gateway.auth.password입니다.
  • 로컬 모드에서 Node 호스트는 의도적으로 gateway.remote.token / gateway.remote.password를 무시합니다.
  • 원격 모드에서는 원격 우선순위 규칙에 따라 gateway.remote.token / gateway.remote.password를 사용할 수 있습니다.
  • 활성 로컬 gateway.auth.* SecretRefs가 구성되어 있지만 해결되지 않으면 Node 호스트 인증은 닫힌 상태로 실패합니다.
  • Node 호스트 인증 해석은 OPENCLAW_GATEWAY_* 환경 변수만 존중합니다.

Node 호스트 시작(서비스)

openclaw node install --host <gateway-host> --port 18789 --display-name "Build Node"
openclaw node start
openclaw node restart

페어링 + 이름 지정

Gateway 호스트에서:

openclaw devices list
openclaw devices approve <requestId>
openclaw nodes status

Node가 변경된 인증 세부 정보로 재시도하면 openclaw devices list를 다시 실행하고 현재 requestId를 승인하세요.

이름 지정 옵션:

  • openclaw node run / openclaw node install--display-name(Node의 ~/.openclaw/node.json에 지속됨).
  • openclaw nodes rename --node <id|name|ip> --name "Build Node"(Gateway 재정의).

명령 allowlist 설정

Exec 승인은 Node 호스트별입니다. Gateway에서 allowlist 항목을 추가하세요.

openclaw approvals allowlist add --node <id|name|ip> "/usr/bin/uname"
openclaw approvals allowlist add --node <id|name|ip> "/usr/bin/sw_vers"

승인은 Node 호스트의 ~/.openclaw/exec-approvals.json에 저장됩니다.

exec를 Node로 지정

기본값 구성(Gateway 구성):

openclaw config set tools.exec.host node
openclaw config set tools.exec.security allowlist
openclaw config set tools.exec.node "<id-or-name>"

또는 세션별로:

/exec host=node security=allowlist node=<id-or-name>

설정되면 host=node를 사용하는 모든 exec 호출은 Node 호스트에서 실행됩니다(해당 Node allowlist/승인의 적용을 받음).

host=auto는 자체적으로 Node를 암시적으로 선택하지 않지만, auto에서 명시적인 호출별 host=node 요청은 허용됩니다. 세션에서 Node exec를 기본값으로 사용하려면 tools.exec.host=node 또는 /exec host=node ...를 명시적으로 설정하세요.

관련 항목:

명령 호출

저수준(raw RPC):

openclaw nodes invoke --node <idOrNameOrIp> --command canvas.eval --params '{"javaScript":"location.href"}'

일반적인 "agent에 MEDIA 첨부 파일 제공" 워크플로에는 더 높은 수준의 헬퍼가 있습니다.

명령 정책

Node 명령은 호출되기 전에 두 가지 게이트를 통과해야 합니다.

  1. Node가 WebSocket connect.commands 목록에 해당 명령을 선언해야 합니다.
  2. Gateway의 플랫폼 정책이 선언된 명령을 허용해야 합니다.

Windows 및 macOS 동반 Node는 기본적으로 canvas.*, camera.list, location.get, screen.snapshot 같은 안전하게 선언된 명령을 허용합니다. talk capability를 광고하거나 talk.* 명령을 선언하는 신뢰된 Node도 플랫폼 레이블과 무관하게 선언된 push-to-talk 명령(talk.ptt.start, talk.ptt.stop, talk.ptt.cancel, talk.ptt.once)을 기본적으로 허용합니다. camera.snap, camera.clip, screen.record처럼 위험하거나 개인정보 영향이 큰 명령은 여전히 gateway.nodes.allowCommands로 명시적인 opt-in이 필요합니다. gateway.nodes.denyCommands는 항상 기본값과 추가 allowlist 항목보다 우선합니다.

Plugin 소유 Node 명령은 Gateway node-invoke 정책을 추가할 수 있습니다. 그 정책은 allowlist 검사 이후, Node로 전달하기 전에 실행되므로 raw node.invoke, CLI 헬퍼, 전용 agent 도구가 동일한 Plugin 권한 경계를 공유합니다. 위험한 Plugin Node 명령에는 여전히 명시적인 gateway.nodes.allowCommands opt-in이 필요합니다.

Node가 선언한 명령 목록을 변경한 뒤에는 이전 장치 페어링을 거부하고 새 요청을 승인하여 Gateway가 업데이트된 명령 스냅샷을 저장하게 하세요.

스크린샷(canvas 스냅샷)

Node가 Canvas(WebView)를 표시 중이면 canvas.snapshot{ format, base64 }를 반환합니다.

CLI 헬퍼(임시 파일에 쓰고 MEDIA:<path> 출력):

openclaw nodes canvas snapshot --node <idOrNameOrIp> --format png
openclaw nodes canvas snapshot --node <idOrNameOrIp> --format jpg --max-width 1200 --quality 0.9

Canvas 컨트롤

openclaw nodes canvas present --node <idOrNameOrIp> --target https://example.com
openclaw nodes canvas hide --node <idOrNameOrIp>
openclaw nodes canvas navigate https://example.com --node <idOrNameOrIp>
openclaw nodes canvas eval --node <idOrNameOrIp> --js "document.title"

참고:

  • canvas present는 URL 또는 로컬 파일 경로(--target)와, 선택적 위치 지정을 위한 --x/--y/--width/--height를 받습니다.
  • canvas eval은 인라인 JS(--js) 또는 위치 인자를 받습니다.

A2UI(Canvas)

openclaw nodes canvas a2ui push --node <idOrNameOrIp> --text "Hello"
openclaw nodes canvas a2ui push --node <idOrNameOrIp> --jsonl ./payload.jsonl
openclaw nodes canvas a2ui reset --node <idOrNameOrIp>

참고:

  • A2UI v0.8 JSONL만 지원됩니다(v0.9/createSurface는 거부됨).

사진 + 동영상(Node 카메라)

사진(jpg):

openclaw nodes camera list --node <idOrNameOrIp>
openclaw nodes camera snap --node <idOrNameOrIp>            # default: both facings (2 MEDIA lines)
openclaw nodes camera snap --node <idOrNameOrIp> --facing front

동영상 클립(mp4):

openclaw nodes camera clip --node <idOrNameOrIp> --duration 10s
openclaw nodes camera clip --node <idOrNameOrIp> --duration 3000 --no-audio

참고:

  • canvas.*camera.*에는 Node가 foregrounded 상태여야 합니다(백그라운드 호출은 NODE_BACKGROUND_UNAVAILABLE을 반환).
  • 너무 큰 base64 payload를 피하기 위해 클립 길이는 제한됩니다(현재 <= 60s).
  • Android는 가능할 때 CAMERA/RECORD_AUDIO 권한을 요청합니다. 거부된 권한은 *_PERMISSION_REQUIRED로 실패합니다.

화면 녹화(Node)

지원되는 Node는 screen.record(mp4)를 노출합니다. 예시:

openclaw nodes screen record --node <idOrNameOrIp> --duration 10s --fps 10
openclaw nodes screen record --node <idOrNameOrIp> --duration 10s --fps 10 --no-audio

참고:

  • screen.record 사용 가능 여부는 Node 플랫폼에 따라 다릅니다.
  • 화면 녹화는 <= 60s로 제한됩니다.
  • --no-audio는 지원되는 플랫폼에서 마이크 캡처를 비활성화합니다.
  • 여러 화면을 사용할 수 있을 때 디스플레이를 선택하려면 --screen <index>를 사용하세요.

위치(Node)

Node는 설정에서 위치가 활성화된 경우 location.get을 노출합니다.

CLI 헬퍼:

openclaw nodes location get --node <idOrNameOrIp>
openclaw nodes location get --node <idOrNameOrIp> --accuracy precise --max-age 15000 --location-timeout 10000

참고:

  • 위치는 기본적으로 꺼져 있습니다.
  • "항상"은 시스템 권한이 필요하며, 백그라운드 fetch는 최선으로 수행됩니다.
  • 응답에는 lat/lon, 정확도(미터), 타임스탬프가 포함됩니다.

SMS(Android Node)

Android Node는 사용자가 SMS 권한을 부여하고 장치가 전화 기능을 지원하는 경우 sms.send를 노출할 수 있습니다.

저수준 invoke:

openclaw nodes invoke --node <idOrNameOrIp> --command sms.send --params '{"to":"+15555550123","message":"Hello from OpenClaw"}'

참고:

  • capability가 광고되기 전에 Android 장치에서 권한 프롬프트를 수락해야 합니다.
  • 전화 기능이 없는 Wi-Fi 전용 장치는 sms.send를 광고하지 않습니다.

Android 장치 + 개인 데이터 명령

Android Node는 해당 capability가 활성화된 경우 추가 명령 제품군을 광고할 수 있습니다.

사용 가능한 제품군:

  • device.status, device.info, device.permissions, device.health
  • notifications.list, notifications.actions
  • photos.latest
  • contacts.search, contacts.add
  • calendar.events, calendar.add
  • callLog.search
  • sms.search
  • motion.activity, motion.pedometer

호출 예시:

openclaw nodes invoke --node <idOrNameOrIp> --command device.status --params '{}'
openclaw nodes invoke --node <idOrNameOrIp> --command notifications.list --params '{}'
openclaw nodes invoke --node <idOrNameOrIp> --command photos.latest --params '{"limit":1}'

참고:

  • Motion 명령은 사용 가능한 센서에 따라 기능으로 제한됩니다.

시스템 명령(Node 호스트 / Mac Node)

macOS Node는 system.run, system.notify, system.execApprovals.get/set을 노출합니다. 헤드리스 Node 호스트는 system.run, system.which, system.execApprovals.get/set을 노출합니다.

예시:

openclaw nodes notify --node <idOrNameOrIp> --title "Ping" --body "Gateway ready"
openclaw nodes invoke --node <idOrNameOrIp> --command system.which --params '{"name":"git"}'

참고:

  • system.run은 페이로드에 stdout/stderr/종료 코드를 반환합니다.
  • 셸 실행은 이제 host=node와 함께 exec 도구를 통해 수행됩니다. nodes는 명시적 Node 명령을 위한 직접 RPC 표면으로 남아 있습니다.
  • nodes invokesystem.run 또는 system.run.prepare를 노출하지 않습니다. 이들은 exec 경로에만 유지됩니다.
  • exec 경로는 승인 전에 표준 systemRunPlan을 준비합니다. 승인이 부여되면 Gateway는 이후 호출자가 편집한 command/cwd/session 필드가 아니라 저장된 해당 계획을 전달합니다.
  • system.notify는 macOS 앱의 알림 권한 상태를 따릅니다.
  • 인식되지 않는 Node platform / deviceFamily 메타데이터는 system.runsystem.which를 제외하는 보수적인 기본 허용 목록을 사용합니다. 알 수 없는 플랫폼에서 해당 명령이 의도적으로 필요하다면 gateway.nodes.allowCommands를 통해 명시적으로 추가하세요.
  • system.run--cwd, --env KEY=VAL, --command-timeout, --needs-screen-recording을 지원합니다.
  • 셸 래퍼(bash|sh|zsh ... -c/-lc)의 경우 요청 범위 --env 값은 명시적 허용 목록(TERM, LANG, LC_*, COLORTERM, NO_COLOR, FORCE_COLOR)으로 축소됩니다.
  • 허용 목록 모드에서 항상 허용 결정의 경우, 알려진 디스패치 래퍼(env, nice, nohup, stdbuf, timeout)는 래퍼 경로 대신 내부 실행 파일 경로를 유지합니다. 안전하게 래핑을 해제할 수 없으면 허용 목록 항목이 자동으로 유지되지 않습니다.
  • 허용 목록 모드의 Windows Node 호스트에서는 cmd.exe /c를 통한 셸 래퍼 실행에 승인이 필요합니다(허용 목록 항목만으로는 래퍼 형식이 자동 허용되지 않습니다).
  • system.notify--priority <passive|active|timeSensitive>--delivery <system|overlay|auto>를 지원합니다.
  • Node 호스트는 PATH 재정의를 무시하고 위험한 시작/셸 키(DYLD_*, LD_*, NODE_OPTIONS, PYTHON*, PERL*, RUBYOPT, SHELLOPTS, PS4)를 제거합니다. 추가 PATH 항목이 필요하면 --env를 통해 PATH를 전달하지 말고 Node 호스트 서비스 환경을 구성하거나 표준 위치에 도구를 설치하세요.
  • macOS Node 모드에서 system.run은 macOS 앱의 exec 승인(Settings → Exec approvals)으로 제한됩니다. ask/allowlist/full은 헤드리스 Node 호스트와 동일하게 동작하며, 거부된 프롬프트는 SYSTEM_RUN_DENIED를 반환합니다.
  • 헤드리스 Node 호스트에서 system.run은 exec 승인(~/.openclaw/exec-approvals.json)으로 제한됩니다.

Exec Node 바인딩

여러 Node를 사용할 수 있을 때 exec를 특정 Node에 바인딩할 수 있습니다. 이는 exec host=node의 기본 Node를 설정합니다(에이전트별로 재정의할 수 있음).

전역 기본값:

openclaw config set tools.exec.node "node-id-or-name"

에이전트별 재정의:

openclaw config get agents.list
openclaw config set agents.list[0].tools.exec.node "node-id-or-name"

모든 Node를 허용하도록 설정 해제:

openclaw config unset tools.exec.node
openclaw config unset agents.list[0].tools.exec.node

권한 맵

Node는 권한 이름(예: screenRecording, accessibility)을 키로 하고 boolean 값(true = 허용됨)을 갖는 permissions 맵을 node.list / node.describe에 포함할 수 있습니다.

헤드리스 Node 호스트(크로스 플랫폼)

OpenClaw는 Gateway WebSocket에 연결하고 system.run / system.which를 노출하는 헤드리스 Node 호스트(UI 없음)를 실행할 수 있습니다. 이는 Linux/Windows에서 또는 서버와 함께 최소 Node를 실행할 때 유용합니다.

시작:

openclaw node run --host <gateway-host> --port 18789

참고:

  • 페어링은 여전히 필요합니다(Gateway가 디바이스 페어링 프롬프트를 표시함).
  • Node 호스트는 Node ID, 토큰, 표시 이름, Gateway 연결 정보를 ~/.openclaw/node.json에 저장합니다.
  • Exec 승인은 ~/.openclaw/exec-approvals.json을 통해 로컬에서 적용됩니다 (Exec 승인 참조).
  • macOS에서 헤드리스 Node 호스트는 기본적으로 system.run을 로컬에서 실행합니다. system.run을 동반 앱 exec 호스트를 통해 라우팅하려면 OPENCLAW_NODE_EXEC_HOST=app을 설정하세요. 앱 호스트를 필수로 사용하고 사용할 수 없을 때 닫힌 상태로 실패하게 하려면 OPENCLAW_NODE_EXEC_FALLBACK=0을 추가하세요.
  • Gateway WS가 TLS를 사용하는 경우 --tls / --tls-fingerprint를 추가하세요.

Mac Node 모드

  • macOS 메뉴 막대 앱은 Node로 Gateway WS 서버에 연결합니다(따라서 openclaw nodes …가 이 Mac을 대상으로 동작함).
  • 원격 모드에서 앱은 Gateway 포트에 대한 SSH 터널을 열고 localhost에 연결합니다.