Claude Code에서 발견한 스킬 문제를 Codex에도 반영했다. 도구를 옮긴 것이 아니라, 동시에 쓰는 두 도구의 판단 기준을 맞춘 작업이었다.
지난 글에서 스킬 53개를 만들어두고 실제로는 3개만 쓰고 있었다는 이야기를 썼다. Claude Code의 일주일치 기록을 확인해 보니 자연어 호출을 막는 설정과 실제 말투에서 벗어난 트리거가 원인이었다.
그 문제를 고친 뒤 이런 생각이 들었다.
나는 Claude Code만 쓰는 게 아닌데, Codex에서는 스킬을 제대로 쓰고 있을까?
여기서 처음에는 “Claude에서 정리한 걸 Codex로 옮긴다”고 생각했다. 기록을 다시 보니 표현부터 틀렸다. 두 도구는 교체 관계가 아니었다. 같은 시간대에 서로 다른 일을 맡아 동시에 움직이고 있었다.
같은 시간에 둘 다 일하고 있었다
짧게 최근 30분의 사용 기록을 열어봤다.
Claude Code 쪽에서는 37개의 도구 완료 기록이 보였다.
| 도구 종류 | 횟수 |
|---|---|
| Shell | 18 |
| MCP | 14 |
| 파일 읽기·수정 | 4 |
| 작업 목록 | 1 |
같은 시간 Codex에서는 협업 도구 조회, 브라우저 조작, 문서 작성, 명령 실행과 주기적인 검토 작업이 계속 돌고 있었다. 자동 작업에서 같은 종류의 조회가 반복되면서 로그가 1,000줄 상한에 닿아, 전체 호출 수를 Claude와 직접 비교하는 건 의미가 없었다.
그래도 어디에 손을 대고 있었는지는 분명히 달랐다.
- Claude Code는 저장소 안에서 셸을 실행하고 파일을 읽고 고치는 일이 많았다.
- Codex는 브라우저와 여러 연결 도구를 넘나들며 확인하고, 문서를 만들고, 반복 점검을 유지하는 일이 많았다.
이건 제품 설명을 보고 나눈 역할이 아니다. 내가 실제로 그렇게 쓰면서 생긴 분화다. 한쪽에서는 브랜치와 코드를 정리하고, 같은 시각 다른 쪽에서는 사용 기록을 분석하고 문서를 쓰고 있었다. 분 단위가 아니라 같은 초에 두 로그가 번갈아 찍히기도 했다.
물론 경계가 고정된 것은 아니다. Claude Code도 문서를 쓰고 외부 도구를 사용한다. Codex도 코드를 읽고 수정한다. 다만 반복해서 맡기다 보니 각 도구가 자주 서는 자리가 달라졌다.
이 차이를 지우고 하나로 통일할 이유는 없었다.
같은 정책도 같은 방식으로 측정할 수는 없다
두 도구 모두 반복 절차를 스킬로 둘 수 있다. Claude Code의 Skills 문서와 Codex의 Build skills 문서도 이 구조를 공식적으로 제공한다.
그래서 처음에는 스킬 파일과 설정을 그대로 맞추면 될 줄 알았다. 실제로는 그렇지 않았다.
Claude Code에서는 스킬이 호출되면 명시적인 도구 호출과 발동 이벤트가 남는다. 이전 글에서 계산한 “발동 10건”도 그 기록을 센 것이다. 자연어 호출을 막는 설정 역시 Claude Code에서는 실제 실행 경로를 바꿨다.
Codex에서는 Claude와 동일한 발동 이벤트 계약을 전제로 할 수 없었다. 같은 설정 이름이 파일에 있어도 Codex의 자동 선택을 막았다고 단정할 수 없었다. Claude에서 만든 집계기를 이름만 바꿔 돌리면 숫자는 나와도 의미가 달라진다.
그래서 Codex에서는 질문을 바꿨다.
스킬이 발동했는가?
대신 이렇게 물었다.
사용자 요청 뒤에 관련
SKILL.md를 실제로 읽었는가? 일반 도구를 쓰기 전에 읽었는가?
그리고 판정을 세 단계로 나눴다.
| 판정 | 기준 |
|---|---|
| 먼저 적용 | 일반 탐색이나 실행보다 SKILL.md를 먼저 읽음 |
| 늦게 적용 | 여러 도구를 사용한 뒤 SKILL.md를 읽음 |
| 적용 증거 없음 | 같은 요청에서 스킬 문서를 읽은 기록이 없음 |
이건 “발동률”이 아니다. 적용 증거다. 문서를 읽지 않고도 올바른 절차를 수행했을 수 있고, 읽고도 지키지 않았을 수 있다. 그래서 측정값보다 강한 이름을 붙이지 않았다.
같은 정책을 적용한다는 건 같은 필드와 같은 숫자를 복사하는 일이 아니었다. 각 도구에서 확인 가능한 증거로 같은 질문에 답하는 일이었다.
로그를 세는 것부터 달랐다
Codex 세션 기록을 처음 단순 집계했을 때 하루 요청이 300건 넘게 나왔다. 실제로 그렇게 많이 말하지는 않았다.
원인을 열어보니 이전 대화가 다시 주입된 맥락, 환경 정보, 자동 작업 메시지가 모두 사용자 역할로 섞여 있었다. 역할이 user라는 이유만으로 세면 사람이 직접 입력한 요청이 부풀려진다.
도구 호출 형식도 하나가 아니었다. 예전 기록과 현재 Desktop 기록의 이벤트 구조가 달랐고, 스킬 경로가 출력에 나타났다고 모두 스킬을 읽은 것도 아니었다. 검증 명령이 파일 경로를 나열한 경우까지 세면 거짓 양성이 생겼다.
점검기는 다음처럼 바뀌었다.
- 실제 신규 사용자 입력을 나타내는 이벤트와 대화 턴을 연결한다.
- 과거와 현재의 도구 호출 형식을 모두 처리한다.
sed,cat,head처럼SKILL.md를 실제로 읽은 동작만 증거로 센다.- 수백 MB까지 커진 세션은 끝에서부터 읽고 기간 경계를 만나면 멈춘다.
- 집계 뒤에는 원문 표본을 직접 확인한다.
7일치를 다시 돌리니 실제 사용자 요청 196건, 스킬 문서를 읽은 증거가 있는 요청 54건, 그중 다른 도구보다 먼저 읽은 요청 38건이 나왔다.
여기서도 “Codex의 스킬 사용률은 27.6%”라고 쓰지 않았다. 그 숫자가 말해주는 건 더 좁다.
196개 요청 중 54개에서 스킬 문서를 읽은 기록이 있었고, 그중 38개는 일반 도구를 호출하기 전에 읽었다.
관측할 수 있는 만큼만 말하는 것도 정책의 일부다.
공통으로 맞춘 것은 실행법이 아니라 판단 순서였다
Claude Code에서는 자연어 호출을 막던 설정을 점검하고, 내가 실제로 쓰는 표현을 스킬 설명에 반영했다.
Codex에서는 개인 지침에 스킬 우선 라우팅을 추가했다.
- 요청과 맞는 스킬이 있으면 첫 도메인 도구를 사용하기 전에 읽는다.
- 사용자가 스킬 이름을 몰라도 자연어 의도로 연결한다.
- 읽기 전용 조사처럼 안전한 첫 단계는 스킬을 선택한 뒤 바로 시작한다.
- 스킬 선택과 외부 쓰기 권한은 분리한다.
- 비슷한 스킬이 여러 개면 주 스킬 하나를 먼저 정한다.
표현은 다르지만 두 정책이 지키려는 것은 같다.
- 이미 있는 절차를 두고 처음부터 다시 헤매지 않는다.
- 사용자가 명령 이름을 외우게 하지 않는다.
- 외부 변경은 명시된 권한 안에서만 한다.
- 결과를 보고 트리거와 절차를 다시 고친다.
이전에 AI 도구를 바꾸는 비용을 낮추는 법에서 규칙을 제품 밖에 두면 도구를 바꿔도 다시 만들 것이 줄어든다고 썼다. 이어서 Cursor에서 Claude로 옮긴 구체 사례도 정리했다.
이번에는 한 단계가 더 있었다. 나는 도구를 바꾸지 않았다. 둘을 동시에 쓰고 있었다. 그러니 필요한 건 마이그레이션이 아니라 공통 정책과 런타임별 적용 방식을 분리하는 일이었다.
하나의 지표로 비교하지 않기로 했다
처음에는 같은 대시보드에서 두 도구의 호출 수를 나란히 놓고 싶었다. 실제 로그를 보니 그 비교는 쉽게 틀어진다.
- 한 도구는 작업 하나가 여러 텔레메트리 이벤트로 쪼개졌다.
- 다른 도구는 명시적인 스킬 호출이 한 건으로 남았다.
- 주기적으로 도는 자동화는 사람이 시작한 대화보다 훨씬 많은 조회 이벤트를 만들었다.
- 긴 세션과 짧은 세션은 같은 요청 수라도 도구 호출 수가 달랐다.
호출 수가 많다고 더 많이 일한 것도 아니고, 적다고 효율적인 것도 아니다. 서로 다른 런타임의 원시 이벤트를 한 줄로 세워 경쟁시키면 측정 방식의 차이를 생산성 차이로 오해하게 된다.
대신 두 층으로 보기로 했다.
공통으로 볼 것
- 요청에 맞는 절차를 초기에 선택했는가
- 위험한 외부 변경 전에 권한 경계를 지켰는가
- 작업 결과가 검증 가능한 형태로 남았는가
- 같은 실패를 규칙에 반영했는가
도구별로 볼 것
- 어떤 이벤트가 실제 실행 증거인가
- 자동화와 직접 대화를 어떻게 구분할 것인가
- 세션 구조와 로그 상한을 어떻게 처리할 것인가
- 해당 도구가 자주 맡는 일에서 병목이 무엇인가
공통 정책은 결과를 맞추고, 도구별 관측은 그 결과에 도달하는 경로를 설명한다.
둘을 쓰는 이유도 더 명확해졌다
도구가 둘이면 규칙도 두 벌이라 관리 비용만 늘어난다고 생각할 수 있다. 실제로 아무 기준 없이 복사하면 그렇다.
하지만 공통으로 유지할 것을 좁히면 얘기가 달라진다.
- 공유할 것: 작업 원칙, 안전 경계, 완료 조건, 자연어 의도
- 각자 둘 것: 설정 필드, 로그 파서, 도구 이름, 인증 방식, 실행 명령
모든 문장을 동기화하려 하지 않는다. 한쪽의 설정을 다른 쪽에서 의미도 모른 채 유지하지도 않는다. 정책이 바뀌면 두 런타임에서 그 정책이 어떤 동작으로 번역되는지만 확인한다.
이 구조 덕분에 역할 분화도 유지할 수 있다. 저장소에 오래 머물며 구현하는 작업과 여러 시스템을 오가며 확인하고 정리하는 작업을 동시에 진행하되, 둘 다 같은 안전 기준과 완료 기준을 따른다.
역할은 나눠도 기준은 갈라지지 않는다.
마무리
지난 글의 결론은 “스킬을 더 만들기 전에 실제로 쓰이는지 재보자”였다.
이번에 하나를 더 배웠다.
여러 에이전트를 함께 쓴다면, 같은 지표를 강제로 맞추지 말고 같은 판단을 각 도구의 증거로 확인해야 한다.
Claude Code와 Codex 중 하나를 고를 필요는 없었다. 둘은 이미 같은 시간에 다른 일을 하고 있었다. 하나의 사용법으로 통일할 필요도 없었다. 실행 환경과 관측 방식이 달랐기 때문이다.
대신 스킬을 먼저 찾고, 권한 경계를 지키고, 결과를 검증하고, 실패를 다시 규칙에 넣는 순서는 함께 가져갈 수 있었다.
결국 통일해야 했던 건 도구가 아니었다.
통일해야 했던 건 판단 기준이었다.