Orbit API
GitLab v19.5Offering: GitLab.com
요약
이 API를 사용하여 Orbit에 대한 쿼리를 실행하고, 스키마를 조회하며, 클러스터 상태를 확인합니다. 경로, 매개변수, 응답을 포함한 Orbit 엔드포인트의 전체 레퍼런스는 대화형 API 레퍼런스를 참조합니다. GQL 쿼리 모드의 사용 가능 여부는 orbit_gql_queries라는 기능 플래그로 제어됩니다.
히스토리
- GitLab 18.10에서
knowledge_graph라는 기능 플래그와 함께 실험 기능으로 도입되었습니다. 기본적으로 비활성화됩니다. - GitLab 19.1에서 실험에서 베타로 변경되었습니다.
- GitLab 19.3에서 GitLab.com에서 활성화되었습니다.
- GitLab 19.4에서
orbit_gql_queries라는 기능 플래그와 함께 GQL 모드가 도입되었습니다. 기본적으로 비활성화됩니다. - GitLab 19.5에서 기능 플래그
knowledge_graph가 제거되었습니다.
이 API를 사용하여 Orbit에 대한 쿼리를 실행하고, 스키마를 조회하며, 클러스터 상태를 확인합니다.
엔드포인트 레퍼런스#
경로, 매개변수, 응답을 포함한 Orbit 엔드포인트의 전체 레퍼런스는 대화형 API 레퍼런스를 참조합니다. 다음 섹션에서는 생성된 레퍼런스에 나오지 않는 쿼리 DSL 동작과 실제 사용 예시를 다룹니다.
쿼리 모드#
GQL 쿼리 모드의 사용 가능 여부는 orbit_gql_queries라는 기능 플래그로 제어됩니다.
자세한 내용은 히스토리를 참조합니다.
쿼리는 기본적으로 JSON DSL 객체를 사용해야 합니다.
orbit_gql_queries를 활성화하면 쿼리는 읽기 전용 GQL 문자열로, 탐색은 GQL 안내로 전환됩니다.
GQL은 openCypher 9 구문을 따릅니다.
이 플래그는 개별 사용자를 대상으로 합니다.
REST 및 MCP 호출자는 매개변수나 헤더로 모드를 재정의할 수 없습니다.
플래그를 활성화하면 response_format: gql이 쿼리 결과를 일반 텍스트 표로 반환합니다.
스킬#
히스토리
- GitLab 19.5에서 도입되었습니다.
스킬 엔드포인트는 read_api 스코프로 인증해야 합니다.
Orbit 라이선스는 확인하지 않으므로, 사용할 수 없는 스킬은 403 Forbidden 대신 404 Not Found를 반환합니다.
다음 경우에는 Skills are not available 메시지와 함께 404 Not Found가 응답됩니다.
- Knowledge Graph 서비스가 스킬 RPC를 지원하지 않는 이전 버전입니다.
- 인스턴스에 Knowledge Graph 서비스가 구성되어 있지 않습니다. GitLab Self-Managed에서는
gitlab.yml의orbit.enabled또는 이전 설정인knowledge_graph.enabled로 제어합니다. - 현재 사용자가 최상위 그룹에서 Orbit를 켠 그룹의 Reporter 이상 권한을 가지고 있지 않습니다. Admin Mode의 관리자와 감사자는 이 권한 요건에서 제외됩니다.
이러한 경우 Orbit CLI는 내장된 로컬 스킬을 사용합니다.
배포된 스킬 목록 조회#
연결된 Knowledge Graph 서비스와 함께 배포된 Orbit 스킬을 나열합니다.
GET /orbit/skills
이 요청은 속성을 받지 않습니다.
성공하면 200 OK와 다음 응답 속성이 반환됩니다.
| 속성 | 유형 | 설명 |
|---|---|---|
server_version |
문자열 | 배포된 Knowledge Graph 서비스의 버전. |
skills |
배열 | 배포된 스킬. |
skills[].compatibility |
문자열 | 스킬 매니페스트에 명시된 환경 요건. |
skills[].description |
문자열 | 스킬 매니페스트에 명시된 설명. |
skills[].name |
문자열 | 스킬 이름. |
skills[].version |
문자열 | 매니페스트에 명시된 스킬 버전. |
응답에는 정렬된 스킬 이름과 버전에서 생성한 ETag 헤더와
private, max-age=0, must-revalidate로 설정된 Cache-Control 헤더가 포함됩니다.
요청 예시:
curl --request GET \
--header "PRIVATE-TOKEN: <your_access_token>" \
--url "https://gitlab.example.com/api/v4/orbit/skills"
응답 예시:
{
"skills": [
{
"name": "orbit",
"version": "0.29.0",
"description": "Use the glab orbit CLI for knowledge graph queries.",
"compatibility": "Requires Orbit CLI"
}
],
"server_version": "0.31.0"
}
배포된 스킬 조회#
배포된 Orbit 스킬 트리 전체를 조회합니다.
GET /orbit/skills/:name
지원되는 속성:
| 속성 | 유형 | 필수 | 설명 |
|---|---|---|---|
name |
문자열 | 예 | 스킬 이름. |
성공하면 200 OK와 다음 응답 속성이 반환됩니다.
| 속성 | 유형 | 설명 |
|---|---|---|
compatibility |
문자열 | 스킬 매니페스트에 명시된 환경 요건. |
files |
배열 | 스킬 트리의 파일. |
files[].content |
문자열 | UTF-8 파일 콘텐츠. |
files[].path |
문자열 | 스킬 루트를 기준으로 정규화한 경로. |
files[].sha256 |
문자열 | 파일 콘텐츠의 SHA-256 해시. |
name |
문자열 | 스킬 이름. |
server_version |
문자열 | 배포된 Knowledge Graph 서비스의 버전. |
version |
문자열 | 스킬 버전. |
응답에는 다음 헤더가 포함됩니다.
| 헤더 | 설명 |
|---|---|
Cache-Control |
private, max-age=0, must-revalidate로 설정됩니다. |
ETag |
"<version>"로 설정됩니다. |
캐시된 스킬 트리를 다시 검증하려면 현재 ETag 값을 If-None-Match 요청 헤더로 보냅니다.
값이 일치하면 응답 본문 없이 304 Not Modified가 반환됩니다.
요청 예시:
curl --request GET \
--header "PRIVATE-TOKEN: <your_access_token>" \
--url "https://gitlab.example.com/api/v4/orbit/skills/orbit"
응답 예시:
{
"name": "orbit",
"version": "0.29.0",
"compatibility": "Requires Orbit CLI",
"server_version": "0.31.0",
"files": [
{
"path": "SKILL.md",
"sha256": "93f2655e8772217e4aa8c8fbe3ad0c1f36b2bdf4a63f9f6e2f6d89a3b01da9f8",
"content": "# Orbit skill\n"
}
]
}
스킬이 존재하지 않으면 오류 메시지에 알려진 스킬 이름이 포함된 404 Not Found가 반환됩니다.
배포된 스킬 메타데이터 확인#
파일을 조회하지 않고 배포된 스킬의 식별 정보와 캐시 헤더를 확인합니다.
HEAD /orbit/skills/:name
지원되는 속성:
| 속성 | 유형 | 필수 | 설명 |
|---|---|---|---|
name |
문자열 | 예 | 스킬 이름. |
성공하면 200 OK와 GET /orbit/skills/:name과 동일한 ETag 및 Cache-Control
헤더가 반환되며 응답 본문은 없습니다.
요청 예시:
curl --head \
--header "PRIVATE-TOKEN: <your_access_token>" \
--url "https://gitlab.example.com/api/v4/orbit/skills/orbit"
배포된 스킬 파일 조회#
배포된 스킬의 파일 하나를 원시 UTF-8 텍스트로 조회합니다. 이 경로로 SKILL.md를 직접 가져오거나
같은 스킬 트리의 파일에 대한 상대 링크를 따라갈 수 있습니다.
GET /orbit/skills/:name/*path
지원되는 속성:
| 속성 | 유형 | 필수 | 설명 |
|---|---|---|---|
name |
문자열 | 예 | 배포된 스킬 이름. |
path |
문자열 | 예 | 스킬 루트를 기준으로 한 파일 경로(예: references/usage.md). |
성공하면 200 OK와 함께 JSON 객체가 아닌 파일 콘텐츠가 반환됩니다.
Markdown 파일(.md)의 콘텐츠 유형은 text/markdown; charset=utf-8입니다.
그 외 파일의 콘텐츠 유형은 text/plain; charset=utf-8이며, HTML로 제공되는 스킬 파일은 없습니다.
스킬 매니페스트에 나열된 정확한 경로만 사용할 수 있습니다. 알 수 없는 경로는 404 Not Found를 반환합니다.
형식이 잘못된 경로는 400 Bad Request를 반환할 수 있습니다. API 오류 응답은 원시 파일 콘텐츠가 아닌 JSON이며,
경로 순회 미들웨어가 차단한 요청은 일반 텍스트 오류를 반환할 수 있습니다.
응답에는 파일의 SHA-256에서 생성한 강한 ETag와 private, max-age=0, must-revalidate로
설정된 Cache-Control 헤더가 포함됩니다. 파일이 변경되지 않았을 때 304 Not Modified를 받으려면
ETag를 If-None-Match로 보냅니다. HEAD는 본문 없이 동일한 헤더를 반환합니다.
요청 예시:
curl --request GET \
--header "PRIVATE-TOKEN: <your_access_token>" \
--url "https://gitlab.example.com/api/v4/orbit/skills/orbit/SKILL.md"
응답 예시:
# Orbit skill
명명된 쿼리#
프로그래밍 방식의 소비자라면 POST /api/v4/orbit/query보다
POST /api/v4/orbit/query/:name을 사용하는 것이 좋습니다. 명명된 쿼리의 구조는 서버에 있으므로
DSL 문법이나 온톨로지와 어긋날 수 없습니다.
명명된 요청은 JSON 엔벨로프를 유지하며, 템플릿은 활성 모드에서 실행됩니다.
쿼리 템플릿#
GET /api/v4/orbit/query/templates에 나열되는 명명된 쿼리 템플릿에는
인증된 사용자를 기준으로 렌더링된 raw_query가 포함됩니다.
- 템플릿은 JSON 모드에서는 JSON 객체를, GQL 모드에서는 GQL 문자열을 포함합니다.
- 인증된 사용자의 ID와 같은 신원 값은 요청 자격 증명을 기준으로
서버 측에서 확인됩니다. 동일한 요청이라도
사용자마다 다른
raw_query값이 반환됩니다. 템플릿을 캐시하거나 사용자 또는 모드 간에 공유하지 않습니다. - 매개변수화된 쿼리는 카탈로그에서 제외되므로, 이름과 인수를 지정하여 호출합니다.
템플릿보다 명명된 쿼리를 직접 실행하는 것이 좋습니다. 템플릿은 쿼리 편집기나 탐색기에 프리셋의 텍스트를 채우는 것처럼 쿼리 텍스트를 표시하는 것이 목적일 때만 사용합니다.
쿼리 예시#
다음 예시는 쿼리 유형별 Orbit 쿼리 DSL을 보여 줍니다. 모든
예시는 POST /api/v4/orbit/query를 사용합니다. 전체 쿼리 언어는
Orbit 쿼리 언어를 참조합니다.
GQL 모드에서는 POST /api/v4/orbit/query의 query 값으로 GQL 문자열을 전달합니다.
{"query": "MATCH (u:User {id: 1}) RETURN u LIMIT 1"}
예시는 기본 raw 응답 형식을 사용합니다. 각 응답에서 result
객체는 일치한 nodes와 그 사이의 edges를 나열합니다. 노드 ID는 문자열입니다.
집계 쿼리는 columns, group_columns, rows도 반환합니다.
사용자명으로 사용자 조회:
curl --request POST \
--header "PRIVATE-TOKEN: <your_access_token>" \
--header "Content-Type: application/json" \
--data '{
"query": {
"query_type": "traversal",
"nodes": [
{"id": "u", "entity": "User", "filters": {"username": "john_smith"}}
]
}
}' \
--url "https://gitlab.example.com/api/v4/orbit/query"
응답 예시:
{
"result": {
"format_version": "5.0.3",
"query_type": "traversal",
"nodes": [
{"type": "User", "id": "1", "username": "john_smith", "name": "John Smith", "state": "active"}
],
"edges": [],
"pagination": {"has_more": false, "truncated": false}
},
"query_type": "traversal",
"row_count": 1
}
프로젝트에서 병합된 머지 리퀘스트 찾기:
curl --request POST \
--header "PRIVATE-TOKEN: <your_access_token>" \
--header "Content-Type: application/json" \
--data '{
"query": {
"query_type": "traversal",
"nodes": [
{"id": "p", "entity": "Project", "node_ids": [8]},
{"id": "mr", "entity": "MergeRequest", "filters": {"state": "merged"}}
],
"relationships": [{"type": "IN_PROJECT", "from": "mr", "to": "p"}]
}
}' \
--url "https://gitlab.example.com/api/v4/orbit/query"
응답 예시:
{
"result": {
"format_version": "5.0.3",
"query_type": "traversal",
"nodes": [
{"type": "Project", "id": "8", "name": "Diaspora Client", "full_path": "diaspora/diaspora-client", "visibility_level": "public"},
{"type": "MergeRequest", "id": "43", "iid": 1, "title": "Resolve connection timeout on large payloads", "state": "merged", "source_branch": "fix-timeout", "target_branch": "main"},
{"type": "MergeRequest", "id": "44", "iid": 2, "title": "Replace deprecated API calls in federation module", "state": "merged", "source_branch": "update-federation-api", "target_branch": "main"}
],
"edges": [
{"from": "MergeRequest", "from_id": "43", "to": "Project", "to_id": "8", "type": "IN_PROJECT"},
{"from": "MergeRequest", "from_id": "44", "to": "Project", "to_id": "8", "type": "IN_PROJECT"}
],
"pagination": {"has_more": false, "truncated": false}
},
"query_type": "traversal",
"row_count": 2
}
프로젝트별 머지 리퀘스트 수 집계. 순회 및 집계 쿼리는 node_ids 또는 필터로
노드를 하나 이상 한정해야 합니다.
curl --request POST \
--header "PRIVATE-TOKEN: <your_access_token>" \
--header "Content-Type: application/json" \
--data '{
"query": {
"query_type": "aggregation",
"nodes": [
{"id": "p", "entity": "Project", "node_ids": [5, 8]},
{"id": "mr", "entity": "MergeRequest"}
],
"relationships": [{"type": "IN_PROJECT", "from": "mr", "to": "p"}],
"aggregations": [{"count": "mr", "as": "mr_count"}],
"group_by": ["p"]
}
}' \
--url "https://gitlab.example.com/api/v4/orbit/query"
응답 예시:
{
"result": {
"format_version": "5.0.3",
"query_type": "aggregation",
"nodes": [],
"edges": [],
"columns": [{"name": "mr_count", "function": "count", "target": "mr"}],
"group_columns": [{"name": "p", "kind": "node", "node": "p", "entity": "Project"}],
"rows": [
{"p": {"type": "Project", "id": "8", "properties": {"name": "Diaspora Client", "full_path": "diaspora/diaspora-client", "visibility_level": "public"}}, "mr_count": 8},
{"p": {"type": "Project", "id": "5", "properties": {"name": "Puppet", "full_path": "brightbox/puppet", "visibility_level": "public"}}, "mr_count": 6}
],
"pagination": {"has_more": false, "truncated": false}
},
"query_type": "aggregation",
"row_count": 2
}
사용자의 외부 이웃 찾기. direction 속성은 outgoing,
incoming, both를 받으며 기본값은 outgoing입니다.
curl --request POST \
--header "PRIVATE-TOKEN: <your_access_token>" \
--header "Content-Type: application/json" \
--data '{
"query": {
"query_type": "neighbors",
"nodes": [{"id": "u", "entity": "User", "node_ids": [1]}],
"neighbors": {"direction": "outgoing"}
}
}' \
--url "https://gitlab.example.com/api/v4/orbit/query"
응답 예시:
{
"result": {
"format_version": "5.0.3",
"query_type": "neighbors",
"nodes": [
{"type": "User", "id": "1", "username": "john_smith", "name": "John Smith", "state": "active"},
{"type": "Group", "id": "29", "name": "diaspora", "full_path": "diaspora", "visibility_level": "public"},
{"type": "MergeRequest", "id": "43", "iid": "1", "title": "Resolve connection timeout on large payloads", "state": "merged", "source_branch": "fix-timeout", "target_branch": "main"},
{"type": "MergeRequest", "id": "44", "iid": "2", "title": "Replace deprecated API calls in federation module", "state": "merged", "source_branch": "update-federation-api", "target_branch": "main"}
],
"edges": [
{"from": "User", "from_id": "1", "to": "Group", "to_id": "29", "type": "MEMBER_OF"},
{"from": "User", "from_id": "1", "to": "MergeRequest", "to_id": "43", "type": "AUTHORED"},
{"from": "User", "from_id": "1", "to": "MergeRequest", "to_id": "44", "type": "AUTHORED"}
],
"pagination": {"has_more": false, "truncated": false}
},
"query_type": "neighbors",
"row_count": 3
}
사용자에서 프로젝트까지의 최단 경로 찾기. 경로 찾기 쿼리에는
rel_types가 필요하며, 각 관계 유형은 정의된 방향으로만 따라갑니다.
즉 from 노드에서 to 노드 방향입니다.
curl --request POST \
--header "PRIVATE-TOKEN: <your_access_token>" \
--header "Content-Type: application/json" \
--data '{
"query": {
"query_type": "path_finding",
"nodes": [
{"id": "u", "entity": "User", "node_ids": [1]},
{"id": "p", "entity": "Project", "node_ids": [8]}
],
"path": {
"type": "shortest",
"from": "u",
"to": "p",
"max_depth": 3,
"rel_types": ["MEMBER_OF", "CONTAINS"]
}
}
}' \
--url "https://gitlab.example.com/api/v4/orbit/query"
응답 예시:
{
"result": {
"format_version": "5.0.3",
"query_type": "path_finding",
"nodes": [
{"type": "User", "id": "1", "username": "john_smith", "name": "John Smith", "state": "active"},
{"type": "Group", "id": "29", "name": "diaspora", "full_path": "diaspora", "visibility_level": "public"},
{"type": "Project", "id": "8", "name": "Diaspora Client", "full_path": "diaspora/diaspora-client", "visibility_level": "public"}
],
"edges": [
{"from": "User", "from_id": "1", "to": "Group", "to_id": "29", "type": "MEMBER_OF", "path_id": 0, "step": 0},
{"from": "Group", "from_id": "29", "to": "Project", "to_id": "8", "type": "CONTAINS", "path_id": 0, "step": 1}
],
"pagination": {"has_more": false, "truncated": false}
},
"query_type": "path_finding",
"row_count": 1
}
액세스 및 클러스터 상태#
GET /api/v4/orbit/status는 액세스 여부나 서비스 상태와 관계없이 항상 200 OK를
반환합니다. 사용자에게 액세스 권한이 없으면 system은
null입니다.
{
"user": {
"available": false
},
"system": null
}