실시간: WebSocket, SSE, 라이브 캔버스
전체 실시간 인터페이스: WS 채팅 프로토콜, 터미널, 라이브 캔버스(A2UI), 노드, SSE 이벤트/로그 스트림.
Revka 게이트웨이는 모든 인터랙티브·서버 푸시 상호작용을 두 가지 실시간 전송 방식으로 처리합니다. WebSocket은 양방향 세션에, Server-Sent Events(SSE)는 단방향 브로드캐스트 스트림에 사용됩니다. 이 페이지는 /ws/chat 에이전트 프로토콜과 오류 코드, PTY 터미널, 라이브 캔버스(A2UI) 시스템, 동적 노드 레지스트리, 대시보드 라이브 뷰에 데이터를 공급하는 두 SSE 스트림에 대한 상세 참조 문서입니다.
커스텀 클라이언트, 외부 통합, 또는 게이트웨이와 실시간으로 통신하는 엣지 디바이스를 구축하는 경우 이 문서를 참고하세요. 전송 방식 개요 및 REST와의 관계는 게이트웨이 API 개요를 참조하세요. 베어러 토큰 발급 방법은 페어링 및 인증을 참조하세요.
WebSocket 인증
섹션 제목: “WebSocket 인증”모든 /ws/* 엔드포인트는 페어링이 활성화된 경우 베어러 토큰을 요구합니다. 브라우저는 new WebSocket()에서 Authorization 헤더를 설정할 수 없으므로, 게이트웨이는 다음 세 가지 소스에서 우선순위 순서로 토큰을 추출합니다.
Authorization: Bearer <token>헤더 — 비브라우저 클라이언트용Sec-WebSocket-Protocol: bearer.<token>서브프로토콜 — 브라우저 호환?token=<token>쿼리 파라미터 — 브라우저 호환 폴백
// Browser: pass the token as a subprotocol alongside the channel subprotocol.const ws = new WebSocket( "wss://host:port/ws/chat?session_id=" + sessionId, ["revka.v1", "bearer." + token],);WebSocket 에이전트 채팅 (/ws/chat)
섹션 제목: “WebSocket 에이전트 채팅 (/ws/chat)”Revka 에이전트와 클라이언트 간의 양방향 세션인 주요 인터랙티브 채널입니다. 세션 재개, 진행 중 스티어링, 중단, 파일 첨부, 페이지 컨텍스트 힌트, 스트리밍 출력을 지원합니다.
ws://host:port/ws/chat?session_id=<uuid>&name=My+Session&token=<bearer>서브프로토콜: revka.v1
연결 쿼리 파라미터
섹션 제목: “연결 쿼리 파라미터”| 파라미터 | 필수 여부 | 설명 |
|---|---|---|
session_id | 아니오 | 재개할 기존 세션의 UUID. 생략하면 새 세션을 생성합니다. |
name | 아니오 | 세션 백엔드에 저장되는 사람이 읽을 수 있는 레이블. |
token | 아니오 | 베어러 토큰(우선순위 참조 — 헤더 및 서브프로토콜이 우선합니다). |
업그레이드 후 서버는 첫 번째 메시지로 session_start 프레임을 전송합니다. 메시지를 전송하지 않으면 5초 핸드셰이크 타임아웃 후 연결은 수신 전용 브로드캐스트 릴레이가 됩니다 — agent_event 프레임만 관찰하려는 워크플로우 뷰어에 유용합니다.
클라이언트 → 서버 프레임
섹션 제목: “클라이언트 → 서버 프레임”| 프레임 | 필드 | 목적 |
|---|---|---|
{"type":"connect", ...} | session_id?, device_name?, capabilities? | 첫 번째 프레임의 선택적 핸드셰이크; 서버가 connected로 응답합니다. |
{"type":"message","content":"..."} | content (필수), page_context?, attachments? | 에이전트에 채팅 메시지를 전송합니다. |
{"type":"steer","content":"..."} | content (필수) | 진행 중 스티어링 메모를 삽입합니다. |
{"type":"stop"} | — | 현재 진행 중인 턴을 취소합니다. |
{ "type": "message", "content": "Summarize the open PRs", "page_context": "workflows", "attachments": ["a1b2c3d4-...", "e5f6a7b8-..."]}서버 → 클라이언트 프레임
섹션 제목: “서버 → 클라이언트 프레임”| 프레임 | 필드 | 의미 |
|---|---|---|
{"type":"session_start", ...} | session_id, resumed, message_count, name | 업그레이드 후 첫 번째 프레임. |
{"type":"connected","message":"..."} | message | connect 핸드셰이크 프레임의 응답. |
{"type":"chunk","content":"..."} | content | LLM의 스트리밍 텍스트 델타. |
{"type":"thinking","content":"..."} | content | 확장 사고 델타(thinking이 활성화된 경우). |
{"type":"tool_call","name":"...","args":{}} | name, args | 도구 호출 알림. |
{"type":"tool_result","name":"...","output":"..."} | name, output | 도구 실행 결과. |
{"type":"operator_status","phase":"...","detail":"..."} | phase, detail | 오퍼레이터 라이프사이클 상태(예: queued, steering). |
{"type":"agent_event","event":{}} | event | 오퍼레이터로부터 릴레이된 브로드캐스트 이벤트. |
{"type":"chunk_reset"} | — | done 프레임 도착 전에 누적된 초안을 지웁니다. |
{"type":"done","full_response":"..."} | full_response | 이번 턴의 완전한 응답. |
{"type":"stopped","message":"..."} | message | stop 프레임으로 턴이 취소되었습니다. |
{"type":"error","message":"...","code":"..."} | message, code | 오류가 발생했습니다(아래 코드 참조). |
오류 코드
섹션 제목: “오류 코드”error 프레임의 code 필드는 다음 중 하나입니다.
| 코드 | 원인 |
|---|---|
INVALID_JSON | 프레임이 유효한 JSON이 아닙니다. |
EMPTY_CONTENT | message 프레임에 content가 없습니다. |
SESSION_BUSY | 세션별 큐가 가득 찼습니다 — 이미 진행 중인 턴이 있습니다(직렬화 참조). |
AGENT_INIT_FAILED | 이번 턴에서 에이전트를 초기화할 수 없었습니다. |
AUTH_ERROR | 인증에 실패했습니다. |
PROVIDER_ERROR | 업스트림 LLM 프로바이더가 오류를 반환했습니다. |
AGENT_ERROR | 에이전트가 턴 도중 오류를 발생시켰습니다. |
NO_ACTIVE_TURN | 진행 중인 턴 없이 steer가 전송되었습니다. |
UNKNOWN_MESSAGE_TYPE | 프레임의 type을 인식할 수 없습니다. |
스티어링과 중단
섹션 제목: “스티어링과 중단”턴 진행 중에 {"type":"steer","content":"..."} 를 전송하면 가이던스를 삽입할 수 있습니다. 해당 메모는 다음 오퍼레이터 경계에서 적용되며 즉시 반영되지 않습니다 — 도구 호출 도중 스티어를 전송하면 해당 호출이 완료된 후에 적용됩니다. 이는 의도된 동작입니다. 턴이 거의 끝날 무렵에 전송된 스티어는 done 이전에 적용되지 않을 수 있습니다.
{"type":"stop"} 을 전송하면 진행 중인 턴을 취소하며, 서버는 stopped 프레임으로 응답합니다. 진행 중인 턴이 없을 때 stop을 전송하면 stopped 프레임이 반환됩니다(메시지: ‘No active Operator turn to stop.’). 진행 중인 턴 없이 steer를 전송하면 코드 NO_ACTIVE_TURN의 error가 반환됩니다.
첨부 파일
섹션 제목: “첨부 파일”먼저 POST /api/sessions/{session_id}/attachments(멀티파트, 파일당 25 MiB)를 통해 파일을 업로드하면 file_id가 반환됩니다. 그런 다음 message 프레임의 attachments 배열에서 해당 ID를 참조하세요. 게이트웨이는 각 ID를 에이전트가 인식하는 콘텐츠 마커로 변환합니다. 이미지는 비전 지원 프로바이더를 위해 [IMAGE:/path] 마커가 되고, 텍스트 파일은 최대 200,000자까지 인라인으로 처리되며 초과분에는 잘림 마커가 표시됩니다.
페이지 컨텍스트 힌트
섹션 제목: “페이지 컨텍스트 힌트”message 프레임의 선택적 page_context 필드는 대시보드 페이지에 특화된 LLM 지침으로 전환합니다. 허용되는 값은 agent_pool, agent_teams, skills, workflows, canvas입니다. 예를 들어 canvas 컨텍스트는 에이전트가 텍스트로 설명하는 대신 render_canvas 도구를 호출하도록 지시합니다. (Architect 에디터는 page_context 값 대신 content 내에 <editor-state> 및 <architect-instructions> 같은 XML 블록을 사용합니다.)
세션별 직렬화
섹션 제목: “세션별 직렬화”각 세션은 동시에 하나의 진행 중인 턴만 허용합니다. 동일 세션에 대한 동시 요청은 FIFO 순서로 큐에 들어가며 현재 턴이 완료되면 실행됩니다. 큐가 가득 찬 경우 서버는 코드 SESSION_BUSY의 error를 반환합니다. 직렬화는 SQLite 히스토리 손상을 방지하고 세션 상태의 일관성을 유지합니다.
큐 잠금 타임아웃은 기본값 300초입니다. 웹 검색, 서브에이전트 위임 등의 긴 도구 체인은 일상적으로 30초를 초과하므로, 느린 채팅 턴을 위해서는 요청별 REST 타임아웃이 아닌 이 값을 높이세요.
| 변수 | 기본값 | 설명 |
|---|---|---|
REVKA_GATEWAY_SESSION_LOCK_TIMEOUT_SECS | 300 | 큐에 대기 중인 요청이 세션 잠금을 기다리는 최대 시간(초). |
타임아웃 시 Previous message is still being processed — please wait, or retry once it completes 메시지가 반환됩니다. 세션은 또한 dashboard_<uuid> 메모리 접두사를 사용해 세션별로 Kumiho 메모리를 격리합니다.
WebSocket PTY 터미널 (/ws/terminal)
섹션 제목: “WebSocket PTY 터미널 (/ws/terminal)”portable_pty 기반의 WebSocket PTY 터미널입니다. 사용자의 쉘이나 지정된 AI 코딩 CLI를 PTY 내에서 실행하고 stdio를 양방향으로 브리지합니다. 이는 대시보드의 Code 탭을 구동하며 전체 쉘 접근 권한을 제공합니다 — 권한이 있는 엔드포인트로 취급하세요.
ws://host:port/ws/terminal?token=<bearer>&tool=claude&cwd=/my/project&cols=120&rows=40&mcp_session=<id>&mcp_token=<tok>쿼리 파라미터
섹션 제목: “쿼리 파라미터”| 파라미터 | 기본값 | 설명 |
|---|---|---|
token | — | 베어러 토큰. |
session_id | — | 선택적 세션 레이블. |
tool | (사용자 $SHELL) | 실행할 CLI: claude, codex, opencode, gemini, agy, cursor. 생략하면 사용자 쉘을 사용합니다. |
cwd | — | 작업 디렉터리(틸드 확장 및 유효성 검사 적용). |
mcp_session | — | 자동 주입을 위한 MCP 데몬 세션 ID. |
mcp_token | — | 자동 주입을 위한 MCP 베어러 토큰. |
cols | 80 | PTY 초기 열 수. |
rows | 24 | PTY 초기 행 수. |
와이어 프로토콜
섹션 제목: “와이어 프로토콜”- 클라이언트 → 서버: 텍스트 또는 바이너리 프레임은 PTY stdin으로 파이프되는 원시 키스트로크/바이트 데이터입니다. 크기 조정을 위해서는
{"type":"resize","cols":N,"rows":N}을 전송하세요. - 서버 → 클라이언트: 텍스트 프레임은 UTF-8로 디코딩된 PTY 출력입니다. 실행 실패 시 서버는 빨간색 ANSI 오류 프레임을 전송합니다.
const term = new Terminal(); // xterm.jsconst ws = new WebSocket(url, ["bearer." + token]);ws.binaryType = "arraybuffer";term.onData((d) => ws.send(d)); // keystrokes → PTYws.onmessage = (e) => term.write(typeof e.data === "string" ? e.data : new Uint8Array(e.data)); // PTY output → screenterm.onResize(({ cols, rows }) => ws.send(JSON.stringify({ type: "resize", cols, rows })));MCP 자동 주입
섹션 제목: “MCP 자동 주입”mcp_session과 mcp_token이 제공되면 게이트웨이는 CLI별 MCP 설정을 작성해 실행된 도구가 인프로세스 MCP 서버에 접근할 수 있게 합니다. 각 CLI는 고유한 메커니즘을 사용합니다.
| 도구 | 작성되는 설정 | 메커니즘 |
|---|---|---|
claude | <tmpdir>/.mcp.json | --mcp-config <path> CLI 플래그 |
codex | <tmpdir>/.codex/config.toml | HOME 리디렉션 |
opencode | <tmpdir>/.config/opencode/config.json | HOME + XDG_CONFIG_HOME 리디렉션 |
gemini | <tmpdir>/.gemini/settings.json | HOME 리디렉션 |
agy | <tmpdir>/.gemini/config/mcp_config.json | HOME 리디렉션 |
cursor | <tmpdir>/.cursor/mcp.json | HOME 리디렉션 |
환경 변수 REVKA_MCP_URL, REVKA_MCP_SESSION, REVKA_MCP_TOKEN은 항상 설정됩니다. 도구 분기의 경우 CLI 설정 파일이 격리된 임시 디렉터리를 사용하도록 HOME이 리디렉션되며, WebSocket이 닫힐 때 임시 디렉터리가 삭제됩니다. 쉘은 TERM=xterm-256color 및 COLORTERM=truecolor를 설정하고 사용자 환경의 안전한 하위 집합(PATH, LANG, LC_ALL 등)을 전달합니다.
라이브 캔버스 (A2UI)
섹션 제목: “라이브 캔버스 (A2UI)”라이브 캔버스는 Revka의 A2UI(에이전트-to-UI) 인터페이스입니다. 에이전트가 풍부한 HTML/SVG/마크다운 패널을 렌더링하여 연결된 모든 브라우저 탭에 실시간으로 스트리밍합니다. 에이전트(또는 모든 호출자)가 지정된 이름의 캔버스에 프레임을 푸시하면 모든 WebSocket 구독자가 즉시 수신합니다. 캔버스 상태는 인메모리이며 데몬 재시작 시 유지되지 않습니다.
default라는 기본 캔버스가 있으며, 추가적으로 임의의 수의 명명된 캔버스를 사용할 수 있습니다.
WebSocket 라이브 캔버스 (/ws/canvas/:id)
섹션 제목: “WebSocket 라이브 캔버스 (/ws/canvas/:id)”단일 명명된 캔버스를 구독하고 새 프레임이 푸시될 때마다 수신합니다.
ws://host:port/ws/canvas/<canvas_id>?token=<bearer>연결 시 서버는 현재 스냅샷(있는 경우)을 즉시 전송한 후 connected 프레임을 전송합니다.
서버 → 클라이언트 프레임
섹션 제목: “서버 → 클라이언트 프레임”| 프레임 | 필드 | 의미 |
|---|---|---|
{"type":"frame","canvas_id":"...","frame":{}} | canvas_id, frame | 캔버스에 푸시된 새 콘텐츠. |
{"type":"connected","canvas_id":"..."} | canvas_id | 업그레이드 후 초기 응답. |
{"type":"lagged","canvas_id":"...","missed_frames":N} | canvas_id, missed_frames | 클라이언트가 브로드캐스트 링 버퍼에서 뒤처졌습니다. |
{"type":"error","error":"Maximum canvas count reached"} | error | 레지스트리가 최대 용량에 도달했습니다. |
frame 객체는 frame_id, content_type, content, timestamp를 포함합니다. 대시보드에서 text/html 프레임은 샌드박스 처리된 iframe에서 렌더링됩니다.
라이브 캔버스 REST API
섹션 제목: “라이브 캔버스 REST API”REST 엔드포인트는 캔버스 상태를 관리하고 WebSocket은 업데이트를 스트리밍합니다. 모든 캔버스 엔드포인트는 이름 또는 UUID인 :id를 허용합니다.
| 메서드 | 경로 | 인증 | 목적 |
|---|---|---|---|
GET | /api/canvas | Bearer | 활성 캔버스 ID 목록 → {"canvases":["default", ...]} |
GET | /api/canvas/:id | Bearer | 현재 스냅샷 조회 → {"canvas_id":"...","frame":{}} |
GET | /api/canvas/:id/history | Bearer | 프레임 히스토리 조회 → {"canvas_id":"...","frames":[...]} |
POST | /api/canvas/:id | 루프백: 없음; 외부: bearer | 프레임 푸시. |
DELETE | /api/canvas/:id | 루프백: 없음; 외부: bearer | 캔버스 초기화. |
POST /api/canvas/defaultContent-Type: application/json
{ "content_type": "html", "content": "<h1>Build status</h1><p>Green</p>" }콘텐츠 유형 및 크기 제한
섹션 제목: “콘텐츠 유형 및 크기 제한”content_type 필드는 캔버스 콘텐츠 유형 허용 목록인 html, svg, markdown, text에 대해 유효성을 검사합니다. 임의의 eval 콘텐츠는 설계상 제외됩니다. 설정된 프레임별 최대값을 초과하는 콘텐츠는 HTTP 413을 반환합니다.
| 항목 | 동작 |
|---|---|
허용되는 content_type | html, svg, markdown, text(eval 제외) |
| 크기 초과 콘텐츠 | 413 거부 |
| 레지스트리가 최대 용량 | error 프레임 Maximum canvas count reached; 먼저 미사용 캔버스를 DELETE하세요 |
render_canvas 및 clear_canvas
섹션 제목: “render_canvas 및 clear_canvas”에이전트는 REST를 직접 호출하는 대신 두 가지 오퍼레이터 도구를 통해 라이브 캔버스를 구동합니다.
render_canvas— 지정된 이름의 캔버스에 새 프레임을 푸시합니다(에이전트의POST /api/canvas/:id경로).clear_canvas— 캔버스를 초기화합니다(에이전트의DELETE /api/canvas/:id경로).
채팅 메시지에 page_context: "canvas"가 포함되면 에이전트는 텍스트로 출력을 설명하는 대신 render_canvas를 호출해 출력을 그리도록 지시받습니다. 임베드된 <img> 및 <a> 태그는 HMAC 서명된 워크스페이스 에셋 URL을 통해 워크스페이스 파일을 참조할 수 있으며, 상대 경로이므로 터널을 통해서도 작동합니다.
WebSocket 동적 노드 레지스트리 (/ws/nodes)
섹션 제목: “WebSocket 동적 노드 레지스트리 (/ws/nodes)”외부 프로세스(휴대폰, 센서, IoT 디바이스, 원격 Revka 인스턴스 등)가 WebSocket을 통해 연결하고 기능을 광고합니다. 각 기능은 동적으로 사용 가능한 에이전트 도구가 되며, 게이트웨이는 호출을 올바른 노드로 디스패치합니다. 레지스트리는 순수 인메모리이며 재시작 시 초기화됩니다.
ws://host:port/ws/nodes?token=<bearer>서브프로토콜: revka.nodes.v1
노드 → 게이트웨이 프레임
섹션 제목: “노드 → 게이트웨이 프레임”| 프레임 | 필드 | 목적 |
|---|---|---|
{"type":"register","node_id":"...","capabilities":[...]} | node_id(1~128자), capabilities | 노드와 기능을 등록합니다. |
{"type":"result","call_id":"...","success":true,"output":"...","error":null} | call_id, success, output, error? | 호출 결과를 반환합니다. |
게이트웨이 → 노드 프레임
섹션 제목: “게이트웨이 → 노드 프레임”| 프레임 | 필드 | 목적 |
|---|---|---|
{"type":"invoke","call_id":"...","capability":"...","args":{}} | call_id, capability, args | 노드에 대한 호출 요청. |
{"type":"error","message":"..."} | message | 오류(예: 레지스트리가 최대 용량). |
{ "type": "register", "node_id": "phone-1", "capabilities": [ { "name": "camera.snap", "description": "Take a photo", "parameters": { "type": "object", "properties": {} } }, { "name": "gps.locate", "description": "Read GPS fix", "parameters": { "type": "object", "properties": {} } } ]}각 기능의 parameters는 JSON Schema 객체이며 기본값은 {"type":"object","properties":{}}입니다. 기능은 노드 ID가 접두사로 붙은 도구로 에이전트에 노출됩니다. 동일한 node_id로 재등록하면 업데이트가 적용되며, WebSocket이 닫히면 노드가 등록 해제되고 해당 기능이 사라집니다.
인증: 설정의 노드별 auth_token이 우선 적용되며, 노드 토큰이 설정되지 않은 경우 표준 페어링 가드가 적용됩니다. 레지스트리 용량은 설정 가능한 max_nodes로 제한됩니다.
멀티 노드 레지스트리 (REST)
섹션 제목: “멀티 노드 레지스트리 (REST)”노드 디스커버리는 [nodes] enabled = true로 활성화됩니다. REST 인터페이스를 통해 연결된 노드를 나열하고 특정 노드의 기능을 호출할 수 있습니다.
| 메서드 | 경로 | 인증 | 목적 |
|---|---|---|---|
GET | /api/nodes | Bearer | 연결된 노드와 기능 목록 조회. |
POST | /api/nodes/{node_id}/invoke | Bearer | 기능 호출 — 본문: {"capability":"...","args":{}}. |
invoke 엔드포인트는 호출당 30초 하드 타임아웃을 적용합니다. 중앙 게이트웨이에서 멀티 노드 에이전트 네트워크를 오케스트레이션하는 데 사용하세요. 오케스트레이션 패턴은 특수 스위트: 노드를, 엣지 디바이스 설정은 하드웨어 빠른 시작을 참조하세요.
SSE 이벤트 스트림 (/api/events)
섹션 제목: “SSE 이벤트 스트림 (/api/events)”게이트웨이의 내부 브로드캐스트 채널을 대시보드 클라이언트에 노출하는 Server-Sent Events 스트림입니다. LLM 요청, 도구 호출, 에이전트 라이프사이클, 관찰 가능성 오류를 실시간으로 제공합니다. 이는 브로드캐스트/관찰 가능성 데이터이며 세션별 대화가 아닙니다. 대화에는 /ws/chat을 사용하세요.
GET /api/eventsAuthorization: Bearer <token>Accept: text/event-stream페어링이 활성화된 경우 인증이 필요합니다. 브로드캐스트 채널의 용량은 4096개 이벤트이며, Axum의 기본 킵얼라이브 주석 프레임이 연결을 유지합니다.
이벤트 유형
섹션 제목: “이벤트 유형”type | 필드 | 발생 시점 |
|---|---|---|
llm_request | provider, model, timestamp | LLM API 호출이 시작될 때. |
tool_call_start | tool, timestamp | 도구 호출이 시작될 때. |
tool_call | tool, duration_ms, success, timestamp | 도구 호출이 완료될 때. |
agent_start | provider, model, timestamp | 에이전트 턴이 시작될 때. |
agent_end | provider, model, duration_ms, tokens_used, cost_usd, timestamp | 에이전트 턴이 종료될 때. |
error | component, message, timestamp | 관찰 가능성 오류가 발생할 때. |
channel_event | payload | 오퍼레이터 채널 이벤트(/ws/chat 클라이언트에게 agent_event로도 릴레이됨). |
channel_event 페이로드에는 승인 요청(human_approval_request) 및 기타 오퍼레이터 알림이 포함되며, 대시보드는 이를 페이지 전체 승인 토스트로 표시합니다.
const es = new EventSource("/api/events"); // browser adds no Authorization headeres.onmessage = (e) => { const evt = JSON.parse(e.data); if (evt.type === "agent_end") console.log("cost:", evt.cost_usd);};데몬 로그 SSE 스트림 (/api/daemon/logs)
섹션 제목: “데몬 로그 SSE 스트림 (/api/daemon/logs)”데몬 stderr 로그를 테일링하고 새 줄을 SSE 이벤트로 스트리밍합니다. 연결 시 마지막 약 64 KB의 초기 버스트를 전송한 후 새로 추가된 바이트를 500ms 간격으로 폴링합니다. 초기 버스트를 넘어선 이전 로그는 재생되지 않습니다.
GET /api/daemon/logsAuthorization: Bearer <token>Accept: text/event-stream로그 파일은 ~/.revka/logs/daemon.stderr.log에 위치합니다(설정 파일의 상위 디렉터리 기준으로 경로를 해석합니다). 테일러는 로테이션과 잘림을 처리합니다. 파일 크기가 줄어들면 처음부터 다시 읽습니다.
| 이벤트 페이로드 | 의미 |
|---|---|
{"type":"log","line":"...","timestamp":"..."} | 새 로그 줄. |
{"type":"log_unavailable","line":"daemon log not readable at ...","timestamp":"..."} | 게이트웨이가 로그 파일을 읽을 수 없습니다. |
대시보드 Logs 페이지는 이 스트림을 일시 중지/재개 및 유형별 필터링 기능이 있는 최근 500개 항목 롤링 버퍼로 표시합니다. 로그, 감사, doctor, 페어링 및 스킨 페이지를 참조하세요.
SSE vs. WebSocket — 전송 방식 선택
섹션 제목: “SSE vs. WebSocket — 전송 방식 선택”일반적인 실시간 세션 흐름
섹션 제목: “일반적인 실시간 세션 흐름”-
페어링 한 번 수행하여 베어러 토큰 획득(페어링 및 인증 참조).
-
SSE를 통해
/api/events를 구독하여 게이트웨이 전체의 라이브 관찰 가능성, 비용, 승인 이벤트를 수신합니다. -
revka.v1및bearer.<token>서브프로토콜로/ws/chat을 엽니다.message프레임을 전송하고chunk프레임을 초안으로 스트리밍한 후chunk_reset시 폐기하고done.full_response를 렌더링합니다. -
필요에 따라
steer/stop프레임으로 진행 중인 턴을 스티어링 또는 중단합니다. -
에이전트가 A2UI 출력을 렌더링하는 경우
/ws/canvas/default로 캔버스를 확인하거나, 코딩 세션을 위해/ws/terminal을 엽니다.