오늘도 공부
Codex에서 GPT-5.6 Luna를 서브에이전트로 사용하는 방법 본문
이 문서는 GPT-5.6 Sol을 메인 오케스트레이터로 사용하면서 GPT-5.6 Luna를 서브에이전트로 실행하는 로컬 설정을 기록한 운영 가이드다. Codex 업데이트나 설정 초기화 후 Luna 서브에이전트가 보이지 않을 때 이 문서를 따라 다시 설정하고 검증한다.
현재 확인된 정상 구성
2026년 8월 1일 기준으로 다음 구성이 실제 실행까지 확인됐다.
- 메인 모델:
gpt-5.6-sol - 서브에이전트 모델:
gpt-5.6-luna - Luna 다중 에이전트 프로토콜:
v2 - Luna 추론 수준:
low,medium,high,xhigh,max - 실제 검증 결과: Luna 자식 에이전트가 생성되고
LUNA_SUBAGENT_OK를 반환함 - 검증 당시 데스크톱 내장 Codex:
0.146.0-alpha.9.2 - 검증 당시 터미널 Codex:
0.146.0
시작하기 전에: Codex 경로 설정
이 문서의 명령은 macOS와 Linux의 Bash/Zsh 셸을 기준으로 한다. 먼저 현재 터미널에서 Codex 데이터 디렉터리를 CODEX_DIR 변수로 지정한다.
export CODEX_DIR="${CODEX_HOME:-$HOME/.codex}"
printf 'Codex directory: %s\n' "$CODEX_DIR"
CODEX_HOME을 따로 설정했다면 그 경로를 사용한다.- 별도 설정이 없다면 현재 사용자의 기본 경로인
$HOME/.codex를 사용한다. - 이후 터미널을 새로 열었다면 위 명령을 다시 실행한다.
- Windows에서는 Codex 데이터 디렉터리를 확인한 뒤 PowerShell 환경 변수와 경로 표기법에 맞게 명령을 바꿔야 한다.
이 문서에서 사용하는 파일은 다음과 같다.
$CODEX_DIR/config.toml
$CODEX_DIR/models_cache.json
$CODEX_DIR/models-luna-v2.json
models_cache.json은 Codex가 내려받은 원본 모델 카탈로그다. 이 파일을 직접 수정하지 않고 복사본인 models-luna-v2.json에서 Luna 항목만 v2로 바꾼다.
이 설정은 로컬 모델 카탈로그 오버라이드다. Codex 업데이트로 공식 카탈로그나 서브에이전트 동작 방식이 바뀌면 더 이상 필요하지 않거나 작동하지 않을 수 있다. 업데이트 후에는 반드시 실제 자식 에이전트 실행까지 확인한다.
1. 현재 설정 확인
터미널에서 다음 명령을 실행한다.
grep -nE 'model_catalog_json|multi_agent' "$CODEX_DIR/config.toml"
jq '.models[]
| select(.slug == "gpt-5.6-luna")
| {
slug,
multi_agent_version,
supported_reasoning_levels
}' "$CODEX_DIR/models-luna-v2.json"
정상이라면 다음 두 조건을 만족해야 한다.
model_catalog_json = "/absolute/path/to/codex-home/models-luna-v2.json"
multi_agent = true
Luna 모델 정보에는 다음 값이 있어야 한다.
{
"slug": "gpt-5.6-luna",
"multi_agent_version": "v2"
}
파일이 없거나 값이 다르면 다음 절차로 다시 만든다.
2. Luna V2 모델 카탈로그 다시 만들기
먼저 원본 모델 캐시와 현재 설정을 백업한다.
mkdir -p "$CODEX_DIR/backups/luna-v2-setup"
cp "$CODEX_DIR/models_cache.json" \
"$CODEX_DIR/backups/luna-v2-setup/models_cache.json"
cp "$CODEX_DIR/config.toml" \
"$CODEX_DIR/backups/luna-v2-setup/config.toml"
원본 카탈로그를 복사하고 Luna 항목만 v2로 변경한다.
cp "$CODEX_DIR/models_cache.json" \
"$CODEX_DIR/models-luna-v2.json"
python3 - <<'PY'
import json
import os
from pathlib import Path
codex_dir = Path(os.environ["CODEX_DIR"]).expanduser().resolve()
catalog_path = codex_dir / "models-luna-v2.json"
data = json.loads(catalog_path.read_text(encoding="utf-8"))
models = data.get("models", [])
matches = [
model
for model in models
if model.get("slug") == "gpt-5.6-luna"
]
if len(matches) != 1:
raise SystemExit(
f"gpt-5.6-luna 항목이 정확히 1개여야 합니다. 현재: {len(matches)}개"
)
matches[0]["multi_agent_version"] = "v2"
temporary_path = catalog_path.with_suffix(".json.tmp")
temporary_path.write_text(
json.dumps(data, ensure_ascii=False, indent=2) + "\n",
encoding="utf-8",
)
temporary_path.replace(catalog_path)
print("gpt-5.6-luna multi_agent_version=v2 설정 완료")
PY
명령이 Luna 항목을 찾지 못하면 작업을 중단한다. 다른 모델을 Luna로 추정해 바꾸면 안 된다. 먼저 Codex를 업데이트하거나 models_cache.json에 Luna가 제공되는지 확인한다.
3. config.toml 연결
$CODEX_DIR/config.toml의 최상위 영역에 다음 설정을 둔다. 첫 번째 [섹션]이 시작되기 전에 있어야 한다.
먼저 현재 사용자에게 맞는 설정 한 줄을 출력한다.
printf 'model_catalog_json = "%s/models-luna-v2.json"\n' "$CODEX_DIR"
출력된 절대경로를 복사해 config.toml에 넣는다. 예시는 다음과 같다.
model = "gpt-5.6-sol"
model_catalog_json = "/absolute/path/to/codex-home/models-luna-v2.json"
기존 [features] 섹션에는 다음 값을 추가하거나 확인한다.
[features]
multi_agent = true
주의 사항:
model_catalog_json을[features]나[projects]아래에 넣으면 안 된다.- TOML 문자열 안에서는
$HOME이나$CODEX_DIR같은 셸 변수가 자동으로 확장되지 않는다. 반드시 앞의printf명령으로 확인한 절대경로를 넣는다. - 같은 키를 두 번 선언하면 TOML 로딩 오류가 날 수 있다.
- 기존
[features]섹션이 있으면 새 섹션을 하나 더 만들지 말고 그 안에 추가한다. - 메인 모델을 Sol로 유지하려면
model = "gpt-5.6-sol"을 그대로 둔다.
설정을 저장한 뒤 파싱 상태를 확인한다.
codex doctor --summary
config.load가 실패한다면 앱을 재시작하기 전에 config.toml의 중복 키와 섹션 위치부터 고친다.
4. Codex 완전 재시작
실행 중인 Codex는 시작 시 읽은 모델 카탈로그와 도구 스키마를 계속 사용할 수 있다. 설정 파일만 바꿔서는 이미 열린 작업에 Luna가 나타나지 않을 수 있다.
- 진행 중인 작업을 마친다.
- ChatGPT/Codex 데스크톱 앱을
⌘Q로 완전히 종료한다. - 터미널에서 별도
codex프로세스가 실행 중이면 함께 종료한다. - 데스크톱 앱을 다시 실행한다.
- 기존 작업이 아니라 새 작업에서 Luna 서브에이전트를 검증한다.
강제 종료나 macOS 재부팅은 필수 조건이 아니다. 앱을 정상적으로 완전히 종료했다가 다시 여는 것으로 충분하다.
5. Luna 서브에이전트 실제 실행
Luna를 확실히 사용하려면 서브에이전트 생성 시 모델을 명시해야 한다.
model: gpt-5.6-luna
reasoning_effort: max
fork_turns: none
fork_turns는 none 또는 최근 턴 수처럼 제한된 값을 사용한다. 전체 대화 기록을 상속하는 생성 방식은 부모 모델과 추론 수준을 그대로 물려받으므로 Luna 모델 오버라이드를 적용할 수 없다.
사용자가 Codex에 요청할 때는 다음과 같이 작성할 수 있다.
메인 Sol이 작업을 조율하고, 실제 하위 작업은
gpt-5.6-luna / reasoning max 서브에이전트로 실행해 줘.
Luna 생성 시 모델을 명시하고 fork_turns는 none 또는 제한된 턴 수를 사용해 줘.
Luna는 max까지 지원한다. ultra를 지정하면 모델 검증 단계에서 거부될 수 있다.
6. 빠른 스모크 테스트
새 작업에서 다음과 같이 요청한다.
gpt-5.6-luna, reasoning max로 읽기 전용 서브에이전트 한 개를 생성해 줘.
그 에이전트는 다른 도구를 사용하지 말고 LUNA_SUBAGENT_OK만 반환하게 해 줘.
실행 후 자식 세션의 실제 model과 reasoning_effort도 확인해 줘.
성공 판정은 다음 세 조건을 모두 만족해야 한다.
- 자식 생성 요청이 모델 검증 단계에서 거부되지 않는다.
- 자식이
LUNA_SUBAGENT_OK를 반환한다. - 자식 rollout의
turn_context에model="gpt-5.6-luna"와reasoning_effort="max"가 기록된다.
최근 자식 세션에서 모델 기록을 찾으려면 다음 명령을 사용할 수 있다.
grep -R -l '"model":"gpt-5.6-luna"' \
"$CODEX_DIR/sessions" |
tail -n 5
찾은 rollout 파일에서 turn_context를 확인한다.
jq -c '
select(.type == "turn_context")
| {
model: .payload.model,
reasoning_effort:
.payload.collaboration_mode.settings.reasoning_effort
}
' /절대/경로/rollout-파일.jsonl
정상 결과 예시는 다음과 같다.
{
"model": "gpt-5.6-luna",
"reasoning_effort": "max"
}
에이전트가 자기 모델을 말로 주장하는 것만으로는 충분하지 않다. 반드시 자식 세션의 turn_context를 확인한다.
7. 문제가 생겼을 때
gpt-5.6-luna가 허용 모델 목록에 없음
다음 항목을 순서대로 확인한다.
model_catalog_json경로가 정확한가models-luna-v2.json에 Luna 항목이 있는가- Luna의
multi_agent_version이v2인가 [features]의multi_agent가true인가- 설정 변경 후 앱을 완전히 재시작했는가
- 재시작 후 만든 새 작업에서 테스트했는가
Luna를 지정했는데 Sol 자식이 실행됨
다음 원인이 가장 흔하다.
- 생성 요청에서
model을 생략함 - 부모의 전체 대화 기록을 그대로 상속함
- 자동 오케스트레이션에 맡기고 Luna 사용을 명시하지 않음
Luna를 강제하려면 model=gpt-5.6-luna와 제한된 fork_turns를 함께 지정한다.
reasoning_effort가 거부됨
Luna에는 low, medium, high, xhigh, max 중 하나를 사용한다. ultra는 사용하지 않는다.
업데이트 후 다시 작동하지 않음
업데이트된 $CODEX_DIR/models_cache.json에서 Luna의 공식 multi_agent_version을 먼저 확인한다.
jq '.models[]
| select(.slug == "gpt-5.6-luna")
| {
slug,
multi_agent_version,
supported_reasoning_levels
}' "$CODEX_DIR/models_cache.json"
- 공식 값이 이미
v2라면 별도 오버라이드가 필요하지 않을 수 있다. - 공식 값이
v1이면 이 문서의 절차로 별도 카탈로그를 다시 만든다. - Luna 항목 자체가 없으면 임의로 모델 항목을 만들지 않는다.
- 모델은 보이지만 생성 도구가 거부한다면 현재 Codex 버전의 서브에이전트 도구 스키마가 Luna를 허용하는지 확인한다.
8. 원상 복구
로컬 오버라이드를 제거하려면 앱을 완전히 종료한 뒤 config.toml에서 다음 줄을 삭제한다.
model_catalog_json = "/absolute/path/to/codex-home/models-luna-v2.json"
models-luna-v2.json은 즉시 삭제하지 말고 보관해도 된다. 그다음 앱을 다시 실행하면 Codex가 기본 모델 카탈로그를 사용한다.
백업한 설정으로 되돌려야 할 때는 앱을 종료한 상태에서 백업 내용을 확인한 뒤 복원한다.
cp "$CODEX_DIR/backups/luna-v2-setup/config.toml" \
"$CODEX_DIR/config.toml"
복원 후에는 codex doctor --summary로 설정 파싱 여부를 확인하고 앱을 다시 실행한다.
'개발상식' 카테고리의 다른 글
| AI가 코드를 쓰는 시대, 개발자는 무엇을 설계해야 할까 (0) | 2026.07.18 |
|---|---|
| 이제는 “뭘 만들까?”보다 “누구의 어떤 문제를 풀까?”가 더 중요하다 (1) | 2026.03.24 |
| AI 에이전트 협업 팀을 위한 Git 운영 튜토리얼 (0) | 2026.02.12 |
| SQLite FTS5 전문 검색 가이드 (0) | 2026.02.06 |
| IntelliJ IDEA에서 서버 시작전 포트 죽이는 실행방법 (0) | 2026.01.20 |
