주식 앱을 만들면서 에이전트 오케스트레이션 시스템을 직접 짰습니다. 역할을 Planner / Worker / Tester / Refactor / Manager / Screen Tester / Reviewer 일곱 개로 나누고, 역할별 피드 파일(feeds/<role>.feed.md)에 cursor와 dispatch-counter를 붙이고, feed-append.py·feed-read.py 같은 파이썬 스크립트로 pub/sub을 돌렸어요. Worker가 작업을 끝내면 PostToolUse 훅이 Tester를 자동으로 띄우는 체인까지 만들었습니다. 원하는 건 하나였습니다. 비즈니스 판단 빼고는 구현·테스트·리뷰가 사람 개입 없이 알아서 돌아가는 것.
그런데 잘 안 돌아갔습니다. pub/sub은 전파가 자꾸 끊기고, 그래서 중앙 index 방식으로 몰았더니 이번엔 충돌이 났어요. 태스크 현황을 46KB짜리 README 하나에 모아뒀는데 에이전트 여럿이 동시에 건드리니까, 결국 워크트리에서는 그 파일 편집 금지라는 규칙까지 둬야 했습니다. 당시 채팅을 다시 열어보면 이렇게 묻고 있습니다. “pub/sub으로 그게 잘 안둘러가는거 같애. 한곳에 index방식으로 처리하는건 또 충돌이 너무 많이나고 흠… 뭐 좋은 방법 없을까?”
그 상태에서 5월 28일에 Opus 4.8이 나왔습니다. 출시 소식을 훑다가 “병렬로 멀티쎄션 막 일시키는거 잇던데” 하고 물어봤고, 돌아온 답이 Dynamic Workflows였어요. Claude가 작업을 계획하고 서브에이전트를 동시 16개, 실행당 최대 1,000개까지 띄운 뒤 결과를 스스로 검증한다. 루프·분기·중간 결과는 스크립트가 들고 있고, Claude의 컨텍스트에는 최종 답만 남는다. 제가 피드 파일과 cursor로 만들려던 게 정확히 그거였습니다. 이미 있었고, 더 잘 만들어져 있었어요.
켜는 과정은 좀 허탈했습니다. /effort ultracode를 쳤더니 “Ultracode needs dynamic workflows enabled (see /config) and an xhigh-capable model”이라는 에러가 나왔고, /config에서 workflows를 on으로 토글하고 다시 치니까 끝. 제가 파이썬 스크립트와 훅으로 조립하던 게 설정 한 줄이었습니다. 그날 채팅에 남은 제 반응은 “되었다 ㅋㅋㅋ”가 전부예요.
첫 ultracode 실행으로 뭘 시켰는지가 좀 웃긴데, 제가 직접 만든 오케스트레이션 시스템을 어떻게 고칠지 설계하는 일이었습니다. 에이전트 10개가 병렬로 제 pub/sub 문서들을 정독하고 철학이 다른 설계안 4개를 경합시켰어요. 손으로 만든 오케스트레이션의 개선안을 내장 오케스트레이션한테 짜게 한 겁니다.
이런 일이 처음도 아니었습니다. 저는 한동안 스킬을 안 쓰고 에이전트 규칙을 전부 CLAUDE.md 컨벤션으로 관리했거든요. “여지껏 컨벤션으로 다 처리햇는데 누락이 좀 잇긴햇거든”이라고 물었더니 원리가 나왔습니다. CLAUDE.md는 매 메시지마다 다시 읽히는데, 대화가 길어질수록 규칙이 컨텍스트 전체에 희석돼서 “있긴 한데 무시됨” 상태가 된다는 거예요. 그래서 무거운 절차는 스킬로 빼고(트리거되는 순간 작업 바로 옆에 주입되니 준수율이 오릅니다), 한 번도 빠지면 안 되는 규칙은 훅으로 뺍니다(exit code 2, 모델 판단을 아예 안 거칩니다). 이 구분을 제가 발명할 필요가 없었습니다. 도구에 이미 설계돼 있었고, 저만 모르고 있었어요.
두 사건을 붙여놓고 나서야 패턴이 보였습니다. 프롬프트 엔지니어링, 컨텍스트 관리라고 부르던 것들이 도구 안으로 들어가고 있다는 것. 규칙을 언제 주입할지는 스킬이 가져갔고, 결정론적 강제는 훅이, 멀티에이전트 오케스트레이션은 워크플로가, 추론 예산 조절은 effort 슬라이더가 가져갔습니다. 반년 전에 직접 엔지니어링해야 했던 게 지금은 설정값입니다.
새 기능이 들어오면 기존에 쓰던 것들의 자리도 다시 짜입니다. 스킬이 생기니 CLAUDE.md의 역할은 “모든 규칙을 담는 곳”에서 “매 메시지마다 들고 다닐 가치가 있는 것만 남기는 곳”으로 줄었습니다. 별개였던 commands와 skills는 병합돼서 같은 슬래시 인터페이스가 됐고, 이제 실질적 구분은 파일 위치가 아니라 “사람이 부르느냐, 에이전트가 부르느냐”뿐이에요. 기능 하나가 추가되는 게 아니라 배치 전체가 재편되는 겁니다.
그러면 문법을 외우는 건 의미가 없습니다. 다음 버전에서 또 바뀔 테니까요. 남는 건 LLM이 어떻게 동작하는지에 대한 감각입니다. 컨텍스트가 길어지면 앞쪽 지시가 희석된다. 필요한 순간에 주입된 지시가 제일 잘 지켜진다. 모델 판단에 기대는 층과 결정론적으로 강제하는 층은 다르다. 중간 산출물이 컨텍스트에 쌓이면 품질이 떨어진다. 이 감각이 있으면 릴리스 노트를 읽을 때 “이 기능이 내 세팅의 어느 부분을 대체하는구나”가 바로 보입니다. 없으면 새 기능은 그냥 지나가는 뉴스고, 나는 계속 내 바퀴를 굴립니다.
다음 릴리스에서도 뭔가가 제 세팅 어딘가를 대체할 겁니다. 그게 뭔지는 모르지만, 이번엔 릴리스 노트에서 알아볼 수는 있을 것 같아요.