Hermes는 어떻게 스스로 배워가는가: 코드로 뜯어본 Skill Self-Evolution Architecture
Hermes의 self-evolution은 모델 파라미터를 바꾸는 이야기가 아니다. 작업 경험을 Skill이라는 절차적 기억으로 저장하고, 다음 작업에 다시 주입하며, patch와 review를 통해 점진적으로 개선하는 구조다.
대부분의 LLM은 매번 처음부터 답을 만든다. 어제 어떤 방식으로 문제를 풀었는지, 그 과정에서 무엇이 잘 먹혔는지, 다음번에도 같은 절차를 따라야 하는지 같은 정보는 모델 안에 안정적으로 남아 있지 않다. 대화 맥락이 길게 이어질 때는 학습이 누적된 것처럼 보일 수 있지만, 세션이 바뀌고 작업이 바뀌면 다시 처음으로 돌아간다.
사람은 그렇게 일하지 않는다. 문제를 몇 번 풀다 보면, 그 경험은 단순한 기억이 아니라 절차가 된다. 어떤 종류의 버그는 먼저 로그 구조부터 봐야 하고, 어떤 초기 로딩 문제는 이미지보다 번들 분할부터 확인하는 편이 낫다. 중요한 것은 정답을 하나 더 아는 일이 아니라, 어떤 순서로 접근해야 하는지 몸에 붙는 일이다.
Hermes의 Skill 시스템은 바로 그 간극을 겨냥한다. 이 글에서 보려는 질문은 하나다. Hermes는 어떻게 작업 경험을 재사용 가능한 절차로 바꾸고, 그 절차를 다시 자신의 다음 행동에 연결하는가. 결론부터 말하면, Hermes의 self-evolution은 모델 파라미터를 바꾸는 이야기가 아니다. 훨씬 더 현실적이고, 그래서 더 흥미로운 방식이다.
먼저 선을 긋고 가자: 이 글에서 말하는 self-evolution은 무엇인가
“에이전트가 스스로 진화한다”는 표현은 쉽게 과장으로 흐른다. 그래서 먼저 범위를 분명히 하는 편이 낫다. 이 글에서 말하는 self-evolution은 모델 자체를 재학습하는 일도 아니고, 파라미터나 내부 가중치를 직접 수정하는 일도 아니다. Hermes가 실제로 하는 일은 작업 중 의미 있는 해결 절차를 포착하고, 그것을 Skill이라는 구조화된 문서로 저장한 뒤, 이후 비슷한 작업이 들어오면 다시 불러와 사용하고, 사용하면서 틀린 부분을 patch하고 빠진 부분을 보완하며 필요하면 재구성하는 것이다.
즉, Hermes의 self-evolution은 “내부 모델의 진화”가 아니라 외부화된 절차적 기억의 진화에 가깝다. 이 표현이 훨씬 정확하다.
왜 Memory가 아니라 Skill인가
Hermes에는 이미 메모리 개념이 있다. 그런데 self-evolution의 중심은 Memory가 아니라 Skill이다. 이 차이를 구분하지 않으면 구조가 흐려진다.
| 구분 | Memory | Skill |
|---|---|---|
| 저장하는 것 | 사용자 정보, 선호, 반복되는 사실 | 문제 해결 절차, 작업 방법론 |
| 예시 | ”사용자는 한국어를 선호한다" | "React 성능 문제는 이 순서로 디버깅한다” |
| 역할 | 맥락 유지 | 행동 지침 제공 |
| 성격 | 선언적 기억 | 절차적 기억 |
이 구분은 꽤 본질적이다. 사용자가 누구인지 아는 것과, 무엇을 어떻게 해야 하는지 아는 것은 서로 다른 종류의 지식이다. 전자는 문맥 이해에 가깝고, 후자는 실행 전략에 가깝다. Hermes는 이 둘을 분리하고, self-evolution의 핵심을 후자, 즉 절차적 기억 쪽에 둔다.
Skill은 결국 무엇인가
Hermes에서 Skill은 단순한 메모 파일이 아니다. “이런 상황에서 이런 절차를 따르라”는 작업 지침에 가깝다. 실제 구현에서는 SKILL.md라는 문서 단위로 저장되며, YAML frontmatter와 본문을 가진 구조화된 마크다운이다.
예를 들면 이런 식이다.
---
name: react-performance-debug
description: React 앱의 렌더링 성능 문제를 진단하고 해결하는 절차
platforms: [macos, linux, windows]
---
# React Performance Debug
## When to Use
- 사용자가 "렌더링이 느리다"고 말할 때
- React DevTools에서 렌더링 시간이 비정상적으로 길 때
## Procedure
1. `npx react-devtools`로 프로파일링 시작
2. 병목 컴포넌트를 식별
3. 상태 구조와 렌더링 경계를 점검
4. 불필요한 리렌더를 줄인다
이 형식에서 중요한 것은 문서의 외형이 아니라 구조다. Skill은 보통 세 가지를 담는다. 언제 써야 하는지, 어떤 순서로 해야 하는지, 어떤 함정을 피해야 하는지다. 다시 말해 Skill은 “알고 있는 사실”이 아니라 “반복 가능한 절차”를 담는 그릇이다.
이제부터 self-evolution은 이 절차를 어떻게 만들고, 어떻게 수정하고, 어떻게 다시 행동에 연결하느냐의 문제로 바뀐다.
Hermes는 언제 “이건 배울 가치가 있다”고 판단하는가
아무 작업이나 다 Skill로 만들면 시스템은 금방 쓰레기장이 된다. 반대로 너무 엄격하면 정작 중요한 패턴을 놓친다. 그래서 self-evolution 시스템에서 가장 먼저 중요한 것은 저장 형식이 아니라 학습 트리거다.
Hermes는 이 지점을 두 층으로 처리한다. 하나는 시스템 프롬프트 수준의 가이드이고, 다른 하나는 런타임 수준의 nudge 트리거다.
시스템 프롬프트는 무엇을 말하는가
agent/prompt_builder.py에는 다음과 같은 가이드가 들어 있다.
SKILLS_GUIDANCE = (
"After completing a complex task (5+ tool calls), fixing a tricky error, "
"or discovering a non-trivial workflow, save the approach as a "
"skill with skill_manage so you can reuse it next time.\n"
"When using a skill and finding it outdated, incomplete, or wrong, "
"patch it immediately with skill_manage(action='patch') ..."
)
이 문장은 의외로 많은 것을 말해준다. Hermes는 Skill 저장 타이밍을 복잡한 작업을 끝냈을 때, 어려운 오류를 해결했을 때, 비사소한 워크플로를 발견했을 때, 기존 스킬이 틀렸거나 낡았다는 걸 알게 되었을 때로 규정한다. 즉, self-evolution의 단위는 “성공했다”가 아니라 재사용 가능한 해결 방식이 나왔다는 데 있다.
이 기준은 중요하다. Hermes는 결과물이 아니라 해결 방법을 축적하려 하기 때문이다.
nudge: Hermes는 시간을 재지 않고 복잡도를 센다
실제 트리거는 run_agent.py 쪽에 있다. 초기화 코드를 보면 Skill 관련 카운터가 다음처럼 잡혀 있다.
self._iters_since_skill = 0
self._skill_nudge_interval = 10
self._skill_nudge_interval = int(skills_config.get("creation_nudge_interval", 10))
그리고 대화 루프가 지나가며 누적된 카운터를 보고 리뷰를 띄울지 결정한다.
if (
self._iters_since_skill >= self._skill_nudge_interval
and "skill_manage" in self.valid_tool_names
):
_should_review_skills = True
self._iters_since_skill = 0
실제로 skill_manage를 사용하면 카운터를 다시 초기화한다.
elif function_name == "skill_manage":
self._iters_since_skill = 0
여기서 중요한 점은 Hermes가 “10분마다 배운다” 같은 시간 기반 트리거를 쓰지 않는다는 것이다. Hermes는 시간을 재지 않고 복잡도를 센다. 간단한 질문은 짧게 끝나지만, 복잡한 작업은 도구 호출과 시도 횟수가 늘어난다. 그러면 카운터가 차고, 그 순간 “이 작업에는 재사용할 만한 패턴이 있었을지도 모른다”는 신호로 해석한다. nudge가 시계가 아니라 작업의 밀도를 측정하는 셈이다.
학습은 메인 세션에서 하지 않는다
Hermes의 self-evolution 설계에서 가장 눈에 띄는 부분은 학습과 사용자 응답을 분리했다는 점이다. 많은 시스템은 배움을 메인 루프 안에 욱여넣는다. 그러면 사용자가 원하는 작업을 처리하는 흐름과 시스템이 자기 경험을 정리하는 흐름이 충돌하게 된다.
Hermes는 이 문제를 분리한다. run_agent.py의 _spawn_background_review()를 보면 별도의 리뷰 에이전트를 띄운다.
review_agent = AIAgent(
model=self.model,
max_iterations=8,
quiet_mode=True,
platform=self.platform,
provider=self.provider,
)
review_agent._memory_store = self._memory_store
review_agent._memory_enabled = self._memory_enabled
review_agent._user_profile_enabled = self._user_profile_enabled
review_agent._memory_nudge_interval = 0
review_agent._skill_nudge_interval = 0
review_agent.run_conversation(
user_message=prompt,
conversation_history=messages_snapshot,
)
그리고 stdout/stderr는 /dev/null로 돌린다. 사용자는 메인 작업의 결과만 보고, 학습 프로세스는 뒤에서 조용히 일어난다. 이 구조를 한 번 정리하면 다음과 같다.
사용자 요청
→ 메인 에이전트가 작업 수행
→ 사용자에게 최종 응답 전달
→ 대화 스냅샷을 별도 리뷰 에이전트에 전달
→ 재사용 가능 패턴 검토
→ Skill 생성/수정 또는 "Nothing to save"
이 분리가 중요한 이유는 단순하다. 학습이 메인 작업을 방해하면 사용자는 그 기능을 싫어하게 된다. 반대로 학습이 뒤로 빠지면, 사용자 입장에서는 “일을 잘 해주는 에이전트”로 남으면서도, 시스템은 별도로 “배움을 축적하는 에이전트”가 될 수 있다.
리뷰 프롬프트는 무엇을 배울지 제한한다
self-evolution이 성립하려면 백그라운드 리뷰가 아무거나 저장하지 않아야 한다. Hermes는 이 판단을 리뷰 프롬프트에 박아둔다.
_SKILL_REVIEW_PROMPT = (
"Review the conversation above and consider saving or updating a skill if appropriate.\n\n"
"Focus on: was a non-trivial approach used to complete a task that required trial "
"and error, or changing course due to experiential findings along the way, or did "
"the user expect or desire a different method or outcome?\n\n"
"If a relevant skill already exists, update it with what you learned. "
"Otherwise, create a new skill if the approach is reusable.\n"
"If nothing is worth saving, just say 'Nothing to save.' and stop."
)
이 문장을 곱씹어보면 판단 축이 명확하다. 비사소한 접근이 있었는지, 시행착오가 있었는지, 경험적 발견 때문에 경로를 바꿨는지, 재사용 가능한지, 이미 유사 Skill이 있으면 새로 만들지 말고 업데이트할 수 있는지다. 여기서 중요한 것은 “정답”이 아니라 “패턴”이다. Hermes는 이번 답변이 맞았는지를 저장하려는 게 아니라, 이번에 어떤 방식으로 문제를 풀었는지를 저장하려고 한다.
Skill CRUD: self-evolution의 실체는 결국 skill_manage다
Hermes가 self-evolution을 말할 수 있는 이유는 학습된 절차를 실제로 생성, 수정, 삭제할 수 있는 인터페이스가 있기 때문이다. 그 인터페이스가 tools/skill_manager_tool.py의 skill_manage다. 지원 액션은 여섯 가지다.
| 액션 | 역할 | 언제 쓰나 |
|---|---|---|
create | 새 Skill 생성 | 처음 배우는 패턴일 때 |
edit | SKILL.md 전체 재작성 | 구조를 크게 갈아엎을 때 |
patch | 부분 수정 | 스킬을 점진적으로 개선할 때 |
delete | Skill 삭제 | 명시적으로 제거할 때 |
write_file | 보조 파일 추가 | reference/template/script 첨부 |
remove_file | 보조 파일 삭제 | 보조 자산 정리 |
이 중에서 정말 중요한 것은 edit보다 patch다. self-evolution은 대부분 전면 교체가 아니라 점진적 수정으로 일어나기 때문이다.
create: 무조건 저장하지 않고, 먼저 검증부터 한다
Skill 생성 흐름은 생각보다 보수적이다. _create_skill()은 이름과 카테고리를 검증하고, frontmatter와 크기를 확인한 뒤, 기존 Skill과 충돌하는지 검사한다. 그다음 atomic write를 수행하고, 보안 스캔을 통과하지 못하면 롤백한다.
def _create_skill(name: str, content: str, category: str = None):
err = _validate_name(name)
err = _validate_category(category)
err = _validate_frontmatter(content)
err = _validate_content_size(content)
existing = _find_skill(name)
if existing:
return {"success": False, "error": ...}
_atomic_write_text(skill_md, content)
scan_error = _security_scan_skill(skill_dir)
if scan_error:
shutil.rmtree(skill_dir, ignore_errors=True)
return {"success": False, "error": scan_error}
이 흐름이 시사하는 바는 분명하다. Hermes는 자동 학습을 허용하지만, 그 자동 학습을 무검증 쓰기로 구현하지는 않는다. 오히려 반대다. 에이전트가 자기 행동 지침을 수정할 수 있기 때문에, 사람이 직접 쓰는 문서보다 더 엄격한 검증이 필요하다고 보는 편에 가깝다.
patch: Hermes가 진짜로 잘 설계한 지점
edit는 전체를 덮어쓰는 방식이다. 필요할 때는 있지만, 기본 진화 단위로 쓰기에는 너무 거칠다. 실전에서 좋은 절차는 대개 “이 단계 하나를 먼저 해야 했네”, “이 경우엔 예외를 하나 더 적어야겠네”, “이 순서는 뒤집는 게 더 낫겠네”처럼 부분 수정으로 발전한다. Hermes는 이를 patch 중심으로 설계한다.
from tools.fuzzy_match import fuzzy_find_and_replace
new_content, match_count, _strategy, match_error = fuzzy_find_and_replace(
content, old_string, new_string, replace_all
)
여기서 핵심은 단순 문자열 치환이 아니라 fuzzy_find_and_replace라는 점이다. LLM은 예전 출력을 글자 단위로 완벽하게 재현하지 못한다. 공백이 다를 수 있고, 인덴트가 다를 수 있고, 표현이 조금 바뀔 수 있다. 만약 patch가 exact match만 허용하면 self-evolution은 금방 좌초한다. Hermes는 이 현실을 인정하고, 의미상 같은 부분을 찾아 바꾸는 방식으로 간다. 이건 단순 구현 디테일이 아니라, self-evolution이 실제로 굴러가느냐 마느냐를 가르는 설계다.
저장 방식도 진화 친화적으로 설계되어 있다: Atomic Write
에이전트가 Skill을 자주 수정한다는 것은 저장 실패나 중간 상태가 시스템 전체 품질에 직접 영향을 준다는 뜻이다. 그래서 Hermes는 파일 저장도 그냥 하지 않는다.
def _atomic_write_text(file_path: Path, content: str, encoding: str = "utf-8") -> None:
file_path.parent.mkdir(parents=True, exist_ok=True)
fd, temp_path = tempfile.mkstemp(
dir=str(file_path.parent),
prefix=f".{file_path.name}.tmp.",
suffix="",
)
try:
with os.fdopen(fd, "w", encoding=encoding) as f:
f.write(content)
os.replace(temp_path, file_path)
except Exception:
os.unlink(temp_path)
raise
os.replace()를 쓰는 이유는 분명하다. 쓰는 도중 프로세스가 죽더라도 파일이 반쯤 깨진 상태로 남지 않게 하려는 것이다. Skill은 결국 외부화된 절차 기억이다. 그 기억 저장소가 불안정하면 self-evolution은 금방 “쌓을수록 망가지는 시스템”이 된다. Hermes는 적어도 그 함정을 피하려고 한다.
그런데 스스로 배우게 둘 거면, 악성 Skill은 어떻게 막나
여기서부터가 중요하다. 에이전트가 자신의 행동 지침을 수정할 수 있다면, 가장 먼저 떠올려야 할 질문은 이것이다. 그럼 프롬프트 주입이나 악의적 패턴을 Skill로 저장해버리는 건 어떻게 막는가.
Hermes는 이 문제를 tools/skills_guard.py로 방어한다.
출처별 설치 정책
먼저 INSTALL_POLICY가 있다.
INSTALL_POLICY = {
# safe caution dangerous
"builtin": ("allow", "allow", "allow"),
"trusted": ("allow", "allow", "block"),
"community": ("allow", "block", "block"),
"agent-created": ("allow", "allow", "ask"),
}
이 정책 표는 단순 보안 옵션이 아니다. self-evolution의 안전장치다. Hermes는 “에이전트가 직접 만들었으니 무조건 믿자”라고 하지 않는다. 오히려 agent-created라는 출처를 별도 카테고리로 두고 다룬다. 즉, 자기 생성 Skill도 신뢰 모델의 바깥에 놓지 않는다.
무엇을 탐지하나
스캐너는 꽤 폭넓은 위협 패턴을 본다. 비밀 유출 패턴, 프롬프트 주입 패턴, 파괴적 명령, 지속성이나 백도어성 행위, 난독화, 자격 증명 유출, 보이지 않는 유니코드 문자가 그 대상이다.
| 범주 | 예시 |
|---|---|
| 정보 탈취 | curl ... ${API_KEY} |
| 프롬프트 주입 | ignore previous instructions |
| 파괴적 명령 | rm -rf / |
| 지속성 설치 | crontab, authorized_keys |
| 난독화 | base64 -d | sh, eval() |
| 자격증명 노출 | 토큰/키 패턴 |
이 지점은 아주 중요하다. Hermes의 self-evolution은 자율성을 밀어붙인 시스템이 아니라, 자율성 위에 가드레일을 얹은 시스템이다. 이런 가드레일 없이 self-evolution을 말하는 것은 사실상 공상에 가깝다.
배운 Skill은 어디로 들어가나: 다시 행동으로 주입되는 경로
학습이 저장만 되고 끝나면 그것은 아카이브일 뿐이다. self-evolution이 되려면 저장된 Skill이 이후의 행동 생성 과정 안으로 다시 들어와야 한다. Hermes는 이 주입 경로를 두 단계로 만든다.
1) 시스템 프롬프트에 Skill 인덱스를 넣는다
build_skills_system_prompt()는 대화 시작 시 Skill 목록을 시스템 프롬프트에 넣는다.
result = (
"## Skills (mandatory)\n"
"Before replying, scan the skills below. If one clearly matches your task, "
"load it with skill_view(name) and follow its instructions. "
"If a skill has issues, fix it with skill_manage(action='patch').\n"
"\n"
"<available_skills>\n"
+ "\n".join(index_lines) + "\n"
"</available_skills>\n"
"\n"
"If none match, proceed normally without loading a skill."
)
여기서 구조가 좋다. 모든 Skill 전문을 통째로 넣지 않고 먼저 인덱스만 보여준다. 1차로 이름과 설명만 스캔하고, 지금 작업과 맞는 것이 있으면 skill_view(name)로 전문을 로드한다. Skill이 많아질수록 이런 설계는 더 중요해진다.
2) 필요하면 명시적으로 직접 불러올 수도 있다
자동 매칭만 있는 구조는 아니다. 사용자가 slash command나 명시적 호출로 특정 Skill을 직접 활성화할 수도 있다. 이렇게 되면 Skill 재사용 경로가 두 개가 된다. 하나는 시스템이 현재 작업과 맞는 Skill을 골라 로드하는 자동 경로이고, 다른 하나는 사용자가 특정 Skill을 직접 활성화하는 명시 경로다. 이 두 경로 덕분에 Skill은 저장소에 썩지 않고, 실제 행동 루프 안으로 다시 들어온다.
그래서 이 구조가 실제로 어떻게 진화처럼 보이는가
이제 이 구조가 실제 작업에서 어떻게 누적되는지 보면 더 분명해진다. 다음은 하나의 흐름을 단순화한 시나리오다.
처음에는 새로운 절차가 생긴다
어떤 사용자가 Next.js 앱 초기 로딩이 너무 느리다고 요청한다. 에이전트는 번들 분석을 하고, 캐시 전략을 보고, 이미지 최적화를 검토하고, 코드를 조금 손본다. 여러 번 도구를 호출하고 시행착오도 겪는다. 결국 문제를 해결한다. 이 작업이 끝난 뒤 nudge가 발동하고, 백그라운드 리뷰 에이전트가 대화 스냅샷을 보고 판단한다. “이건 단순 답변이 아니라 재사용 가능한 최적화 절차다.” 그 결과 nextjs-initial-load 같은 Skill이 생성된다.
그다음에는 비용이 줄어든다
며칠 뒤 다른 프로젝트에서도 비슷한 초기 로딩 이슈가 들어온다. 이번에는 Hermes가 이미 Skill 인덱스 안에 관련 패턴이 있다는 것을 안다. skill_view()로 내용을 불러오고, 이전보다 훨씬 적은 시행착오로 문제를 푼다. 처음에는 15번의 도구 호출이 필요했던 작업이, 이제는 5번 안쪽으로 줄 수 있다. self-evolution이 느낌이 아니라 실제 작업 비용 감소로 드러나는 순간이다.
사용하면서 수정이 일어난다
이번에는 같은 Next.js 문제인데, 로딩은 빨라졌지만 폰트 깜빡임이 남아 있다. 이전 Skill에는 font preloading 단계가 없었다. 에이전트는 그 누락을 발견하고, 기존 Skill에 해당 절차를 patch한다. 좋은 Skill은 처음부터 완성되지 않는다. 실전에서 부딪히며 조금씩 좋아진다.
축적이 쌓이면 구조 자체가 바뀐다
시간이 지나 여러 프로젝트에 쓰다 보면, 절차 순서 자체가 비효율적이라는 것을 알게 될 수도 있다. 그때는 부분 수정이 아니라 구조 재편이 필요하다. 이 경우 edit가 동원될 수 있다. 즉, Hermes의 self-evolution은 처음 배우기, 사용하며 보완하기, 축적된 경험을 바탕으로 재구성하기라는 세 단계를 모두 포괄한다. 이 세 단계가 함께 돌아갈 때 비로소 “진화”라는 말이 어느 정도 성립한다.
이 설계가 좋은 이유
이제 왜 이 구조가 잘 짜였는지 정리할 차례다.
학습이 메인 UX를 망치지 않는다
학습이 메인 세션 안에 끼어들면 사용자는 “쓸데없이 복잡하고 느린 에이전트”라고 느끼게 된다. Hermes는 그걸 피한다. 사용자는 작업 결과만 받고, 학습은 뒤에서 조용히 일어난다. 이건 단순히 예쁜 구현이 아니라 기능이 오래 살아남기 위한 조건이다.
진화의 기본 단위를 patch로 잡았다
실전 지식은 대개 patch로 발전한다. 전체 문서를 매번 다시 쓰는 방식은 유지되지 않는다. Hermes가 fuzzy patch를 중심에 둔 건, LLM 기반 시스템에서 self-evolution이 실제로 굴러가게 만드는 현실적인 선택이다.
Memory와 Skill을 분리했다
“누구를 상대하는가”와 “어떻게 행동할 것인가”를 분리해둔 것은 에이전트 아키텍처에서 꽤 좋은 선택이다. 이 분리 덕분에 사용자 맥락은 맥락대로 쌓이고, 절차적 지식은 절차적 지식대로 진화할 수 있다.
안전장치를 루프 안에 넣었다
보안 스캐너와 설치 정책이 바깥에 따로 있는 것이 아니라 생성과 수정 루프 안으로 들어와 있다. 즉, self-evolution이 일어날 때마다 항상 가드레일도 같이 작동한다. 이건 아주 중요하다. 자가 진화 시스템은 보통 “스스로 학습한다”는 문장만 크게 보이는데, 실제로는 “무엇을 배우지 못하게 막느냐”가 더 중요할 때가 많다.
그렇다고 완성형은 아니다
물론 이 구조가 완벽하다고 보기는 어렵다. 오히려 여기서부터 다음 질문이 나온다.
Skill의 품질은 누가 평가하는가
Hermes는 악성 패턴은 막는다. 하지만 무해하지만 별로인 스킬까지 자동으로 걸러주지는 못한다. 틀린 해결 절차가 저장될 수 있고, 더 좋은 접근법이 나와도 오래된 스킬이 남아 있을 수 있으며, 스킬이 자주 쓰이는지 실제로 효과가 있는지에 대한 평가 메트릭도 약하다.
아직 selection pressure는 약하다
지금 Hermes의 self-evolution은 “기억하고, 다시 쓰고, 고친다”까지는 꽤 강하다. 하지만 진짜 진화처럼 보이려면 여기에 선택 압력이 더 붙어야 한다. 예를 들면 사용 빈도, 재사용 성공률, 작업 시간 절감 효과, patch 빈도, 장기 미사용 Skill의 자동 감쇠, 서로 비슷한 Skill 간 병합 후보 탐지 같은 지표가 필요하다. 지금의 Hermes는 self-evolution의 뼈대는 잘 갖췄지만, 그 진화를 압축하고 정제하는 평가지표 계층은 아직 약한 편이다. 다만 바로 이 지점이 앞으로 가장 재밌게 확장될 수 있는 영역이기도 하다.
정리: Hermes의 self-evolution은 경험을 절차로 바꾸는 루프다
전체를 한 문장으로 압축하면 이렇다. Hermes의 Skill self-evolution은 작업 경험을 절차적 기억으로 저장하고, 그 기억을 다음 작업에 다시 주입하며, 사용 과정에서 patch와 review를 통해 점진적으로 개선하는 구조다.
작업 수행
→ 반복/복잡도 누적
→ nudge 발동
→ 백그라운드 리뷰
→ Skill 생성 또는 수정
→ 다음 작업에서 Skill 재사용
→ 재사용 결과를 바탕으로 다시 수정
여기서 핵심 부품은 다섯 가지다. nudge는 배울 타이밍을 감지하고, background review는 메인 작업과 분리된 학습을 수행하며, skill_manage는 생성과 수정과 삭제 인터페이스를 제공하고, skills_guard는 위험한 학습을 차단하고, build_skills_system_prompt는 학습된 절차를 다음 행동에 다시 연결한다. 이 다섯 개가 연결되면서 Hermes는 단순히 답을 잘하는 에이전트가 아니라, 작업하면서 점점 더 절차를 축적하는 에이전트가 된다.
나는 바로 이 점이 Hermes Skill 시스템의 가장 흥미로운 지점이라고 본다. self-evolution을 거창하게 포장하지 않고, 실제 운영 가능한 수준의 구조로 끌어내렸기 때문이다. 모델을 재학습하지 않아도 에이전트는 충분히 더 나아질 수 있다. 단, 그 더 나아짐은 파라미터 안이 아니라 절차적 기억의 루프 위에서 일어난다.
Hermes는 그 사실을 꽤 잘 구현한 사례다.
참고 코드 위치
hermes-agent/agent/prompt_builder.pySKILLS_GUIDANCEbuild_skills_system_prompt()
hermes-agent/run_agent.py_iters_since_skill_skill_nudge_interval_SKILL_REVIEW_PROMPT_spawn_background_review()
hermes-agent/tools/skill_manager_tool.py_create_skill()_patch_skill()_atomic_write_text()
hermes-agent/tools/skills_guard.pyINSTALL_POLICY- threat pattern scanning
Subscribe call to action
이 글이 맞았다면, 다음 글도 같은 밀도로 보내드릴게요.
조금은 어렵게 느껴질 수 있어도 괜찮습니다. 업계에서 부딪히며 얻은 감각과 개인적으로 깊게 공부한 내용을 바탕으로, 빨리 소비되는 정보보다 오래 남는 맥락을 남기려 합니다.