콘텐츠로 이동

게이트웨이 API 개요

Axum 게이트웨이 아키텍처, 본문/타임아웃 제한, REST·SSE·WebSocket 전송 방식의 구성 방법

Revka 게이트웨이는 Axum 기반의 HTTP 서버로, 구조화된 REST API와 WebSocket 및 Server-Sent Events 전송 방식을 통해 전체 에이전트 런타임을 외부에 노출합니다. 동일한 프로세스가 내장 React 대시보드, 모든 /api/* 라우트, 실시간 스트림, 그리고 동일 출처 브라우저 접근을 위해 역방향 프록시된 내장 MCP 서버를 함께 제공합니다. 이 페이지는 아키텍처 개요로서, 세 가지 전송 방식이 어떻게 맞물리는지, 모든 라우트에 공통으로 적용되는 본문 및 타임아웃 제한, 라우트별 재정의, 그리고 게이트웨이가 노출하는 네 가지 인증 방식을 설명합니다.

클라이언트를 게이트웨이에 연결하거나, 역방향 프록시를 구성하거나, 특정 기능에 어떤 전송 방식을 사용할지 결정할 때 이 페이지를 먼저 읽으십시오. 각 라우트 그룹의 요청별 참조는 다음 단계의 링크를 따라가십시오. 서버 시작 방법은 revka gateway, daemon & service를 참조하십시오.

revka gateway는 HTTP/WebSocket 게이트웨이만 시작하고, revka daemon은 동일한 게이트웨이에 채널, 하트비트, 크론 스케줄러를 추가로 시작합니다. 두 명령 모두 동일한 HTTP 인터페이스를 노출하며, 다섯 개의 레이어로 구성됩니다.

레이어경로 접두사전송 방식인증
내장 대시보드/, /_app/*HTTP (정적)없음 (SPA 셸)
REST API/api/*HTTP (JSON)Bearer 토큰
실시간 스트림/api/events, /api/daemon/logsSSEBearer 토큰
WebSocket 전송/ws/*WebSocketBearer 토큰
공개 인그레스/health, /metrics, /pair, /webhook, /whatsapp, /track/c/*, …HTTP없음 또는 엔드포인트별 서명

대시보드는 API와 동일한 출처에서 제공되므로 브라우저가 CORS 경계를 넘지 않습니다. 별도의 인-프로세스 MCP 서버가 임시 로컬 포트에 바인딩되고, 게이트웨이는 이를 /api/mcp/*(및 /ws/mcp/events) 아래에 역방향 프록시로 노출하여 브라우저 클라이언트가 출처를 벗어나지 않고도 MCP 도구에 접근할 수 있게 합니다. 외부 MCP 클라이언트는 ~/.revka/mcp.json에서 인-프로세스 서버의 주소를 직접 읽습니다.

게이트웨이는 세 가지 전송 방식을 지원합니다. 상호작용 형태에 맞는 방식을 선택하십시오.

  • REST — 요청/응답 방식의 작업: 설정, 상태 조회, 크론 작업·에이전트·스킬·팀·워크플로·메모리 에셋에 대한 CRUD.
  • SSE — 서버가 모든 구독자에게 단방향으로 푸시하는 브로드캐스트 스트림: 관찰 가능성 이벤트와 데몬 로그.
  • WebSocket — 양방향, 연결별 세션: 대화형 에이전트 채팅, PTY 터미널, 라이브 캔버스 업데이트, MCP 진행 이벤트, 노드 등록.

모든 /api/* 라우트는 JSON 요청/응답 방식이며 Bearer 토큰 인증으로 보호됩니다. 대표적인 엔드포인트 예시는 다음과 같습니다.

GET /api/status
Authorization: Bearer <token>
{
"provider": "openrouter",
"model": "anthropic/claude-sonnet-4",
"uptime_seconds": 3600,
"gateway_port": 8080,
"memory_backend": "kumiho",
"paired": true,
"channels": {},
"health": {}
}

두 개의 SSE 엔드포인트가 대시보드 클라이언트에 서버 발신 스트림을 푸시합니다. 페어링이 활성화된 경우 두 엔드포인트 모두 Bearer 토큰이 필요하며, Accept: text/event-stream 헤더를 함께 보내야 합니다.

엔드포인트스트림 내용
GET /api/events관찰 가능성 브로드캐스트: llm_request, tool_call_start, tool_call, agent_start, agent_end, error, channel_event
GET /api/daemon/logs데몬 stderr 로그의 실시간 테일 — 초기 약 64 KB 버스트, 이후 500 ms 폴링
GET /api/events
Authorization: Bearer <token>
Accept: text/event-stream

SSE는 브로드캐스트 방식의 관찰 가능성 채널입니다. 세션별 대화 채널이 아니므로, 그런 용도로는 /ws/chat을 사용하십시오.

WebSocket 엔드포인트는 양방향 상태 유지 세션을 제공합니다. 브라우저는 new WebSocket()Authorization 헤더를 설정할 수 없으므로, 게이트웨이는 우선순위 순서에 따라 세 가지 대체 방법으로 Bearer 토큰을 수락합니다.

  1. Authorization: Bearer <token> 헤더
  2. Sec-WebSocket-Protocol: bearer.<token> 서브프로토콜
  3. ?token=<token> 쿼리 파라미터
엔드포인트용도서브프로토콜
/ws/chat대화형 에이전트 채팅 — 스트리밍 청크, 도구 이벤트, 조향, 중지, 첨부 파일revka.v1
/ws/terminal셸이나 AI 코딩 CLI를 실행할 수 있는 PTY 터미널revka.v1
/ws/canvas/{id}이름이 지정된 캔버스에 푸시되는 라이브 프레임 구독revka.v1
/ws/mcp/events인-프로세스 MCP 서버의 세션 이벤트 스트림 프록시 (Code 탭)revka.v1
/ws/nodes외부 노드가 에이전트 도구가 될 기능을 등록revka.nodes.v1
ws://host:port/ws/chat?session_id=<uuid>&name=My+Session&token=<bearer>

PTY 터미널은 Android에서 비활성화됩니다. 각 WebSocket 엔드포인트의 프레임별 프로토콜은 실시간: WebSocket, SSE & 라이브 캔버스에서 확인하십시오.

라우트가 명시적으로 제외하지 않는 한, 모든 라우트에는 요청 본문 크기 제한과 요청 타임아웃 두 가지 제한이 적용됩니다.

게이트웨이는 요청 본문에 **65,536 바이트(64 KiB)**의 전역 제한을 적용합니다. 본문이 이를 초과하는 요청은 핸들러에 도달하기 전에 거부됩니다. 대부분의 API 호출은 간결한 JSON이기 때문에 제한값을 의도적으로 작게 설정했으며, 더 큰 페이로드가 필요한 라우트는 자체적으로 더 높은 제한을 선언합니다.

일부 엔드포인트는 페이로드에 맞게 제한을 높입니다. 문서화된 재정의 목록은 다음과 같습니다.

라우트제한이유
PUT /api/config1 MiB전체 config.toml 본문
POST / PUT /api/workflows, PUT /api/workflows/{*kref}16 MiB실제 워크플로 YAML이 64 KiB를 초과할 수 있음
POST /api/sessions/{id}/attachments25 MiB파일별 이미지/문서 업로드
POST /api/skins/import25 MiBUI 스킨 ZIP 업로드
POST /api/agents/avatar, POST /api/teams/avatar5 MiB아바타 이미지 업로드
PUT /api/assets/artifacts/content2 MiB아티팩트 콘텐츠 편집
GET /api/artifact-body256 MiB원시 아티팩트 바이트 제공 (응답 측)

모든 요청은 주로 슬로우-로리스 연결을 방지하기 위해 타임아웃 제한도 받습니다. 기본값은 REQUEST_TIMEOUT_SECS에 의해 설정된 30초입니다.

Terminal window
# Raise the per-request timeout to 5 minutes for long agentic calls
REVKA_GATEWAY_TIMEOUT_SECS=300 revka gateway
변수기본값의미
REVKA_GATEWAY_TIMEOUT_SECS30전역 요청별 타임아웃(초)을 재정의합니다.

일부 엔드포인트는 이 기본값과 별개로 자체적인 더 긴 제한 시간을 가집니다. 예를 들어 GET /api/memory/graph는 대형 그래프를 위해 60초를 허용하고, POST /api/nodes/{node_id}/invoke는 호출당 30초의 고정 제한을 사용합니다.

게이트웨이에는 네 가지 인증 방식이 있습니다. 라우트가 어떤 방식을 사용하는지 파악하는 것이 연동의 핵심입니다.

기본 인증 방식입니다. 모든 /api/* 라우트, SSE 스트림, WebSocket 엔드포인트는 일회성 페어링 흐름으로 발급된 Bearer 토큰을 요구합니다.

Authorization: Bearer <token>

클라이언트가 페어링 코드를 토큰으로 교환하면 게이트웨이는 해시만 저장하고, 토큰은 한 번만 표시됩니다. 코드, SQLite 기기 레지스트리, 토큰 갱신, 속도 제한에 대한 전체 내용은 페어링 및 인증을 참조하십시오.

일부 변경 엔드포인트는 권한 있는 상태를 조작하기 때문에 사용자 Bearer 토큰이 아닌 내부 서비스 토큰으로만 접근할 수 있습니다. 토큰은 게이트웨이 시작 시 자동 생성되어 <state_dir>/service-token에 저장됩니다(POSIX에서 모드 0600). 전용 헤더를 통해 전달합니다.

X-Revka-Service-Token: <service-token>

예를 들어 POST /api/cost/usage(예산 원장 기록)와 POST /api/auth/profiles/{id}/resolve(저장된 자격 증명을 복호화하는 유일한 경로)가 해당됩니다. 서비스 토큰은 서명된 워크스페이스 에셋 URL의 HMAC 서명 키로도 사용됩니다.

관리 엔드포인트는 루프백 확인으로 제한됩니다. 로컬이 아닌 IP에서의 요청은 403을 받습니다. 호스트 내에서만 접근 가능하기 때문에 Bearer 토큰이 필요하지 않습니다.

엔드포인트사용처
POST /admin/shutdownrevka stop
GET /admin/paircode, POST /admin/paircode/newrevka gateway get-paircode
POST /api/channel-events이벤트를 게시하는 운영자 및 로컬 서비스

로드 밸런서, 웹훅 제공자, 링크를 클릭하는 이메일 수신자 등 Bearer 토큰을 보유할 수 없는 호출자를 위해 일부 엔드포인트는 의도적으로 인증을 요구하지 않습니다.

  • 활성 상태 및 메트릭: GET /health는 페어링 상태와 컴포넌트 스냅샷을 담아 200을 반환하며 비밀을 노출하지 않습니다. GET /metrics[observability] backend = "prometheus" 설정 시 Prometheus 텍스트 형식을 노출합니다.
  • 웹훅 인그레스: POST /webhook, /whatsapp, /linq, /wati, /nextcloud-talk, /webhook/gmail. Bearer 토큰 대신 제공자 HMAC 또는 공유 비밀을 검증하며, IP별 속도 제한이 적용됩니다.
  • 서명된 URL: GET /track/c/{encoded}(이메일 클릭 추적)와 GET /workspace/{*path}?exp=&sig=(HMAC 서명, 시간 제한 워크스페이스 에셋)는 Authorization 헤더 대신 자체 서명을 포함합니다.

WebAuthn/FIDO2 하드웨어 키 인증은 선택적 기능 게이트 방식(/api/webauthn/*, webauthn 컴파일 피처 필요)으로 제공됩니다. TLS, 속도 제한, WebAuthn & 정적 파일 제공을 참조하십시오.

일반적인 대시보드 또는 클라이언트 세션은 세 가지 전송 방식을 동시에 사용합니다.

  1. 페어링을 한 번 수행하여 Bearer 토큰을 얻은 다음, GET /health(인증 없음) 또는 GET /api/status(Bearer)로 게이트웨이가 정상 동작 중인지 확인합니다.

  2. REST로 작업을 수행합니다 — 설정 읽기/쓰기, 크론 작업 및 에이전트 관리, 메모리 그래프 조회 — 각 호출에 Authorization: Bearer <token>을 포함하고 64 KiB 제한(또는 라우트별 재정의 값) 이내로 유지합니다.

  3. /api/events를 SSE로 구독하여 실시간 관찰 가능성, 비용, 승인 이벤트를 받습니다.

  4. /ws/chat을 엽니다revka.v1 서브프로토콜이나 ?token= 쿼리 파라미터로 토큰을 전달하고, done 프레임이 올 때까지 청크를 스트리밍합니다.