Codex가 모델에 보내는 한 번의 요청은 고정 base 프롬프트(취업규칙) 위에 “지금 이 순간의 사실” 조각(포스트잇)을 정해진 순서로 쌓은 한 덩어리다.
모델이 왜 특정 행동을 하는지(권한·위치·프로젝트 규칙)는 모두 이 조립 단계에서 결정된다. 여기를 알면 Codex의 판단 근거를 통제할 수 있다.
그림
flowchart TD
A[턴 시작] --> B[build_initial_context 호출]
B --> C1["base 프롬프트 선택<br/>설정 오버라이드 > 히스토리 > 모델 기본"]
B --> D1["권한·스킬·플러그인·성격 조각<br/>→ developer 묶음"]
B --> D2["AGENTS.md 찾아 연결 + 환경 정보<br/>→ user 묶음"]
D1 --> E[developer 메시지 1개]
D2 --> F[user 메시지 1개]
C1 --> G[Prompt.base_instructions 칸]
E --> H[Prompt.input 칸]
F --> H
G --> I[Responses API 요청 발송]
H --> I
I --> J[모델 응답]
J --> K{"대화창이 한계를 넘었나?"}
K -- 예 --> L[compact 가 요약으로 압축]
K -- 아니오 --> A
쉽게 풀기
1단계 — base = “전 직원 취업규칙”. 요청의 맨 밑판은 base instructions(시스템 프롬프트)다. “너는 Codex다, 이렇게 행동하라”는 고정 헌법이며 모델마다 prompt.md 한 장으로 정해진다. 매번 새로 쓰지 않고 늘 같은 판이 깔린다.
2단계 — 그 위에 “오늘 책상 포스트잇”을 붙인다. 취업규칙만으로는 지금 상황을 모른다. 그래서 상황 조각(fragment)을 얹는다 — 어느 폴더(cwd)·셸·날짜·권한·쓸 수 있는 스킬/플러그인, 그리고 프로젝트 AGENTS.md 규칙. 각각이 포스트잇 한 장이다.
3단계 — 포스트잇마다 “이름표”와 “붙일 자리”. 각 조각은 고유 마커(예: <environment_context>…</environment_context>)와 역할(role) 을 갖는다. 정책·도구 안내는 developer, “지금의 사실”은 user다. 이름표가 있어야 대화가 길어졌을 때 Codex가 옛 조각을 찾아 갈아끼울 수 있다.
4단계 — 같은 역할끼리 한 봉투로. developer 조각은 모여 developer 메시지 1개, user 조각은 user 메시지 1개가 된다. base는 별도 칸(base_instructions)에 담긴다. 이 셋이 합쳐져 한 요청이 된다.
아래 그림이 이 4단계의 흐름이다.
flowchart LR
P1["② 상황 조각들<br/>(포스트잇)"] --> R{③ role 분류}
R -->|developer| DV["권한·스킬·플러그인·성격"]
R -->|user| US["AGENTS.md·환경"]
DV --> M1["④ developer 메시지 1개"]
US --> M2["④ user 메시지 1개"]
B1["① base 취업규칙"] --> BK["base_instructions 칸"]
M1 --> REQ[한 번의 모델 요청]
M2 --> REQ
BK --> REQ
핵심 비유
base = 회사 취업규칙(전 직원 동일). fragment = 그날 책상 포스트잇(오늘 위치·열쇠 권한·쓸 도구). 마커 = 포스트잇 제목(떼고 새로 붙일 때 찾는 용도).
핵심 정리
조립에 쓰이는 세 가지 그릇과, 조각이 지켜야 할 공통 계약은 다음과 같다.
그릇
담는 것
요청의 어디로
base_instructions
시스템 프롬프트 전문(고정 헌법)
instructions 필드
developer 묶음
권한·스킬·플러그인·성격 등 정책/능력
input의 developer 메시지
user 묶음
AGENTS.md·환경 등 “지금의 사실”
input의 user 메시지
조각의 공통 계약(ContextualUserFragment 트레잇): role()=들어갈 역할(developer/user), markers()/type_markers()=시작·끝 이름표(식별·교체용), body()=이름표 사이 본문, render()=이름표+본문을 구분자 없이 이어붙임.
펼쳐보기: base 프롬프트 선택 우선순위 + 주요 fragment 목록
base 선택 우선순위 (core/src/session/mod.rs:570~584)
① config.base_instructions 오버라이드가 있으면 그것
② 세션 재개 시 히스토리의 session_meta.base_instructions
③ 둘 다 없으면 현재 모델의 기본 base
모델별 base는 models.json의 각 모델 base_instructions 필드에 인라인 텍스트로 박혀 있다. core/gpt-5.2-codex_prompt.md 등 prompt.md는 사람용 소스 사본일 뿐, 어떤 .rs/.toml도 include_str!로 직접 가져가지 않는다(grep 확인).
주요 fragment 한눈에 보기
UserInstructions(=AGENTS.md) — role user, 마커 # AGENTS.md instructions … </INSTRUCTIONS>
EnvironmentContext — role user, <environment_context>…</environment_context> (cwd·shell·date·timezone·network·filesystem·subagents)
AvailableSkillsInstructions — role developer, <skills_instructions>…
PermissionsInstructions — role developer, <permissions instructions>… (샌드박스·승인정책·writable roots·denied reads)
AvailablePluginsInstructions / AppsInstructions — role developer, 플러그인·MCP 커넥터 목록
PersonalitySpec / CollaborationMode / TokenBudgetContext — role developer, 성격·협업모드·컨텍스트 메타
AGENTS.md는 cwd에서 프로젝트 루트까지 거슬러 올라가며 경로상의 파일을 순서대로 모아 연결한다. 그 발견 규칙을 그림으로 보면 다음과 같다.
flowchart TD
S[cwd에서 시작] --> U{"루트 마커<br/>.git 도달?"}
U -- 아니오 --> UP[상위 폴더로 이동] --> U
U -- 예 --> ROOT[프로젝트 루트 확정]
ROOT --> COL["루트→cwd 경로의<br/>모든 AGENTS.md 순서대로 수집"]
COL --> JOIN["첫 doc 앞에 --- project-doc --- 삽입"]
JOIN --> BUD{"project_doc_max_bytes<br/>예산 초과?"}
BUD -- 예 --> TR[초과분 truncate]
BUD -- 아니오 --> OK[연결 완료]
TR --> OK
펼쳐보기: AGENTS.md 발견 규칙 전문 ( core/src/agents_md.rs)
project_root_markers(기본 .git)를 만날 때까지 cwd에서 위로 올라가 루트를 정한다
루트→cwd 경로상의 모든 AGENTS.md(+AGENTS.override.md+fallback 파일명)를 순서대로 모아 연결한다. 루트 위로는 안 올라간다
첫 project doc 앞에 \n\n--- project-doc ---\n\n 구분자를 넣는다
// input: 대화 입력 아이템(base 위에 쌓인 fragment + 히스토리) — 조립된 컨텍스트가 여기로// tools: 사용 가능한 툴(내장 + MCP 서버 툴)// parallel_tool_calls: 병렬 툴콜 허용 여부// base_instructions: 시스템 프롬프트 본문 → Responses API의 instructions 필드로 전달// personality(opt) / output_schema(opt) / output_schema_strict(기본 true)