메모리 그래프 및 에셋 브라우저 API
메모리 그래프 엔드포인트, 읽기 전용 Kumiho 프록시, 아티팩트 서빙, 그리고 타입이 지정된 에셋 쓰기 API.
이 페이지에서는 Kumiho 그래프 메모리를 클라이언트에 노출하는 게이트웨이 엔드포인트를 설명합니다. Memory Auditor를 위한 단일 통합 메모리 그래프 페이로드, 임의의 GET 엔드포인트를 위한 읽기 전용 범용 Kumiho 프록시, 디스크의 파일을 렌더링하기 위한 아티팩트 본문 서빙, 그리고 프로젝트·스페이스·아이템·리비전·아티팩트·번들·엣지를 변경하는 타입이 지정된 에셋 브라우저 쓰기 API가 포함됩니다.
대시보드 대신 프로그래밍 방식으로 지식 그래프를 읽거나 편집하고 싶을 때 이 엔드포인트를 사용하십시오. 대시보드의 에셋 및 메모리 탐색기는 전적으로 이 엔드포인트 위에 구축되어 있습니다. 스페이스·아이템·리비전·kref·엣지·출처 등의 기반 데이터 모델은 그래프 모델: 스페이스, 아이템 및 출처를 참조하십시오. REST 대신 MCP 도구를 통해 에이전트가 메모리를 읽고 쓰는 방법은 Kumiho 메모리 도구를 참조하십시오.
이 페이지의 모든 라우트에는 페어링 베어러 토큰이 필요합니다.
Authorization: Bearer <token>토큰은 페어링 및 인증의 페어링 흐름을 통해 발급받으십시오. 토큰이 없거나 유효하지 않으면 401이 반환됩니다. 대부분의 라우트는 게이트웨이 기본값인 64 KiB JSON 본문 제한 및 요청 타임아웃을 공유합니다. 예외 사항(메모리 그래프 타임아웃, 아티팩트 본문 및 콘텐츠 편집 크기 제한)은 아래에서 별도로 설명합니다.
요청이 Kumiho에 도달하는 방식
섹션 제목: “요청이 Kumiho에 도달하는 방식”Revka는 그래프 자체를 저장하지 않습니다. 영속성은 Kumiho의 역할입니다. 이 페이지의 모든 라우트는 두 가지 전송 방식 중 하나로 Kumiho에 접근하는 KumihoClient에 위임하며, 전송 방식은 자동으로 선택됩니다.
| 전송 방식 | 설명 | 사용 시점 |
|---|---|---|
| SDK 브리지 | kumiho_sdk_bridge.py라는 루프백 전용 Python 사이드카로, 낮은 레이턴시 읽기를 위해 127.0.0.1을 통해 Kumiho Python SDK를 노출합니다 | Kumiho venv가 존재할 때 우선 사용 |
| 호스팅된 FastAPI | [kumiho] api_url(기본값 https://api.kumiho.cloud)의 Kumiho 컨트롤 플레인으로 직접 HTTP 요청 | 브리지를 사용할 수 없거나, 501 kumiho_sdk_bridge_unsupported가 반환되거나, 5xx가 반환될 때 폴백 |
브리지는 기본적으로 활성화되어 있으며, REVKA_KUMIHO_SDK_BRIDGE=0(또는 false, no, off)으로 비활성화할 수 있습니다. 처음 사용 시 ~/.revka/kumiho/kumiho_sdk_bridge.py로 생성되고, 임시 루프백 포트에서 수신 대기하며, 종료 시 자동으로 재시작하고, ~/.revka/logs/kumiho-sdk-bridge.stdout.log 및 kumiho-sdk-bridge.stderr.log에 로그를 기록합니다. 헬스 체크 및 요청별 타임아웃은 각각 10초입니다. ~/.revka/kumiho/venv/의 venv가 없으면 브리지가 시작되지 않고 모든 읽기가 호스팅된 FastAPI로 폴백되며, 하드 에러는 발생하지 않습니다. 사이드카 설치 방법은 Kumiho 설정을 참조하십시오.
읽기 응답은 토큰 범위의 캐시에서 제공됩니다. 신선 TTL은 10초이고 스테일 윈도우는 120초입니다. 캐시된 값은 최대 10초 지연될 수 있으며, Kumiho가 오프라인 상태가 되어도 스테일 값이 2분간 계속 제공됩니다. 쓰기 메서드(POST/PUT/DELETE)는 재시도하지 않습니다. Kumiho에는 멱등성 키가 없으므로 재시도 시 데이터가 중복 생성될 수 있기 때문입니다.
메모리 그래프
섹션 제목: “메모리 그래프”GET /api/memory/graph는 노드·엣지·스페이스·통계를 단일 페이로드로 반환하며, 대시보드의 Obsidian 스타일 포스 다이렉티드 메모리 탐색기에 바로 사용할 수 있습니다.
GET /api/memory/graph?project=CognitiveMemory&limit=100&kinds=decision,fact&space=CognitiveMemory/Skills&sort=recent&search=gRPCAuthorization: Bearer <token>쿼리 파라미터
섹션 제목: “쿼리 파라미터”| 파라미터 | 타입 | 기본값 | 설명 |
|---|---|---|---|
project | string | [kumiho] memory_project (CognitiveMemory) | 읽을 Kumiho 프로젝트 |
limit | int | 100 (최대 500) | 포함할 최대 아이템 수 |
kinds | string | — | 쉼표로 구분된 kind 필터, 예: decision,fact,preference |
space | string | — | 스페이스 경로 접두사 필터 |
sort | string | recent | recent(최신순) 또는 name |
search | string | — | 전문 검색 쿼리; 일치하는 아이템만 결과에 포함 |
{ "nodes": [ { "id": "CognitiveMemory/Decisions/chose-grpc", "name": "chose-grpc", "kind": "decision", "space": "CognitiveMemory/Decisions", "created_at": "2026-06-18T09:12:00Z", "title": "Chose gRPC over REST", "summary": "...", "revision_kref": "kref://CognitiveMemory/Decisions/chose-grpc?r=2" } ], "edges": [ { "source": "...", "target": "...", "edge_type": "DERIVED_FROM", "metadata": {} } ], "spaces": ["CognitiveMemory", "CognitiveMemory/Skills"], "stats": { "total_items": 42, "total_edges": 18, "kinds": { "decision": 10, "fact": 32 } }}stats.total_items는 limit 잘라내기 이전의 전체 필터링된 집합을 반영하므로 nodes.length보다 클 수 있습니다.
엣지는 반환된 노드 집합에 양쪽 엔드포인트가 모두 존재할 때만 나타납니다. 자기 참조 엣지와 집합 외부 엣지는 필터링되며, (source, edge_type, target) 3중 쌍이 중복되면 중복 제거됩니다. 이를 통해 끊어진 참조 없이 그래프를 렌더링할 수 있습니다.
범용 Kumiho 프록시
섹션 제목: “범용 Kumiho 프록시”GET /api/kumiho/{*path}는 임의의 Kumiho FastAPI GET 엔드포인트에 대한 투명한 읽기 전용 프록시입니다. 쿼리 파라미터는 그대로 전달되며, 응답 본문은 JSON으로 반환됩니다.
GET /api/kumiho/items?space_path=/CognitiveMemory/SkillsGET /api/kumiho/revisions/latest?item_kref=kref://CognitiveMemory/my-skillAuthorization: Bearer <token>GET만 프록시됩니다. 설계상 쓰기 경로는 없습니다. 그래프를 변경하려면 타입이 지정된 에셋 브라우저 쓰기 API나 에이전트·스킬·팀 API에 문서화된 리소스별 라우트를 사용하십시오.
Revka는 요청이 어떻게 처리되었는지 클라이언트가 알 수 있도록 두 가지 관찰성 헤더를 추가합니다.
| 헤더 | 값 | 설명 |
|---|---|---|
X-Revka-Cache | hit · stale | 캐시에서 응답했는지, 스테일 폴백이었는지 여부 |
X-Revka-Kumiho-Transport | sdk-bridge · fastapi | 응답한 전송 방식 |
GET 요청은 일시적인 업스트림 오류(502, 503, 504, 520, 522, 524) 발생 시 15초 예산 내에서 최대 3회 시도(2회 재시도)합니다(500ms / 1500ms 지터 백오프). 업스트림 HTML 에러 페이지(예: Cloudflare 502 스플래시 페이지)는 클라이언트에 도달하기 전에 제거됩니다.
아티팩트 본문 서빙
섹션 제목: “아티팩트 본문 서빙”GET /api/artifact-body는 Kumiho 아티팩트의 location 필드가 참조하는 로컬 파일의 원시 바이트를 스트리밍합니다. 에셋 브라우저와 워크플로 실행 아티팩트 뷰어는 파일 I/O를 직접 구현하지 않고 이 엔드포인트를 통해 텍스트·이미지·비디오 아티팩트를 렌더링합니다.
GET /api/artifact-body?location=file:///home/user/.revka/workspace/artifacts/kumiho/report.mdAuthorization: Bearer <token>| 파라미터 | 타입 | 필수 | 설명 |
|---|---|---|---|
location | string | yes | 아티팩트의 location 값: 절대 경로 또는 선택적으로 file:// 접두사를 포함한 경로; ~는 확장됩니다 |
응답에는 최선 방식의 Content-Type(확장자에서 추측), Content-Disposition: inline, Cache-Control: private, max-age=60이 포함됩니다. 최대 서빙 크기는 256 MiB이며, 더 큰 파일은 413을 반환합니다.
보안 및 폴백
섹션 제목: “보안 및 폴백”경로는 워크스페이스 보안 정책에 따라 검사됩니다. 위치는 절대 경로여야 하며 워크스페이스 또는 허용된 루트 내에서 해석되어야 합니다. 그렇지 않으면 403이 반환됩니다. 상대 경로는 400을 반환합니다.
디스크에서 파일을 찾을 수 없으면 게이트웨이는 리비전 메타데이터 폴백을 시도합니다. Kumiho에서 해당 위치의 아티팩트를 조회하고, base64 페이로드(content_base64, data_base64, payload_base64, body_base64) 또는 텍스트 유사 아티팩트의 텍스트 필드(content, body, text, markdown 등)에서 본문을 재구성합니다. 이 경로가 사용되면 응답에 X-Revka-Artifact-Source: revision-metadata 헤더가 포함됩니다. 워크플로 YAML 정의는 아티팩트 본문으로 절대 제공되지 않도록 이 폴백에서 의도적으로 제외됩니다.
에셋 브라우저 쓰기 API
섹션 제목: “에셋 브라우저 쓰기 API”/api/assets/* 라우트는 대시보드 에셋 페이지 뒤에 있는 타입이 지정된 쓰기 인터페이스입니다. 범용 프록시는 읽기 전용이므로, 스페이스 생성·리비전 추가·아티팩트 콘텐츠 편집 등 모든 변경 작업은 이 라우트를 통해 수행됩니다. 이 라우트들은 기본값인 64 KiB보다 큰 2 MiB 본문 제한을 공유하며 베어러 토큰이 필요합니다.
엔드포인트
섹션 제목: “엔드포인트”POST /api/assets/projectsPOST /api/assets/spacesPOST /api/assets/itemsPOST /api/assets/items/deprecatePOST /api/assets/revisionsPOST /api/assets/revisions/deprecatePOST /api/assets/revisions/publishPOST /api/assets/revisions/tags — tag a revisionDELETE /api/assets/revisions/tags — untag a revisionGET /api/assets/bundlesPOST /api/assets/bundlesGET /api/assets/bundles/membersPOST /api/assets/bundles/membersDELETE /api/assets/bundles/membersPOST /api/assets/edgesGET /api/assets/dependency-graphPOST /api/assets/artifactsPOST /api/assets/artifacts/deprecatePUT /api/assets/artifacts/content — edit artifact content그래프 엔티티 생성
섹션 제목: “그래프 엔티티 생성”생성 라우트는 Kumiho 계층 구조를 그대로 반영합니다. 프로젝트에는 스페이스가 포함되고, 스페이스에는 아이템이 포함되고, 아이템에는 일련의 리비전이 있으며, 리비전에는 아티팩트가 포함될 수 있습니다. 각 생성 요청은 해당 타입 이름을 키로 하는 객체에 생성된 엔티티를 감싸서 반환합니다({"item": {...}}, {"revision": {...}} 등).
POST /api/assets/projects{ "name": "CognitiveMemory", "description": "optional" }
POST /api/assets/spaces{ "parent_path": "/CognitiveMemory", "name": "Decisions" }
POST /api/assets/items{ "space_path": "/CognitiveMemory/Decisions", "item_name": "chose-grpc", "kind": "decision", "metadata": {} }
POST /api/assets/revisions{ "item_kref": "kref://CognitiveMemory/Decisions/chose-grpc", "metadata": { "title": "Chose gRPC" } }
POST /api/assets/edges{ "source_kref": "<rev kref>", "target_kref": "<rev kref>", "edge_type": "DERIVED_FROM", "metadata": {} }엣지는 아이템 kref가 아닌 리비전 kref를 연결하며, edge_type은 그래프 모델: 스페이스, 아이템 및 출처에 설명된 출처 타입 중 하나입니다(DERIVED_FROM, DEPENDS_ON, REFERENCED, CONTAINS, CREATED_FROM, BELONGS_TO).
아티팩트 생성
섹션 제목: “아티팩트 생성”POST /api/assets/artifacts는 아티팩트를 리비전에 연결합니다. 기존 파일을 location으로 등록하고 파일 존재 여부를 검증하거나, 콘텐츠를 디스크에 직접 작성할 수 있습니다.
POST /api/assets/artifacts{ "revision_kref": "kref://CognitiveMemory/Decisions/chose-grpc?r=2", "name": "NOTES.md", "location": "", "content": "# Notes\n...", "write_file": true, "overwrite": false, "validate_exists": false}| 필드 | 타입 | 설명 |
|---|---|---|
revision_kref | string | 아티팩트가 속할 리비전(정확한 ?r=N 선택자 포함 필수) |
name | string | 아티팩트 파일명 |
location | string | 절대 경로 또는 file:// URI; write_file과 함께 비워두면 workspace/artifacts/kumiho/... 아래에 자동 생성됨 |
content | string | 작성할 본문(write_file이 true일 때); 최대 1 MiB |
write_file | bool | 등록 전에 content를 location에 디스크로 작성 |
overwrite | bool | 기존 파일 덮어쓰기 허용; 그렇지 않으면 기존 파일이 있을 때 409 반환 |
validate_exists | bool | 링크 전용 아티팩트의 경우, 파일이 없으면 400으로 실패 |
작성되거나 연결되는 모든 경로는 워크스페이스 보안 정책에 따라 검사됩니다. 워크스페이스 및 허용된 루트 외부의 경로는 403을 반환합니다.
아티팩트 콘텐츠 편집
섹션 제목: “아티팩트 콘텐츠 편집”PUT /api/assets/artifacts/content는 아티팩트 본문을 제자리에서 편집하며, 최대 1 MiB로 제한됩니다.
PUT /api/assets/artifacts/content{ "artifact_kref": "<artifact kref>", "revision_kref": "<revision kref>", "content": "updated body" }동작 방식은 리비전이 게시되었는지 여부에 따라 달라집니다.
- 게시되지 않은 리비전 — 파일이 제자리에서 다시 작성됩니다. 응답에는
"created_revision": false가 포함됩니다. - 게시된 리비전 — 게시된 이력은 불변이므로 게이트웨이가 새 리비전을 생성하고, 편집된 콘텐츠를 새 버전 파일(
name.rN.ext)에 작성하며, 다른 아티팩트를 앞으로 복사합니다. 응답에는"created_revision": true와copied_artifacts수가 포함됩니다.
{ "revision": { "...": "the (possibly new) revision" }, "artifact": { "...": "the edited artifact" }, "created_revision": true, "copied_artifacts": 3}리비전 게시 및 태그 지정
섹션 제목: “리비전 게시 및 태그 지정”POST /api/assets/revisions/publish { "kref": "<revision kref>" }POST /api/assets/revisions/tags { "kref": "<revision kref>", "tag": "milestone" }DELETE /api/assets/revisions/tags { "kref": "<revision kref>", "tag": "milestone" }게시는 리비전에 published 태그를 붙입니다. 태그 추가와 제거는 current를 제외한 모든 태그를 허용합니다. current 태그의 이동 또는 제거는 위험도가 높아 403으로 거부됩니다(kumiho_patch_apply를 통해서만 수행해야 합니다).
번들 및 멤버
섹션 제목: “번들 및 멤버”번들은 Kumiho의 그룹핑 구조로, 팀·정규 집합·세션 캡처 등을 나타냅니다. 번들을 나열하고, 해석된 아이템 세부 정보와 함께 멤버를 나열하고, 멤버를 추가하거나 제거할 수 있습니다.
GET /api/assets/bundles?project=Revka&space_path=/Revka/TeamsGET /api/assets/bundles/members?bundle_kref=<bundle kref>POST /api/assets/bundles/members { "bundle_kref": "...", "item_kref": "...", "metadata": {} }DELETE /api/assets/bundles/members { "bundle_kref": "...", "item_kref": "..." }의존성 그래프
섹션 제목: “의존성 그래프”GET /api/assets/dependency-graph는 캔버스 의존성 뷰를 위해 리비전에서 외부로 엣지를 순회합니다.
GET /api/assets/dependency-graph?revision_kref=<kref>&direction=both&depth=2&edge_type=all&node_limit=100| 파라미터 | 타입 | 기본값 | 설명 |
|---|---|---|---|
revision_kref | string | required | 순회의 중심 노드 |
direction | string | both | upstream/outgoing, downstream/incoming, 또는 both |
depth | int | 1 (최대 3) | 엣지 홉 순회 횟수 |
edge_type | string | all | 특정 엣지 타입으로 제한; all 또는 빈 값은 필터 없음 |
node_limit | int | 100 (최대 200) | 이 수에 도달하면 확장 중지; 도달 시 truncated: true 설정 |
응답에는 해석된 노드(아티팩트 및 수신/발신 엣지 포함), 중복 제거된 엣지 목록, 그리고 유효 direction, depth, node_limit, truncated 플래그가 포함됩니다.
Kumiho SDK 브리지 및 클라이언트 CRUD
섹션 제목: “Kumiho SDK 브리지 및 클라이언트 CRUD”요청이 Kumiho에 도달하는 방식에서 설명한 전송 분리는 SDK 브리지(프로세스 로컬 Python 사이드카)와 **KumihoClient**에 의해 구현됩니다. 이 두 컴포넌트는 이 페이지의 모든 라우트와 API의 다른 곳에 있는 에이전트·스킬·팀·워크플로 라우트를 함께 지원합니다. 이들은 내부 컴포넌트이므로 직접 호출하지 않지만, 동작 방식을 이해하면 관찰되는 현상을 파악하는 데 도움이 됩니다.
- 인증에는 두 가지 토큰이 사용됩니다.
KUMIHO_SERVICE_TOKEN은 호스팅된 FastAPI 호출을 인증하고,KUMIHO_AUTH_TOKEN은 브리지를 인증합니다. 두 값은 다를 수 있습니다.revka onboard는 두 토큰을 모두~/.revka/.env에 기록합니다. Kumiho 설정을 참조하십시오. - 읽기는 재시도하고 쓰기는 재시도하지 않습니다. 위에서 설명한 재시도 및 스테일 캐시 동작은 GET에 적용됩니다. 생성/업데이트/삭제는 한 번만 실행됩니다.
- 캐시는 토큰 범위입니다. 캐시 키는
(token_hash, url)이므로 한 계정의 캐시된 읽기가 다른 계정으로 누출되지 않습니다.
KumihoClient는 이 엔드포인트들이 구성하는 Kumiho REST 전체 인터페이스를 래핑합니다. 아이템(create_item, list_items, search_items, deprecate_item), 리비전(create_revision, get_latest_revision, tag_revision, batch_get_revisions), 스페이스 및 프로젝트(ensure_space, create_project), 엣지(create_edge, list_edges), 아티팩트(create_artifact, get_artifacts, get_artifacts_by_location), 번들(create_bundle, add_bundle_member, list_bundle_members)이 포함됩니다. /api/assets/* 라우트는 정확히 이 호출들에 대한 얇고 유효성이 검사된 래퍼이므로, API를 통해 엔티티를 생성하는 것은 에이전트의 MCP 도구를 통해 생성하는 것과 동일하게 동작합니다.
관련 페이지
섹션 제목: “관련 페이지”- 그래프 모델: 스페이스, 아이템 및 출처 — 여기에 있는 모든 엔티티의 기반 데이터 모델
- Kumiho 그래프 메모리 — 오퍼레이터 가이드
- Kumiho 설정 — 사이드카 설치 및 토큰 설정
- 에셋 및 메모리 탐색기 — 이 엔드포인트 위에 구축된 대시보드
- 에이전트·스킬·팀 API — Kumiho에도 영속되는 리소스별 쓰기 라우트
- Gateway API 개요 — 인증, 본문 제한 및 공통 규칙