[LazyClaude 심층 5] Hyper Agent — 스스로 개선되는 sub-agent
메타-LLM이 sub-agent의 systemPrompt를 외과적으로 편집하고, .bak.md로 한 번에 되돌린다
LazyClaude 심층 5편. Sub-agent를 수동으로 다듬는 것 도 노동이다. 기준이 명확하다면, 그 노동도 LLM이 한다.
무엇을 푸는가
Claude Code의 sub-agent는 ~/.claude/agents/<name>.md에 systemPrompt·tools·description을 둔 마크다운 파일이다. 한 번 만들면 거의 안 건드린다. 그런데 쓰면서 알게 되는 것 이 누적되는 자리이기도 하다 — “이 부분은 늘 헛도네”, “툴 X는 안 써”. 이걸 손으로 정리하는 비용이 의외로 크다.
Hyper Agent는 이 정리를 메타-LLM(주로 Opus)에게 위임한다. 기준은 사용자가 정한 Objective 와 Refine targets, 그리고 그동안의 사용 history.
작동 모델
┌─────────────────┐ propose patch ┌────────────────┐
│ meta-LLM │ ──────────────────▶│ agent file │
│ (Opus) │ │ X.md │
│ │ ◀────────────────── │ ─ systemPrompt│
└─────────────────┘ read history, │ ─ tools │
objective │ ─ description │
└────────────────┘
atomic save with backup
- Objective: 이 sub-agent가 이상적으로 어떻게 동작해야 하는지 (자유 텍스트)
- Refine targets: 메타-LLM이 건드릴 영역 —
systemPrompt/tools/description중 골라서 - Trigger:
manual/interval/after_session/any - Budget cap: 토큰 상한 — 메타-LLM 비용 폭주 방지
외과적 편집 — diff first
핵심 디자인은 전체 재작성이 아니라 패치 다. 메타-LLM에게 “전체를 다시 써라”라고 시키면 사용자가 의도해서 넣은 디테일이 사라진다.
[입력]
- 원본 X.md
- objective
- refine targets
[출력]
- 변경할 라인 단위 패치 (added/removed)
- 변경 이유 한 문단
[적용]
1. cp X.md X.bak.md # always backup
2. apply patch # atomic write
3. record diff in history # ledger
사용자는 다음을 본다:
- 확장 가능한 diff viewer — 무엇이 들어가고 빠지는지
- dry-run 미리보기 — 적용 전 검증
- history timeline — 시간순으로 모든 패치
.bak.md — 한 번 클릭으로 되돌리기
각 적용은 항상 .bak.md를 만든다. 이전 상태를 잃지 않는다 는 단 하나의 보장.
def apply_patch_atomic(path, patch, dry_run=False):
if dry_run:
return preview(path, patch)
bak = path.with_suffix(".bak.md")
shutil.copy2(path, bak)
new_content = apply(patch, read(path))
tmp = path.with_suffix(".md.tmp")
tmp.write_text(new_content)
os.replace(tmp, path) # atomic on POSIX
return {"backup": str(bak), "diff": diff_of(patch)}
POSIX의 os.replace(또는 rename)는 부분 쓰기 상태가 디스크에 남지 않는 보장을 준다. 도중에 프로세스가 죽어도 옛 파일이 그대로다.
메타-LLM 프롬프트 골격
ROLE
You are an editor for a Claude Code sub-agent definition file.
You may ONLY change the sections listed in REFINE_TARGETS.
OBJECTIVE
{user_objective}
CURRENT FILE
---
{x_md_content}
---
USAGE HISTORY (last N sessions)
- session 1: <summary, was the agent useful?>
- session 2: ...
OUTPUT
Return a JSON patch:
{
"edits": [
{"section": "systemPrompt", "op": "replace",
"old": "...", "new": "..."},
...
],
"rationale": "<one paragraph why>"
}
DO NOT touch sections outside REFINE_TARGETS.
핵심: 건드릴 수 있는 영역을 명시적으로 좁힌다. LLM은 권한이 명시되어 있으면 그 안에서 잘 머문다.
트리거 4종
| 트리거 | 의미 |
|---|---|
manual |
버튼 클릭으로만 |
interval |
N분마다 (예: 60분) |
after_session |
sub-agent가 호출된 세션이 끝나면 |
any |
위 셋 OR |
after_session이 가장 자연스럽다 — 경험 이 쌓이는 시점에만 학습이 일어난다.
Composite key 네임스페이싱
global ~/.claude/agents/foo.md와 <cwd>/.claude/agents/foo.md는 이름이 같지만 다른 파일 이다. Hyper Agent는 두 곳의 메타·objective·history를 분리해서 들고 다닌다 — composite key:
key = sha1(scope + ":" + agent_name + ":" + abs_path)
이걸 안 하면 한쪽에서의 학습이 다른 쪽을 오염시킨다.
안전 장치 모음
- Budget cap: 토큰 상한 도달 시 일시 중지
- Refine targets 외 변경 거부: 응답이 권한 밖을 건드리면 패치 자체를 버린다
- Dry-run: 적용 전 사용자에게 diff 먼저
- History append-only: 패치 이력은 수정 되지 않는다
- Single-flight: 같은 agent에 동시에 두 개의 메타-LLM 호출이 가지 않게 lock
무엇이 아닌가
- ❌ “agent를 자율적으로 동작하게” — Hyper Agent는 agent 정의 파일 만 만진다. agent 자체의 실행 권한은 그대로.
- ❌ “스스로 학습한다” — 제안하고, 사용자가 검토 하고, atomic 적용. 무인 자동 변형 아님 (단, 명시적으로
manual외 트리거를 켰을 때만 자동). - ❌ “메모리” — Anthropic의
memory-2025-08-18과는 완전히 다른 레이어.
일반화 — 자기 편집형 시스템의 패턴
이 디자인은 LazyClaude 외에서도 쓸 수 있다:
- 대상 파일 을 마크다운 등 사람-읽기 가능한 형식으로 둔다
- 권한이 있는 영역 을 명시적으로 표기
- diff 단위 로 변경, atomic 으로 적용, backup 항상
- history 를 append-only로 남긴다
“되돌릴 수 있는 작업만 자동화”라는 자율모드의 원칙을, 한 단계 더 안쪽 — agent 정의 파일 — 에 적용한 사례.
한 줄 요약
자기 자신을 편집하는 시스템은 되돌리는 길 부터 만든다.
다음 편: LazyClaude 심층 6 — Auto-Resume: rate-limit과 context-full을 분류하고 재시도하기 이전 편: LazyClaude 심층 4 — PWA + macOS .app