Hermes Agent SOUL.md와 5-Pillar 아키텍처 — Tier 3 스킬 자동 생성 메커니즘 내부 해부
세션이 끝날 때마다 에이전트가 그 대화에서 수행한 작업의 절차를 추출해 스킬 파일로 저장하고, 다음 세션부터 그 스킬을 재사용한다 — Hermes Agent를 처음 접했을 때 이 설명이 제일 먼저 마음에 걸렸습니다. "자기 개선형 에이전트"라는 표현은 마케팅 문구로 흘려들을 수 있는데, 이 메커니즘만큼은 구체적으로 어떻게 동작하는지 확인하고 싶었습니다.
솔직히 처음엔 회의적이었습니다. 쓸수록 성능이 오른다는 게 파인튜닝을 그럴듯하게 포장한 건지, 아니면 실제로 다른 무언가인지 — 결국 코드를 직접 파고들었습니다. Hermes는 LLM 호출 결과를 파일 시스템에 절차형 스킬로 굳히고, 이 스킬을 다음 세션의 시스템 프롬프트에 선택적으로 주입하는 방식으로 실질적인 성능 향상을 만들어냅니다. 파인튜닝이 아니라 외부 메모리 확장에 가깝습니다.
이 글에서는 그 메커니즘의 기반이 되는 5-Pillar 아키텍처를 하나씩 뜯어보고, 특히 SOUL.md가 왜 시스템 프롬프트의 첫 번째 슬롯에 위치하는지, prompt_builder.py가 왜 프런트매터(YAML로 작성된 파일 상단 메타데이터 블록)만 먼저 읽는지 — 설계 의도가 선명하게 보이는 지점까지 따라가 봅니다.
핵심 개념
5-Pillar: 다섯 개의 기둥이 맞물리는 방식
Hermes를 이해하는 가장 빠른 길은 다섯 가지 구성 요소가 서로 어떤 관계인지 파악하는 것입니다. 각각 독립적인 컴포넌트처럼 보이지만, 실제로는 유기적으로 맞물려 있습니다.
| Pillar | 파일 / 컴포넌트 | 핵심 역할 |
|---|---|---|
| Memory | MEMORY.md, USER.md |
세션 간 컨텍스트 유지 |
| Skills | ~/.hermes/skills/*.md |
절차 지식 재사용 |
| SOUL | ~/.hermes/SOUL.md |
에이전트 정체성·톤 정의 |
| Crons | state.db + 게이트웨이 데몬 |
능동적 스케줄링 |
| Self-Improvement | 자동 생성 루프 | 사용 경험 → 스킬 추출 |
Pillar 1 — 세션이 끝나도 기억이 남는 방식
MEMORY.md는 에이전트 자체 메모장, USER.md는 사용자 선호도와 작업 패턴을 기록합니다. 두 파일의 합산 토큰 한도가 약 1,300 토큰으로 제한돼 있어서, 뭘 남길지 우선순위를 강제로 생각하게 됩니다 — 처음에는 좀 답답하지만, 결국 "정말 중요한 것"만 남기게 되는 구조입니다.
가장 먼저 이해해야 할 것은 메모리 파일이 세션 시작 시 딱 한 번 로드되고 그 이후론 고정된다는 점입니다. 세션 도중에 파일을 업데이트해도 현재 세션의 프롬프트엔 반영되지 않습니다. 저도 처음엔 이게 버그인 줄 알았는데, 알고 보니 의도적인 설계였습니다 — 이유는 Pillar 3에서 바로 납득됩니다.
즉각적인 반영이 필요한 경우에는 세션을 재시작하는 방법을 활용할 수 있습니다.
Pillar 2 — 절차형 레시피 시스템, Skills
실제로 써보면서 가장 놀란 점은 스킬 파일의 구조가 얼마나 단순한가였습니다. YAML 프런트매터에 메타데이터, 마크다운 본문에 실제 절차 — 그게 전부입니다.
---
name: competitive-analysis
description: 경쟁사 주간 동향을 분석하고 Slack 요약을 전송하는 절차
trigger: [competitive, analysis, market research]
tier: 3
created_at: 2026-04-22T09:14:00Z
---
## 절차
1. 타깃 경쟁사 리스트를 USER.md에서 로드
2. 각 사이트의 최근 7일 변경사항 크롤링
3. 변경사항을 카테고리별로 분류 (제품, 가격, 채용)
4. 요약본 작성 후 Slack #competitive-intel 채널 전송
## 주의사항
- 크롤링 실패 시 3회 재시도 후 실패 알림
- 요약본은 500자 이내로 압축Progressive Disclosure:
prompt_builder.py는 스킬 파일의 프런트매터만 먼저 읽어 적합성을 판단합니다. 실제 본문은 해당 스킬이 필요하다고 판단될 때만 로드됩니다. 컨텍스트 윈도우를 아끼는 실용적인 설계입니다.
이 동작의 핵심 로직을 발췌하면 다음과 같습니다.
# agent/prompt_builder.py (핵심 발췌 — 개념 수준)
def load_skills_for_session(query: str) -> list[Skill]:
skills_dir = Path("~/.hermes/skills/").expanduser()
candidates = []
for skill_file in skills_dir.glob("*.md"):
# 1단계: 프런트매터만 파싱 (본문 미로드)
frontmatter = parse_frontmatter_only(skill_file)
relevance = score_relevance(frontmatter, query)
if relevance > THRESHOLD:
candidates.append((skill_file, frontmatter, relevance))
# 2단계: 상위 N개만 본문 로드
candidates.sort(key=lambda x: x[2], reverse=True)
return [load_full_skill(path) for path, _, _ in candidates[:MAX_SKILLS]]스킬이 수십 개로 늘어나도 프롬프트 크기가 폭발하지 않는 이유가 바로 이 두 단계 로딩 방식에 있습니다.
Pillar 3 — SOUL.md가 첫 번째 슬롯인 이유
SOUL.md는 에이전트의 어조, 가치관, 응답 스타일을 정의합니다. 그런데 단순한 설정 파일 이상의 의미가 있습니다.
시스템 프롬프트 조립 순서를 보면 SOUL.md가 슬롯 #1, 즉 맨 처음에 위치합니다.
[slot 1] SOUL.md
[slot 2] MEMORY.md + USER.md
[slot 3] 관련 스킬 프런트매터 → 선택된 스킬 본문
[slot 4] Context files (.hermes.md / AGENTS.md / CLAUDE.md)
[slot 5] 도구 사용 가이드
[slot 6] 모델별 지시사항 (Anthropic, OpenAI 등 제공사별 최적화 지시)Pillar 1에서 "왜 메모리가 세션 시작 시 고정되는가?"를 설명하겠다고 했는데, 답이 여기 있습니다. Anthropic과 OpenAI의 프롬프트 캐시는 안정적인 prefix가 있어야 캐시 히트가 발생하기 때문입니다. 세션마다 변하지 않는 SOUL.md를 앞에 두고, 상대적으로 안정적인 MEMORY.md를 그 뒤에 배치하면 캐시 히트율이 올라가고, 결과적으로 API 비용이 줄어듭니다. 성능이 아닌 경제적 이유에서 나온 설계 결정입니다.
# SOUL.md 현재 내용 확인
> read me your soul file
# 피드백으로 직접 업데이트 (에이전트가 파일을 수정)
> 너무 장황해. 핵심만 짧게 답해줘
> 공식적인 어조 그만. 편하게 말해줘Pillar 4 — 반응형에서 능동형으로, Crons
내장 게이트웨이 데몬이 60초마다 state.db를 확인해 예약 작업을 실행합니다. 격리된 에이전트 세션에서 실행되기 때문에 현재 대화에 영향을 주지 않습니다.
# 자연어로 스케줄 등록
> 매일 밤 12시에 스테이징 서버 로그를 분석하고 Slack에 요약 전송해줘이 명령 하나로 Hermes는 두 가지를 동시에 만들어냅니다 — cron job 등록 + 해당 절차를 담은 Tier 3 스킬 파일 생성. 그리고 동일 작업이 반복될수록 스킬은 점점 세련되어 갑니다.
Pillar 5 — 사용 경험이 절차로 굳어지는 Self-Improvement
이게 Hermes의 핵심 차별점입니다. Tier 3 스킬이 자동 생성되는 조건은 네 가지입니다.
- 단일 세션에서 5회 이상 도구 호출이 포함된 복합 작업 완료
- 작업이 멀티 스텝 구조를 가짐
- 에러 복구(error recovery) 또는 사용자 수정(user correction) 이 발생
- 사용자가 결과를 명시적으로 확인(confirm) 함
네 조건 모두 "이 작업이 반복될 가치가 있는가?"를 판단하기 위한 휴리스틱입니다. 에러 복구를 조건에 포함하는 이유가 흥미로운데, 에러 복구 과정 자체가 "어떤 함정이 있는지, 어떻게 피하는지"를 담고 있기 때문입니다.
그리고 v0.12.0부터는 자율 Curator가 7일 주기로 스킬 라이브러리를 채점·통합·정리합니다. 비슷한 스킬은 합치고, 실제로 쓰이지 않는 스킬은 우선순위를 낮춥니다. 완벽하진 않지만, 라이브러리가 무한정 쌓이는 문제를 막아주는 실용적인 장치입니다.
실전 적용
예시 1: Tier 3 스킬 자동 생성 흐름 전체 추적
사용자가 경쟁사 분석 작업을 요청
→ 에이전트가 7단계 멀티스텝 작업 수행 (12회 도구 호출)
→ 중간에 크롤링 실패 → 재시도 로직으로 복구 (에러 복구 발생)
→ 사용자: "완벽해, 이걸 매주 해줘" (명시적 확인)이 흐름이 네 조건을 모두 만족하면 다음 파이프라인이 실행됩니다.
Execute → 실제 작업 수행 (도구 호출, API 요청, 파일 처리 등)
Evaluate → 재사용 가치 판단 (5회 이상 도구 호출 + 멀티스텝 + 확인 여부)
Extract → 절차·에러 패턴·검증 단계를 세션 로그에서 추출
Write → ~/.hermes/skills/에 스킬 파일 생성
Validate → 도구 레지스트리 검증 + 위험 패턴 스캔
Discoverable → 다음 세션부터 프런트매터 스캔 대상에 포함아래 코드는 동작 방식을 설명하기 위한 의사 코드입니다. 실제 구현과 세부 인터페이스는 다를 수 있습니다.
# agent/skill_extractor.py (의사 코드 — 개념 설명용)
def should_generate_skill(session: Session) -> bool:
return (
session.tool_call_count >= 5
and session.is_multistep
and (session.had_error_recovery or session.had_user_correction)
and session.user_confirmed
)
def extract_procedure_steps(session: Session) -> list[str]:
steps = []
tool_calls = [tc for tc in session.tool_calls if tc.success]
for i, call in enumerate(tool_calls):
# 사용자 수정이 있었던 단계는 주의사항으로 마킹
if call.had_user_correction:
steps.append(
f"{i+1}. ⚠️ {call.description} (수정 포인트: {call.correction_note})"
)
else:
steps.append(f"{i+1}. {call.description}")
return steps
def extract_skill(session: Session) -> Skill:
procedure = extract_procedure_steps(session)
pitfalls = extract_error_patterns(session)
validation = extract_validation_steps(session)
return Skill(
name=generate_skill_name(session),
procedure=procedure,
pitfalls=pitfalls,
validation=validation,
tier=3,
)extract_procedure_steps가 에러 복구 단계를 ⚠️로 마킹해 남기는 방식이 포인트입니다. 단순한 성공 절차가 아니라 "어디서 조심해야 하는지"까지 스킬에 포착됩니다.
Validate 단계에서는 도구 레지스트리 검증과 함께 프롬프트 인젝션(AI 에이전트 맥락에서는 외부 입력이 에이전트 행동을 의도치 않게 변조하는 것 — 웹 보안의 SQL 인젝션과 유사한 개념이지만 대상이 LLM 프롬프트입니다), TODO, placeholder 같은 위험 패턴을 스캔합니다. 보안 레이어가 얇긴 하지만 없는 것보단 낫습니다.
생성된 스킬은 ~/.hermes/skills/에 저장되고, 다음 세션부터 프런트매터 스캔 대상에 포함됩니다. 생성된 그 세션에서는 사용할 수 없습니다.
예시 2: SOUL.md 커스터마이징으로 일관된 코딩 어시스턴트 만들기
---
# ~/.hermes/SOUL.md
---
## 정체성
나는 시니어 풀스택 개발자 스타일로 응답한다. 핵심을 먼저 말하고, 부연은 짧게.
## 코딩 스타일
- TypeScript strict mode 기본
- async/await만 사용 (Promise.then 금지)
- 2-space 들여쓰기
## 응답 원칙
- 500자 넘는 답변은 요약 먼저, 상세 내용은 접어서
- 코드 블록엔 언어 항상 명시
- 설명 없이 코드만 요청받으면 코드만 반환프로젝트별 컨텍스트는 .hermes.md로 따로 분리해두는 방식을 권장합니다. SOUL.md를 짧게 유지해야 캐시 히트율이 올라간다는 점을 여기서도 기억할 수 있습니다.
---
# 프로젝트 루트/.hermes.md
---
## 프로젝트 컨텍스트
- 스택: Next.js 15 + NestJS + PostgreSQL
- 테스트: 실제 DB 연결 필수 (mock 금지)
- 배포: Vercel (frontend) + Railway (backend)| 파일 | 범위 | 수정 주체 |
|---|---|---|
SOUL.md |
전역 (모든 프로젝트) | 사용자 + 에이전트 |
USER.md |
전역 (사용자 선호) | 에이전트 자동 |
.hermes.md |
프로젝트별 | 사용자 |
예시 3: Cron + 스킬 조합으로 DevOps 워크플로 자동화
> 매일 오전 9시에 GitHub Actions 실패 목록을 정리하고
심각도별로 분류해서 Slack #dev-alerts에 보내줘.
실패가 없으면 메시지 보내지 말고.Hermes는 이 요청을 처리하면서 내부적으로 다음을 동시에 수행합니다.
# 자동 생성된 스킬 파일 예시
---
name: github-actions-failure-report
description: GitHub Actions 실패를 심각도별 분류 후 Slack 전송
trigger: [github actions, CI failure, daily report]
tier: 3
cron: "0 9 * * *"
---
## 절차
1. GitHub API로 최근 24시간 워크플로 실행 결과 조회
2. 실패 항목 심각도 분류 (critical / warning / info)
3. critical 항목 없으면 실행 중단
4. 요약 메시지 포맷팅 후 Slack 전송
## 에러 처리
- GitHub API 타임아웃 시 3회 재시도
- Slack 전송 실패 시 이메일 폴백cron 필드가 스킬 파일에 직접 포함된다는 점이 눈에 띕니다. Pillar 4(Crons)와 Pillar 2(Skills)가 단순히 공존하는 게 아니라 하나의 파일로 통합되는 방식입니다.
장단점 분석
장점
| 항목 | 내용 |
|---|---|
| 누적 학습 | 20개 이상 자기 생성 스킬 보유 시 유사 작업 40% 속도 향상 보고 |
| 컨텍스트 효율 | Progressive Disclosure로 불필요한 토큰 소모 최소화 |
| 캐시 최적화 | 불변 시스템 프롬프트로 Anthropic/OpenAI 프롬프트 캐시 최대 활용 |
| 선언적 설정 | SOUL.md, MEMORY.md, USER.md 모두 일반 마크다운으로 직접 편집 가능 |
| 모델 무관 | Anthropic, OpenAI API 모두 호환 |
| 오픈소스 생태계 | agentskills.io에 520+ 커뮤니티 스킬, 공식 Anthropic 스킬 16종 포함 |
단점 및 주의사항
| 항목 | 내용 | 대응 방안 |
|---|---|---|
| 프롬프트 인젝션 위험 | 5회 도구 호출 임계값을 넘긴 악의적 세션이 오염된 스킬을 영구 저장할 수 있음 (Issue #25833) | 자동 생성 스킬 정기 감사, user-locked 스킬 적극 활용 |
| 스킬 정확도 미보장 | 자동 생성 스킬에 메커니즘 수준의 정확성 보장 없음 | Curator 채점 결과 주기적 확인, 중요 스킬은 수동 검토 |
| 메모리 크기 제한 | MEMORY.md + USER.md 합산 약 1,300 토큰 한도 | 우선순위 높은 항목만 유지, 나머지는 프로젝트별 .hermes.md로 분리 |
| 미드-세션 반영 불가 | 세션 중 메모리 업데이트가 현재 프롬프트에 미적용 | 즉각 반영 필요 시 세션 재시작 |
prompt_builder.py 수정 위험 |
전역 제품 변경 파일이므로 일반 커스터마이즈 용도로 부적합 | 커스터마이즈는 SOUL.md, USER.md, .hermes.md 활용 |
user-locked 스킬: 사용자가 특정 스킬을 잠금 처리하면 에이전트가 읽기만 가능하고 수정은 불가능합니다. 자동 개선이 필요 없는 안정적인 절차에 적합합니다. GitHub Issue #17583에서 커뮤니티 논의가 진행 중입니다.
실무에서 가장 흔한 실수
-
SOUL.md를 너무 길게 작성하는 것 — SOUL.md는 시스템 프롬프트 첫 번째 슬롯이지만, 길어질수록 캐시 히트율 이점이 줄어들고 컨텍스트를 잡아먹습니다. 핵심 정체성만 담고 나머지는 USER.md나
.hermes.md로 분산시키는 방식이 효과적입니다. -
자동 생성 스킬을 검토 없이 방치하는 것 — Curator가 7일 주기로 채점·정리하지만 완벽하지 않습니다. 특히 에러 복구 과정에서 생성된 스킬은 특수 상황의 임시 해법을 일반 절차로 굳혀버릴 수 있습니다.
~/.hermes/skills/를 주기적으로 살펴보는 습관이 도움됩니다. -
세션 중간에 중요한 작업을 확인(confirm)해주지 않는 것 — Tier 3 스킬 생성 조건 중 하나가 "사용자의 명시적 확인"입니다. "완벽해", "이걸 앞으로도 써줘" 같은 응답이 스킬 생성 트리거 역할을 합니다. 반대로, 실험적인 접근을 시도할 때 무심코 확인해주면 원치 않는 스킬이 생성될 수 있습니다.
마치며
이 구조를 이해하고 나면, Hermes를 단순히 "더 똑똑한 채팅봇"으로 쓰는 것과 "내 워크플로에 맞춰 성장하는 절차 라이브러리"로 쓰는 것 사이의 차이가 선명해집니다. 어떻게 쓰느냐가 결국 어떤 에이전트가 되는가를 결정하는 구조입니다.
지금 바로 시작해볼 수 있는 3단계:
-
~/.hermes/SOUL.md를 직접 열어 에이전트의 응답 어조와 코딩 스타일을 본인 선호에 맞게 작성해보세요.> read me your soul file명령으로 현재 상태를 확인할 수 있고, 피드백 한 줄로 에이전트가 직접 업데이트합니다. -
주 1회 이상 반복하는 작업을 3~4회 수행하면서 Tier 3 스킬 자동 생성 조건을 자연스럽게 충족시켜 볼 수 있습니다. 작업 완료 시 "완벽해" 또는 "이걸 앞으로도 써줘" 같은 명시적 확인 응답을 남기면 스킬 생성이 트리거됩니다.
-
~/.hermes/skills/디렉터리를 2주에 한 번 정도 열어 자동 생성된 스킬을 살펴보세요. 의도와 다른 스킬은 삭제하고, 자주 쓰이는 스킬은 user-locked로 보호해두면 안정적인 운영이 됩니다.
참고 자료
- Hermes Agent 공식 문서
- Architecture | Hermes Agent — NousResearch
- Prompt Assembly | Hermes Agent
- Skills System | Hermes Agent
- Creating Skills | Hermes Agent
- GitHub — NousResearch/hermes-agent
- Hermes Agent Five Pillars: Memory, Skills, Soul, Crons, and Self-Improvement | MindStudio
- Hermes Agent memory: SOUL.md, MEMORY.md and state.db | LumaDock
- Inside Hermes Agent: What 'Self-Improving AI Agent' Actually Means in Production | Saulius blog
- Self-created skills lack mechanism-level guarantees (Issue #25833) | GitHub
- Skills: user-locked vs self-improving tiers (Issue #17583) | GitHub
- Hermes Agent Masterclass | Daily Dose of Data Science
- The Compounding Agent: Why Hermes Is More Than Just a Pretty TUI
- Context and Prompt Management | DeepWiki