본문으로 건너뛰기

API 서버

API 서버는 hermes-agent를 OpenAI 호환 HTTP 엔드포인트로 노출합니다. OpenAI 형식을 지원하는 프론트엔드라면 Open WebUI, LobeChat, LibreChat, NextChat, ChatBox를 비롯한 여러 클라이언트에서 hermes-agent를 백엔드처럼 연결해 사용할 수 있습니다.

에이전트는 터미널, 파일 작업, 웹 검색, 메모리, 스킬 등 전체 도구 세트로 요청을 처리한 뒤 최종 응답을 반환합니다. 스트리밍을 사용할 때는 도구 진행 상태도 스트림 안에 함께 표시되므로, 프론트엔드는 에이전트가 지금 무엇을 수행 중인지 사용자에게 보여줄 수 있습니다.

빠른 시작

1. API 서버 활성화

~/.hermes/.env에 다음 값을 추가합니다.

API_SERVER_ENABLED=true
API_SERVER_KEY=change-me-local-dev
# Optional: only if a browser must call Hermes directly
# API_SERVER_CORS_ORIGINS=http://localhost:3000

2. 게이트웨이 시작

hermes gateway

정상적으로 시작되면 다음과 비슷한 로그가 표시됩니다.

[API Server] API server listening on http://127.0.0.1:8642

3. 프론트엔드 연결

OpenAI 호환 클라이언트의 base URL을 http://localhost:8642/v1로 지정합니다.

# Test with curl
curl http://localhost:8642/v1/chat/completions \
-H "Authorization: Bearer change-me-local-dev" \
-H "Content-Type: application/json" \
-d '{"model": "hermes-agent", "messages": [{"role": "user", "content": "Hello!"}]}'

또는 Open WebUI, LobeChat 같은 프론트엔드를 연결할 수 있습니다. 단계별 설정은 Open WebUI 통합 가이드를 참고하세요.

엔드포인트

POST /v1/chat/completions

표준 OpenAI Chat Completions 형식입니다. 이 엔드포인트는 상태를 저장하지 않으므로, 각 요청마다 messages 배열에 전체 대화 기록을 포함해야 합니다.

요청:

{
"model": "hermes-agent",
"messages": [
{"role": "system", "content": "You are a Python expert."},
{"role": "user", "content": "Write a fibonacci function"}
],
"stream": false
}

응답:

{
"id": "chatcmpl-abc123",
"object": "chat.completion",
"created": 1710000000,
"model": "hermes-agent",
"choices": [{
"index": 0,
"message": {"role": "assistant", "content": "Here's a fibonacci function..."},
"finish_reason": "stop"
}],
"usage": {"prompt_tokens": 50, "completion_tokens": 200, "total_tokens": 250}
}

인라인 이미지 입력: 사용자 메시지의 contenttextimage_url 파트로 이루어진 배열로 보낼 수 있습니다. 원격 http(s) URL과 data:image/... URL을 모두 지원합니다.

{
"model": "hermes-agent",
"messages": [
{
"role": "user",
"content": [
{"type": "text", "text": "What is in this image?"},
{"type": "image_url", "image_url": {"url": "https://example.com/cat.png", "detail": "high"}}
]
}
]
}

업로드 파일(file / input_file / file_id)과 이미지가 아닌 data: URL은 지원하지 않으며 400 unsupported_content_type을 반환합니다.

스트리밍("stream": true): Server-Sent Events(SSE)로 토큰 단위 응답 청크를 반환합니다. Chat Completions 스트림은 표준 chat.completion.chunk 이벤트와 함께, 도구 시작 상태를 표시하기 위한 Hermes 전용 hermes.tool.progress 이벤트를 사용합니다. Responses 스트림은 response.created, response.output_text.delta, response.output_item.added, response.output_item.done, response.completed 같은 OpenAI Responses 이벤트 타입을 사용합니다.

스트림에서의 도구 진행 상태:

  • Chat Completions: Hermes는 저장되는 assistant 텍스트를 오염시키지 않으면서 도구 시작 상태를 보여주기 위해 event: hermes.tool.progress를 보냅니다.
  • Responses: Hermes는 SSE 스트림 중에 사양에 맞는 function_callfunction_call_output 출력 항목을 내보냅니다. 클라이언트는 이를 이용해 실시간 구조화 도구 UI를 렌더링할 수 있습니다.

POST /v1/responses

OpenAI Responses API 형식입니다. previous_response_id를 통해 서버 측 대화 상태를 지원합니다. 서버가 도구 호출과 결과를 포함한 전체 대화 기록을 저장하므로, 클라이언트가 직접 컨텍스트를 관리하지 않아도 멀티턴 흐름을 이어갈 수 있습니다.

요청:

{
"model": "hermes-agent",
"input": "What files are in my project?",
"instructions": "You are a helpful coding assistant.",
"store": true
}

응답:

{
"id": "resp_abc123",
"object": "response",
"status": "completed",
"model": "hermes-agent",
"output": [
{"type": "function_call", "name": "terminal", "arguments": "{\"command\": \"ls\"}", "call_id": "call_1"},
{"type": "function_call_output", "call_id": "call_1", "output": "README.md src/ tests/"},
{"type": "message", "role": "assistant", "content": [{"type": "output_text", "text": "Your project has..."}]}
],
"usage": {"input_tokens": 50, "output_tokens": 200, "total_tokens": 250}
}

인라인 이미지 입력: input[].content에는 input_textinput_image 파트를 넣을 수 있습니다. 원격 URL과 data:image/... URL을 모두 지원합니다.

{
"model": "hermes-agent",
"input": [
{
"role": "user",
"content": [
{"type": "input_text", "text": "Describe this screenshot."},
{"type": "input_image", "image_url": "data:image/png;base64,iVBORw0K..."}
]
}
]
}

업로드 파일(input_file / file_id)과 이미지가 아닌 data: URL은 지원하지 않으며 400 unsupported_content_type을 반환합니다.

previous_response_id로 멀티턴 유지

응답을 체인으로 연결하면 여러 턴에 걸쳐 전체 컨텍스트를 유지할 수 있습니다. 도구 호출 기록도 함께 이어집니다.

{
"input": "Now show me the README",
"previous_response_id": "resp_abc123"
}

서버는 저장된 응답 체인에서 전체 대화를 재구성합니다. 이전 도구 호출과 결과도 보존됩니다. 체인으로 이어진 요청은 같은 세션을 공유하므로, 대시보드와 세션 기록에서도 하나의 멀티턴 대화로 보입니다.

이름 있는 대화

응답 ID를 직접 추적하지 않으려면 conversation 파라미터를 사용할 수 있습니다.

{"input": "Hello", "conversation": "my-project"}
{"input": "What's in src/?", "conversation": "my-project"}
{"input": "Run the tests", "conversation": "my-project"}

서버는 해당 대화의 최신 응답에 자동으로 체인을 연결합니다. 게이트웨이 세션의 /title 명령과 비슷한 방식입니다.

GET /v1/responses/{id}

ID로 이전에 저장된 응답을 조회합니다.

DELETE /v1/responses/{id}

저장된 응답을 삭제합니다.

GET /v1/models

에이전트를 사용 가능한 모델로 나열합니다. 노출되는 모델 이름은 기본적으로 프로필 이름이며, 기본 프로필에서는 hermes-agent가 사용됩니다. 대부분의 프론트엔드가 모델 목록 검색에 이 엔드포인트를 요구합니다.

GET /v1/capabilities

외부 UI, 오케스트레이터, 플러그인 브리지가 API 서버의 안정적인 기능 범위를 확인할 수 있도록 기계가 읽을 수 있는 설명을 반환합니다.

{
"object": "hermes.api_server.capabilities",
"platform": "hermes-agent",
"model": "hermes-agent",
"auth": {"type": "bearer", "required": true},
"features": {
"chat_completions": true,
"responses_api": true,
"run_submission": true,
"run_status": true,
"run_events_sse": true,
"run_stop": true
}
}

대시보드, 브라우저 UI, 제어 플레인과 통합할 때 이 엔드포인트를 사용하면, 실행 중인 Hermes 버전이 runs, 스트리밍, 취소, 세션 연속성을 지원하는지 사설 Python 내부 구현에 의존하지 않고 확인할 수 있습니다.

GET /health

헬스 체크입니다. {"status": "ok"}를 반환합니다. /v1/ 접두사를 기대하는 OpenAI 호환 클라이언트를 위해 GET /v1/health에서도 사용할 수 있습니다.

GET /health/detailed

활성 세션, 실행 중인 에이전트, 리소스 사용량까지 보고하는 확장 헬스 체크입니다. 모니터링 및 관측성 도구에 유용합니다.

Runs API(스트리밍 친화 대안)

서버는 /v1/chat/completions/v1/responses 외에도 runs API를 제공합니다. 클라이언트가 직접 스트리밍을 관리하기보다 진행 이벤트를 구독하고 싶은 장시간 세션에 적합합니다.

POST /v1/runs

새 에이전트 실행을 생성합니다. 진행 이벤트 구독에 사용할 수 있는 run_id를 반환합니다.

{
"run_id": "run_abc123",
"status": "started"
}

run은 간단한 input 문자열과 선택적인 session_id, instructions, conversation_history, previous_response_id를 받습니다. session_id가 제공되면 Hermes는 run 상태에 이 값을 노출하므로, 외부 UI가 자체 대화 ID와 Hermes 실행을 매칭할 수 있습니다.

GET /v1/runs/{run_id}

현재 run 상태를 폴링합니다. SSE 연결을 계속 열어둘 수 없는 대시보드나, 페이지 이동 후 재연결하는 UI에서 유용합니다.

{
"object": "hermes.run",
"run_id": "run_abc123",
"status": "completed",
"session_id": "space-session",
"model": "hermes-agent",
"output": "Done.",
"usage": {"input_tokens": 50, "output_tokens": 200, "total_tokens": 250}
}

상태 정보는 completed, failed, cancelled 같은 종료 상태 이후에도 폴링과 UI 정합성을 위해 짧게 유지됩니다.

GET /v1/runs/{run_id}/events

run의 도구 호출 진행 상황, 토큰 델타, 수명주기 이벤트를 제공하는 Server-Sent Events 스트림입니다. 상태를 잃지 않고 연결과 해제를 반복해야 하는 대시보드나 데스크톱 클라이언트에 맞춰 설계되었습니다.

POST /v1/runs/{run_id}/stop

실행 중인 에이전트 턴을 중단합니다. 엔드포인트는 {"status": "stopping"}을 즉시 반환하며, Hermes는 활성 에이전트가 다음 안전한 중단 지점에서 멈추도록 요청합니다.

Jobs API(백그라운드 예약 작업)

서버는 원격 클라이언트에서 예약 또는 백그라운드 에이전트 실행을 관리할 수 있도록 가벼운 jobs CRUD 표면을 제공합니다. 모든 엔드포인트는 같은 bearer 인증 뒤에 있습니다.

GET /api/jobs

예약된 모든 작업을 나열합니다.

POST /api/jobs

새 예약 작업을 만듭니다. 본문은 hermes cron과 같은 형태를 받습니다. 예를 들어 프롬프트, 일정, 스킬, provider override, 전달 대상 등을 포함할 수 있습니다.

GET /api/jobs/{job_id}

단일 작업의 정의와 마지막 실행 상태를 가져옵니다.

PATCH /api/jobs/{job_id}

기존 작업의 필드(프롬프트, 일정 등)를 업데이트합니다. 부분 업데이트는 기존 값과 병합됩니다.

DELETE /api/jobs/{job_id}

작업을 제거합니다. 진행 중인 run도 함께 취소합니다.

POST /api/jobs/{job_id}/pause

작업을 삭제하지 않고 일시 중지합니다. 재개될 때까지 다음 예약 실행 시각도 중지됩니다.

POST /api/jobs/{job_id}/resume

일시 중지된 작업을 다시 시작합니다.

POST /api/jobs/{job_id}/run

일정과 관계없이 작업을 즉시 실행합니다.

시스템 프롬프트 처리

프론트엔드가 Chat Completions의 system 메시지나 Responses API의 instructions 필드를 보내면, hermes-agent는 이를 핵심 시스템 프롬프트 위에 추가 계층으로 얹습니다. 에이전트는 기존 도구, 메모리, 스킬을 유지하며, 프론트엔드의 시스템 프롬프트는 추가 지시로 작동합니다.

즉, 기능을 잃지 않고 프론트엔드별 동작을 조정할 수 있습니다.

  • Open WebUI 시스템 프롬프트: "You are a Python expert. Always include type hints."
  • 에이전트는 여전히 터미널, 파일 도구, 웹 검색, 메모리 등을 사용할 수 있습니다.

인증

Authorization 헤더의 Bearer 토큰으로 인증합니다.

Authorization: Bearer ***

키는 API_SERVER_KEY 환경 변수로 설정합니다. 브라우저가 Hermes를 직접 호출해야 한다면 API_SERVER_CORS_ORIGINS도 명시적인 허용 목록으로 설정하세요.

Security

API 서버는 터미널 명령을 포함한 hermes-agent의 전체 도구 세트에 접근할 수 있게 합니다. 0.0.0.0처럼 loopback이 아닌 주소에 바인딩할 때는 API_SERVER_KEY필수입니다. 브라우저 접근을 제어하려면 API_SERVER_CORS_ORIGINS도 좁게 유지하세요.

기본 바인드 주소(127.0.0.1)는 로컬 전용입니다. 브라우저 접근은 기본적으로 비활성화되어 있으므로, 신뢰할 수 있는 origin에 대해서만 명시적으로 켜세요.

구성

환경 변수

변수기본값설명
API_SERVER_ENABLEDfalseAPI 서버 활성화
API_SERVER_PORT8642HTTP 서버 포트
API_SERVER_HOST127.0.0.1바인드 주소. 기본값은 localhost 전용입니다.
API_SERVER_KEY(없음)인증에 사용할 Bearer 토큰
API_SERVER_CORS_ORIGINS(없음)브라우저에서 허용할 origin 목록. 쉼표로 구분합니다.
API_SERVER_MODEL_NAME(프로필 이름)/v1/models에 표시할 모델 이름. 기본 프로필에서는 hermes-agent, 그 외에는 프로필 이름이 기본값입니다.

config.yaml

# Not yet supported - use environment variables.
# config.yaml support coming in a future release.

보안 헤더

모든 응답에는 다음 보안 헤더가 포함됩니다.

  • X-Content-Type-Options: nosniff - MIME 타입 스니핑 방지
  • Referrer-Policy: no-referrer - referrer 정보 유출 방지

CORS

API 서버는 기본적으로 브라우저 CORS를 활성화하지 않습니다.

브라우저에서 직접 접근해야 한다면 명시적인 허용 목록을 설정하세요.

API_SERVER_CORS_ORIGINS=http://localhost:3000,http://127.0.0.1:3000

CORS를 활성화하면 다음이 적용됩니다.

  • Preflight 응답Access-Control-Max-Age: 600(10분 캐시)이 포함됩니다.
  • SSE 스트리밍 응답에도 CORS 헤더가 포함되어 브라우저 EventSource 클라이언트가 정상 동작합니다.
  • Idempotency-Key 요청 헤더가 허용됩니다. 클라이언트는 중복 제거에 이 헤더를 사용할 수 있으며, 응답은 키 기준으로 5분 동안 캐시됩니다.

Open WebUI처럼 문서화된 대부분의 프론트엔드는 서버 간 연결을 사용하므로 CORS가 전혀 필요하지 않습니다.

호환 프론트엔드

OpenAI API 형식을 지원하는 프론트엔드는 모두 사용할 수 있습니다. 테스트되었거나 문서화된 통합은 다음과 같습니다.

프론트엔드Stars연결 방식
Open WebUI126k전체 가이드 제공
LobeChat73k사용자 지정 provider endpoint
LibreChat34klibrechat.yaml의 사용자 지정 endpoint
AnythingLLM56k일반 OpenAI provider
NextChat87kBASE_URL 환경 변수
ChatBox39kAPI Host 설정
Jan26k원격 모델 설정
HF Chat-UI8kOPENAI_BASE_URL
big-AGI7k사용자 지정 endpoint
OpenAI Python SDK-OpenAI(base_url="http://localhost:8642/v1")
curl-직접 HTTP 요청

프로필을 이용한 다중 사용자 설정

여러 사용자에게 서로 분리된 Hermes 인스턴스(각자의 설정, 메모리, 스킬)를 제공하려면 프로필을 사용합니다.

# Create a profile per user
hermes profile create alice
hermes profile create bob

# Configure each profile's API server on a different port. API_SERVER_* are env
# vars (not config.yaml keys), so write them to each profile's .env:
cat >> ~/.hermes/profiles/alice/.env <<EOF
API_SERVER_ENABLED=true
API_SERVER_PORT=8643
API_SERVER_KEY=alice-secret
EOF

cat >> ~/.hermes/profiles/bob/.env <<EOF
API_SERVER_ENABLED=true
API_SERVER_PORT=8644
API_SERVER_KEY=bob-secret
EOF

# Start each profile's gateway
hermes -p alice gateway &
hermes -p bob gateway &

각 프로필의 API 서버는 프로필 이름을 모델 ID로 자동 노출합니다.

  • http://localhost:8643/v1/models -> 모델 alice
  • http://localhost:8644/v1/models -> 모델 bob

Open WebUI에서는 각각을 별도 연결로 추가합니다. 모델 드롭다운에는 alicebob이 서로 다른 모델로 표시되며, 각 모델은 완전히 분리된 Hermes 인스턴스에 연결됩니다. 자세한 내용은 Open WebUI 가이드를 참고하세요.

제한 사항

  • 응답 저장 - previous_response_id용으로 저장된 응답은 SQLite에 유지되며 게이트웨이 재시작 후에도 남습니다. 최대 100개의 저장 응답을 보관합니다(LRU eviction).
  • 파일 업로드 미지원 - 인라인 이미지는 /v1/chat/completions/v1/responses에서 모두 지원하지만, 업로드 파일(file, input_file, file_id)과 이미지가 아닌 문서 입력은 API를 통해 지원하지 않습니다.
  • model 필드는 표시용 - 요청의 model 필드는 허용되지만 실제로 사용되는 LLM 모델은 서버 측 config.yaml에서 구성됩니다.

프록시 모드

API 서버는 게이트웨이 프록시 모드의 백엔드 역할도 합니다. 다른 Hermes 게이트웨이 인스턴스가 GATEWAY_PROXY_URL을 이 API 서버로 지정하면, 자체 에이전트를 실행하지 않고 모든 메시지를 이 서버로 전달합니다. 이를 통해 분리 배포가 가능합니다. 예를 들어 Matrix E2EE를 처리하는 Docker 컨테이너가 호스트 측 에이전트로 릴레이하도록 구성할 수 있습니다.

전체 설정은 Matrix Proxy Mode를 참고하세요.