9. Edge Node API (사용자 접점 통신 규약)
본 장은 사용자가 원격지에서 UI(웹 대시보드, 모바일 앱, 챗봇 게이트웨이 등)를 통해 마스터 서버(Master Server)에 접속하여 로컬 클라이언트(Local Client)를 제어하기 위한 Northbound API를 정의한다.
아키텍처 정의 (3-Tier):
[Edge Node (User UI)] ↔ (Edge API) ↔ [Master Server] ↔ (RAWP/Southbound) ↔ [Local Client]
9.1. Edge Node 인증 및 권한 (Authentication)
엣지 노드는 마스터 서버의 로컬 클라이언트 인증 방식(Pairing Token)과 분리된 사용자 단위의 인증 체계(예: OIDC 기반 JWT)를 사용해야 한다. 모든 Edge API 요청은 Authorization: Bearer {user_access_token} 헤더를 포함해야 한다 (MUST).
9.2. 로컬 머신(Node) 풀 관리 및 상태 모니터링
사용자 계정에 바인딩된 로컬 클라이언트 목록과 현재 상태를 조회한다.
9.2.1. 연결된 노드 목록 조회
Endpoint: GET /v1/edge/nodes
Response (200 OK):
{
"nodes": [
{
"node_id": "String (필수, 클라이언트 식별자)",
"device_name": "String (필수, 등록 시 제공된 이름)",
"status": "String (필수, 'online' | 'busy' | 'offline')",
"last_seen": "String (필수, ISO 8601, 마스터 서버와 마지막 통신 시각)",
"capabilities": [
"String (선택, 로컬 머신이 지원하는 기능 목록. §4.1.6에서 동기화된 최신 값 반영)"
],
"active_sessions_count": "Number (필수)",
"config_versions": {
"limits": "Number (선택, 현재 보유 중인 Resource Limits config_version)",
"capabilities": "Number (선택, 현재 보유 중인 Capabilities config_version)"
}
}
]
}
변경 사항:
capabilities필드는 §4.1.6을 통해 동기화된 최신 값을 반영한다.config_versions객체가 추가되어 각 Config Scope의 현재 버전을 엣지 노드에서 조회할 수 있다.
9.2.2. 로컬 머신별 사용량 및 지표 (Metrics)
해당 노드에서 발생한 세션들의 누적/실시간 사용량을 조회한다.
Endpoint: GET /v1/edge/nodes/{node_id}/metrics
Query Parameters: ?period=today (선택, 'today', 'week', 'month')
Response (200 OK):
{
"node_id": "String (필수)",
"period": "String (필수)",
"aggregated_usage": {
"total_input_tokens": "Number",
"total_output_tokens": "Number",
"estimated_cost": "Number (USD 기준)",
"total_tool_invocations": "Number"
},
"health": {
"uptime_seconds": "Number",
"last_error": "String (선택, 최근 발생한 치명적 에러)"
}
}
9.2.3. 노드 설정 조회 (Node Configuration Lookup)
엣지 노드가 특정 로컬 머신의 현재 설정 상태를 조회한다.
Endpoint: GET /v1/edge/nodes/{node_id}/config
Response (200 OK):
{
"node_id": "String (필수)",
"limits": {
"config_version": "Number (필수)",
"effective_at": "String (필수, ISO 8601)",
"limits": {
"rate_limit": "Number",
"max_frame_size": "Number",
"reattach_window": "Number",
"max_buffer_size": "Number",
"buffer_overflow_policy": "String"
}
},
"capabilities": {
"config_version": "Number (필수)",
"effective_at": "String (필수, ISO 8601)",
"capabilities": ["String"]
}
}
이 엔드포인트는 Pull 방식으로 최신 설정을 확인하기 위한 것이다. 실시간 Push 알림은 §9.4.4를 참조한다.
9.3. 엣지 세션(Edge Session) 라이프사이클 관리
엣지 노드는 마스터 서버를 통해 특정 로컬 머신에 새로운 세션을 생성하거나 기존 세션을 조회할 수 있다.
9.3.1. 원격 세션 생성 (Edge → Master)
사용자가 특정 로컬 머신을 선택하여 대화를 시작할 때 호출한다.
Endpoint: POST /v1/edge/nodes/{node_id}/sessions
Request:
{
"agent_name": "String (필수, 실행할 에이전트)",
"workspace_path": "String (선택, 작업 디렉토리)"
}
Response (201 Created):
{
"session_id": "String (필수, UUID v4)",
"edge_ws_ticket": "String (필수, 엣지용 WSS 연결 티켓. 1회용)",
"status": "String (필수, 'INIT' | 'RUNNING')",
"pinned_config_versions": {
"limits": "Number (필수, 이 세션에 바인딩된 Resource Limits config_version)",
"capabilities": "Number (필수, 이 세션에 바인딩된 Capabilities config_version)"
}
}
변경 사항:
pinned_config_versions객체가 추가되어, 이 세션에 바인딩된 설정 버전을 엣지 노드가 확인할 수 있다. §4.1.8의 Session-Pinned Config 참조.
동작 원리: 이 요청을 받은 마스터 서버는 즉시 대상 로컬 머신의 POST /v1/session/init (본 스펙 §5.1)을 호출하여 로컬 세션을 확보한 뒤 응답해야 한다.
9.3.2. 활성 세션 목록 조회
사용자 계정에 귀속된 모든 세션의 현재 상태를 조회한다.
Endpoint: GET /v1/edge/sessions
Query Parameters:
| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
status |
String | 선택 | 세션 상태 필터. 'INIT', 'RUNNING', 'DETACHED' 중 하나. 미지정 시 모든 상태의 세션을 반환. |
node_id |
String | 선택 | 특정 노드에 귀속된 세션만 필터링. |
Response (200 OK):
{
"sessions": [
{
"session_id": "String (필수, UUID v4)",
"node_id": "String (필수, 세션이 실행 중인 로컬 클라이언트 식별자)",
"agent_name": "String (필수, 실행 중인 에이전트 이름)",
"status": "String (필수, 'INIT' | 'RUNNING' | 'DETACHED')",
"created_at": "String (필수, ISO 8601, 세션 생성 시각)",
"last_activity_at": "String (필수, ISO 8601, 마지막 이벤트 수신 시각)",
"pinned_config_versions": {
"limits": "Number (필수, 이 세션에 바인딩된 Resource Limits config_version)",
"capabilities": "Number (필수, 이 세션에 바인딩된 Capabilities config_version)"
}
}
]
}
pinned_config_versions를 통해 엣지 노드는 각 세션이 어떤 시점의 설정으로 동작 중인지를 목록 수준에서 확인할 수 있다. 노드의 현재 config_versions(§9.2.1)와 비교하면, 세션이 최신 설정인지 이전 설정인지를 즉시 판별할 수 있다. TERMINATED 상태의 세션은 이미 종료되었으므로 목록에 포함하지 않는다 (MUST NOT). 종료된 세션의 이력 조회가 필요한 경우 별도의 세션 이력 API를 통해 제공한다.
9.4. 엣지 데이터 평면 (Edge WebSocket 통신)
엣지 노드는 발급받은 티켓을 사용하여 마스터 서버와 WSS를 연결하며, 마스터 서버는 이 연결을 대상 로컬 머신과 투명하게 중계(Transparent Proxy)한다.
Connection URI: wss://{master_host}/v1/edge/ws/stream?ticket={edge_ws_ticket}&session_id={session_id}
9.4.1. 프로토콜 투명성 (Protocol Transparency)
엣지 노드와 마스터 서버 간의 WSS 통신은 RAWP-DPS 1.0 규격을 완전히 동일하게 사용한다 (MUST).
엣지 노드는 본 스펙 §6의 control.* 이벤트(사용자 프롬프트, 인터랙션 응답 등)를 마스터 서버로 발송하며, 마스터는 이를 로컬 머신으로 포워딩한다.
엣지 노드는 로컬 머신이 발송한 agent.*, tool.*, session.* 이벤트를 마스터 서버를 통해 수신하여 사용자 UI에 렌더링한다.
9.4.2. 마스터 서버의 중계 및 개입 규칙
마스터 서버는 단순한 파이프 역할을 넘어 다음의 제어 책임을 가진다:
라우팅: 엣지 노드의 발신 프레임을 올바른 로컬 머신의 소켓으로 전달.
사용량 집계: 중계되는 session.usage 이벤트를 인터셉트하여 데이터베이스에 누적 저장 (§9.2.2 지표 제공용).
파일 검색 중계: control.file.search, control.file.search.cancel, session.file.candidates 이벤트는 중계 대상에 포함된다. session.file.candidates는 session.usage와 달리 인터셉트 없이 단순 포워딩 대상이다.
보안 필터링: 엣지 노드가 허가되지 않은 control.prompt.request 내장 도구(e.g., 로컬 시스템 파괴성 명령어)를 전송하려 할 경우, 마스터 서버 단에서 프레임을 드롭하고 엣지 노드에 session.error를 반환해야 한다 (MUST).
9.4.3. 다중 접점 동기화 (Multi-device Synchronization)
동일한 session_id에 대해 여러 엣지 노드(예: 모바일 앱과 데스크톱 브라우저 동시 접속)가 연결을 요청할 경우, 마스터 서버는 수신되는 RAWP-DPS 1.0 프레임을 모든 연결된 엣지 소켓으로 브로드캐스트(Fan-out)하여 UI 상태를 동기화해야 한다 (SHOULD). 단, control.* 이벤트 발송 시 동시성 충돌을 막기 위해 message_id 기반 멱등성 처리를 수행해야 한다.
9.4.4. 노드 설정 변경 Push 알림 (Node Config Change Notification)
로컬 클라이언트가 §4.1.5 또는 §4.1.6을 통해 설정을 갱신하면, 마스터 서버는 해당 노드에 연결된 모든 활성 엣지 WSS 소켓에 설정 변경 알림 프레임을 전송해야 한다 (MUST). 이 알림을 통해 엣지 노드는 UI에 반영할 설정 변경(예: capabilities 변경으로 인한 기능 목록 갱신)을 실시간으로 인지할 수 있다.
알림 프레임 구조:
이 알림은 RAWP-DPS 1.0의 Envelope 구조(RAWP-DPS §2)를 따르되, 세션 단위가 아닌 노드 단위의 이벤트이므로 session_id와 turn_id를 포함하지 않는다. 마스터 서버가 자체적으로 생성하여 발송하는 프레임이다.
{
"v": "rawp-dps-1.0",
"type": "node.config.changed",
"message_id": "String (필수, UUID v4)",
"timestamp": "String (필수, ISO 8601)",
"payload": {
"node_id": "String (필수, 설정이 변경된 노드의 식별자)",
"changed_scope": "String (필수, 'limits' | 'capabilities')",
"config_version": "Number (필수, 갱신된 스코프의 새 config_version)",
"reason": "String (선택, 클라이언트가 갱신 요청 시 전달한 reason 값 전파)"
}
}
엣지 노드의 처리 규칙:
node.config.changed수신 시, 엣지 노드는changed_scope에 따라 관련된 로컬 캐시를 무효화해야 한다 (MUST).- 상세 설정 값이 필요하면 §9.2.3의
GET /v1/edge/nodes/{node_id}/config을 Pull 호출하여 최신 값을 획득한다. 알림 프레임 자체에는 변경된 설정의 전체 값을 포함하지 않는다. 이는 알림 프레임의 크기를 최소화하고, 엣지 노드가 필요한 시점에만 상세 데이터를 가져오도록 하기 위함이다. changed_scope: "capabilities"수신 시, 엣지 UI가 기능 목록이나 에이전트 지원 기능 표시를 동적으로 갱신하는 경우, Pull 호출 후 UI를 갱신해야 한다 (SHOULD).- 활성 세션에는 §4.1.8에 따라 이전 설정이 유지되므로, 현재 진행 중인 세션의 동작을 변경할 필요는 없다.
전송 범위: 마스터 서버는 해당 노드(node_id)에 연결된 모든 엣지 WSS 소켓에 알림을 브로드캐스트한다. 특정 세션의 WSS가 아닌, 해당 노드와 관련된 모든 엣지 연결이 대상이다. 세션 WSS가 아직 연결되지 않았더라도, 해당 노드에 대해 다른 세션의 WSS가 활성 상태이면 해당 소켓을 통해 알림이 전달된다.