콘텐츠로 이동
Study Notekagent · kmcp

AgentHarness로 Hermes 실행

결론부터
  • Hermes는 Agent가 아니라 AgentHarness 리소스에 backend: hermes를 적어 올린다. kagent는 Hermes의 내용을 정하지 않고 sandbox의 수명만 관리한다.
  • AgentHarness는 항상 Agent Substrate 위에서 돈다. Substrate 설치와 kagent의 연동 설정이 선행 조건이다.
  • 준비되면 kagent UI와 A2A 주소에 일반 Agent처럼 나타난다. controller가 A2A와 Hermes의 프로토콜(ACP) 사이를 변환한다.
  • harness 하나는 actor 하나를 모든 채팅이 공유한다. 사람별로 격리된 비서가 아니라 공용 작업 환경이다.
  • AgentHarness에는 tools·allowedHeaders가 없다. 임직원 토큰으로 backend를 부르는 용도에는 Declarative Agent를 쓴다.
이 장에서 처음 나오는 말5개
HermesHermes Agent
Nous Research가 만든 오픈소스 agent다. 파일·터미널·웹·메모리·코드 실행 도구를 스스로 갖고 있고, 메신저 연동과 예약 실행을 지원한다.
OpenClaw
AgentHarness가 지원하는 또 하나의 backend다. Hermes와 같은 자리에 놓이는 외부 coding agent다.
AgentHarness
외부 coding agent가 돌아갈 장기 실행 sandbox를 선언하는 kagent 리소스다. 안에 kagent runtime이 없다.
ACPAgent Client Protocol
coding agent를 외부에서 조종하기 위한 JSON-RPC 프로토콜이다. Hermes와 OpenClaw가 구현한다.
golden snapshot
Substrate가 actor의 초기 상태를 미리 만들어 둔 snapshot이다. 새 actor는 여기서 복원해 빠르게 시작한다.

지금까지의 Agent는 kagent가 실행 방식을 정했다 — 지시문과 tool을 받아 ADK runtime이 돌리거나, A2A 서버 image를 받아 배포했다. Hermes 같은 agent는 이 틀에 맞지 않는다. 자체 도구와 메모리, 설정 파일, 메신저 연동을 가진 완성된 프로그램이고 A2A 서버가 아니다.

AgentHarness는 이런 프로그램을 “그대로 돌릴 장소”를 kagent가 만들어 주는 리소스다 (Agent Harness). 이 페이지는 Hermes를 올리는 데 무엇이 필요한지와, 올린 뒤 무엇이 되고 무엇이 안 되는지를 본다.

Declarative AgentAgentHarness (Hermes)
kagent가 정하는 것지시문, 모델, tool, 승인 대상sandbox의 생성·삭제, 모델 연결, 메신저 채널
능력을 정하는 곳manifest의 toolNamesHermes 자체의 도구와 설정
안에서 도는 것kagent ADK runtimehermes acp 프로세스
실행 위치Deployment (또는 Substrate)Substrate actor (필수)
상태session은 kagent DBactor 안의 파일·메모리. snapshot으로 보존
manifest로 리뷰할 수 있는 범위Agent가 할 수 있는 일 전체sandbox가 있다는 사실과 연결 설정

마지막 줄이 운영상 가장 큰 차이다. Declarative Agent는 PR의 diff가 능력의 변화였다. Hermes는 터미널과 코드 실행 도구를 스스로 갖고 있어서, manifest에는 그 능력이 드러나지 않는다. 통제 지점이 manifest가 아니라 sandbox의 경계(네트워크, 주입한 자격, 연결한 채널)로 옮겨 간다.

AgentHarness는 Agent Substrate 없이 동작하지 않는다. spec.substrate가 필수 필드이고, kagent의 Substrate 연동이 꺼져 있으면 controller가 harness를 만들 수 없다 (Enable AgentHarness support).

필요한 것은 셋이다.

  1. Agent Substrate 설치(substrate-crds, substrate chart).
  2. kagent chart의 controller.substrate.enabled: true와 Substrate API 주소.
  3. harness가 올라갈 WorkerPool. kagent chart의 substrateWorkerPool.create: true로 기본 pool을 만들 수 있다.

WorkerPool은 플랫폼이 소유한다. controller는 harness마다 ActorTemplate만 만들고 WorkerPool은 만들거나 지우지 않는다.

# 공식 예제의 형태
apiVersion: kagent.dev/v1alpha2
kind: AgentHarness
metadata:
name: hermes-shell
namespace: kagent
spec:
backend: hermes
description: "Hermes shell for scheduled and chat-driven workflows"
modelConfigRef: default-model-config
substrate:
workerPoolRef:
name: kagent-default
필드뜻
backendhermes 또는 openclaw. 필수
substrate.workerPoolRef올라갈 WorkerPool. 생략하면 controller의 기본 pool
substrate.snapshotsConfigactor snapshot 저장 위치. 생략하면 gs://ate-snapshots/<namespace>/<이름>
substrate.workloadImage · imagesandbox image를 바꿀 때만. 생략하면 backend의 기본 image
modelConfigRef쓸 ModelConfig. controller가 이 값으로 Hermes 설정 파일을 만들어 넣는다
envsandbox에 넣을 환경 변수
channelsSlack 같은 메신저 연동

기본 image에는 Hermes가 hermes-agent package로 설치되어 있고 hermes acp 명령으로 실행된다(소스에서 확인).

상태는 두 condition으로 본다. Accepted는 spec이 받아들여졌다는 뜻이고, Ready는 golden snapshot이 준비되어 채팅을 받을 수 있다는 뜻이다.

터미널 창
kubectl -n kagent get agentharness hermes-shell
# NAME BACKEND READY ID AGE

Substrate는 actor에 네트워크로만 들어갈 수 있게 한다. SSH나 exec가 없다. 반면 Hermes의 ACP 서버는 표준 입출력으로 대화한다. kagent는 이 간격을 두 개의 변환기로 메운다.

A2A client의 요청을 controller가 ACP로 바꿔 WebSocket으로 actor 안의 acp-shim에 보내고 shim이 표준 입출력으로 hermes acp 프로세스에 전달한다

그 결과 harness는 kagent UI의 Agent 목록에 함께 나타나고, 일반 Agent처럼 채팅할 수 있다. Hermes가 도구 실행 전에 요청하는 승인은 kagent의 HITL 흐름으로 표시된다.

공식 문서는 이렇게 설명한다. 첫 채팅이 연결될 때 harness template에서 공유 actor 하나가 만들어지고, 이후의 모든 채팅은 그 actor 안의 ACP session으로 들어간다.

이것이 뜻하는 바는 다음과 같다.

  • harness 하나의 파일, Hermes의 메모리, 설치한 도구를 그 harness와 채팅하는 모든 사람이 공유한다.
  • 한 사람이 채팅으로 만든 파일이나 기억시킨 내용을 다른 사람의 채팅이 볼 수 있다.
  • 사람별로 분리가 필요하면 harness를 사람·팀 단위로 따로 만들어야 한다. harness마다 actor와 snapshot이 따로 생긴다.

“임직원 누구나 쓰는 공용 Hermes 하나”는 개인 비서가 아니라 공용 작업실이다. 누가 들어올 수 있는지는 kagent가 아니라 호출을 중계하는 우리 backend가 정한다.

Hermes는 메신저에서 받은 메시지에 답하고, 예약된 작업의 결과를 정해 둔 채널에 올릴 수 있다. channels에 Slack token과 Hermes용 설정을 적는다(Agent Harness 예제).

# 발췌 — 공식 예제의 형태
spec:
backend: hermes
channels:
- name: platform
type: slack
slack:
botToken:
valueFrom: { type: Secret, name: slack-tokens, key: bot-token }
appToken:
valueFrom: { type: Secret, name: slack-tokens, key: app-token }
hermes:
allowedUserIDs:
- U01234567
homeChannel: C0123456789
  • backend: hermes이면 slack.hermes만 쓸 수 있다. slack.openclaw를 쓰면 API가 거부한다.
  • allowedUserIDs는 Hermes에 말을 걸 수 있는 Slack 사용자다. Secret·ConfigMap에서 읽으려면 allowedUserIDsFrom을 쓴다.
  • homeChannel은 예약 실행 결과가 올라가는 채널이다.

Slack으로 들어오는 요청은 oauth2-proxy도 우리 backend도 거치지 않는다. 이 경로의 접근 통제는 allowedUserIDs가 전부라는 점을 감안한다.

앞 페이지의 전파는 Declarative Agent의 tools[].mcpServer.allowedHeaders로 이뤄졌다. AgentHarness의 spec에는 tools도 allowedHeaders도 없다 (API reference).

질문답
임직원 토큰이 Hermes의 tool 호출에 자동으로 실리는가그런 설정이 spec에 없다
Hermes가 backend API를 부르게 하려면env로 고정 자격을 넣는 방법뿐이다. 모든 사용자가 같은 권한이 된다
채팅한 임직원이 누구인지 Hermes가 구분하는가actor와 ACP 프로세스는 공유된다. 사람별 신원이 tool 호출까지 이어진다고 볼 근거를 찾지 못했다

따라서 용도를 나누는 것이 맞다.

  • 임직원의 권한으로 사내 데이터를 조회·변경하는 업무 Agent → Declarative Agent + http MCP 서버 + allowedHeaders.
  • 코드 작성·조사·예약 작업 같은 범용 작업 환경 → AgentHarness. 주입하는 자격은 그 harness를 쓰는 모든 사람에게 허용해도 되는 범위로 제한한다.
항목왜 확인하나
Substrate의 온프렘 준비gVisor, snapshot용 object storage가 필요하다. snapshot 위치 필드는 gs:// prefix만 받는다
snapshot에 들어가는 것actor의 메모리와 파일이 저장된다. 대화 내용·자격이 포함될 수 있다. 저장소의 암호화·보존·삭제 정책
sandbox의 outboundHermes는 웹 접근과 코드 실행 도구를 가진다. 어디로 나갈 수 있는지를 Substrate 쪽에서 제한할 수 있는지
사내 모델 연결modelConfigRef가 LiteLLM을 가리키는 ModelConfig일 때 Hermes 설정이 올바로 만들어지는지
인증 없는 경로chart 기본 oauth2-proxy 설정이 api/agentharnesses/.*/gateway 경로의 인증을 건너뛴다. 이 경로의 용도와 보호 방식
image 공급기본 sandbox image를 사내 registry로 mirror하고 digest를 고정할 수 있는지
버전 조합kagent와 Substrate는 문서가 함께 확인한 버전으로 맞춘다. 0.x 문서 기준 Substrate v0.0.9
  • Hermes harness의 manifest PR에서 “이 agent가 무엇을 할 수 있는가”를 읽을 수 있는가? → 읽을 수 없다. manifest는 sandbox와 연결 설정만 보여 준다. Hermes의 능력은 자체 도구가 정하므로 통제는 sandbox의 네트워크와 주입한 자격에서 한다.
  • 두 임직원이 같은 harness와 채팅한다. A가 만든 파일을 B가 요청으로 읽을 수 있는가? → actor를 공유하므로 가능하다고 봐야 한다. 분리가 필요하면 harness를 나눈다.
  • Hermes가 임직원 본인의 휴가 내역을 조회하게 하고 싶다. 맞는 구성인가? → 맞지 않는다. 임직원 토큰이 Hermes의 tool 호출로 전파되지 않는다. 그 기능은 Declarative Agent로 만든다.