목차
- Rust 전환 이후 달라진 OpenAI Codex 에이전트 루프 구조
- while 루프 기반 반복 실행 — 에이전트 루프의 뼈대
- 컨텍스트 관리 — 서버 측 저장과 클라이언트 측 전송
- 에러 처리와 재시도 메커니즘
- 도구 실행과 샌드박스 격리
- OpenAI Codex 에이전트 루프 구조 커스터마이징 포인트
- 실전 적용 시 고려해야 할 트레이드오프
- 정리와 다음 단계
AI 코딩 에이전트는 단순히 프롬프트를 보내고 응답을 받는 1회성 호출 구조가 아니다. 모델이 스스로 판단하고 도구를 호출하며 결과를 검증하는 반복 사이클 — 에이전트 루프 — 이 내부 실행 메커니즘의 핵심이다. Codex CLI의 agent-loop.ts 소스 코드를 기준으로 while 루프 기반 반복 실행 메커니즘, 컨텍스트 관리 전략, 에러 처리 로직을 분석하고, TypeScript에서 Rust로 전환된 배경을 다룬다.
Rust 전환 이후 달라진 OpenAI Codex 에이전트 루프 구조
가장 먼저 짚어야 할 사실이 있다. Codex CLI는 기존 TypeScript(ink 기반) 구현에서 Rust로 재작성되었다. 코드베이스의 96.2%가 Rust로 구성되어 있으며, 이 전환의 핵심 동기는 에이전트 루프 — 모델을 반복 호출하는 harness — 의 효율성 최적화에 있는 것이다. GC(Garbage Collection) 오버헤드를 제거함으로써 메모리 소비 감소와 실행 속도 향상을 달성했다.
분석 대상 코드 스니펫은 Codex CLI agent-loop.ts 소스 코드의 TypeScript 버전을 기준으로 한다. Rust 버전에서도 동일한 while 루프 → API 호출 → 도구 실행 → 결과 반환 패턴은 유지되지만, 런타임 특성이 다르다는 점을 인지해야 한다.
기존 TypeScript 기반 fork나 확장을 운영 중이라면 Rust 전환으로 인해 빌드 체인과 의존성 구조가 완전히 달라진 상태다. ink 기반 UI 레이어도 교체되었으므로 기존 플러그인 호환성을 반드시 확인해야 한다.
| 항목 | TypeScript(ink) 시절 | Rust 전환 이후 |
|---|---|---|
| 런타임 | Node.js + GC | 네이티브 바이너리, GC 없음 |
| 메모리 | GC 오버헤드 존재 | 직접 메모리 관리 |
| 샌드박스 | 제한적 | macOS Seatbelt / Linux Landlock+seccomp |
| 설치 | npm | npm, Homebrew |
| 확장 프로토콜 | — | 줄바꿈 구분 JSON 와이어 프로토콜, MCP 서버 |
while 루프 기반 반복 실행 — 에이전트 루프의 뼈대

OpenAI Codex 에이전트 루프 구조의 핵심은 while (turnInput.length > 0) 반복문이다. 이 루프는 처리할 입력이 남아 있는 한 계속 순회하며, 각 턴(turn)에서 다음 세 단계를 거친다.
- OpenAI Responses API(
oai.responses.create)를stream: true옵션으로 호출 - 응답에 포함된 tool call(shell 함수)을
handleFunctionCall()로 실행 - 실행 결과를
function_call_output으로 반환하여 다음 턴 입력(turnInput)에 삽입
더 이상 처리할 입력이 없으면 루프가 종료되는 방식이다.
while (turnInput.length > 0) {
// Send request to OpenAI Responses API
const responseCall = this.oai.responses.create({
model, instructions, input,
stream: true,
parallel_tool_calls: false,
tools // shell function
});
// Handle response and tool calls
turnInput = []; // Reset for next iteration
}
주목할 부분은 parallel_tool_calls: false 설정이다. 도구 호출을 병렬로 실행하지 않고 순차적으로 처리한다는 의미로, 이는 shell 명령 간 의존성(예: 파일 생성 후 해당 파일 수정)을 안전하게 보장하기 위한 설계 선택인 것이다. 병렬 실행이 필요한 경우 이 플래그가 커스터마이징의 첫 번째 포인트가 된다.
plan-execute-verify 사이클로 매핑하기
이 while 루프를 plan-execute-verify 관점에서 보면 구조가 명확해진다.
- Plan: 모델이 Responses API 응답으로 다음에 실행할 tool call을 결정하는 단계.
instructions와 이전 턴의function_call_output이 판단 근거가 된다. - Execute:
handleFunctionCall()이 shell 명령을 실제로 실행하는 단계. 샌드박스 내에서 격리 실행되는 편이다. - Verify: 실행 결과가
turnInput에 다시 들어가면서 모델이 성공 여부를 판단하는 단계. 추가 작업이 필요하면 다음 턴이 시작되고, 완료되었으면turnInput이 비어 루프가 종료된다.
Codex CLI는 Chat Completions API가 아닌 Responses API를 사용한다. Responses API는 tool call 결과를 `function_call_output` 타입으로 직접 반환할 수 있어 에이전트 루프 구현이 간결해지는 구조다. `previous_response_id`를 통한 서버 측 대화 관리도 Responses API 고유 기능이다.
에이전트 루프가 여러 턴을 거치면 대화 이력이 누적되기 마련이다. Codex CLI의 컨텍스트 관리는 두 가지 모드로 분기한다.
서버 측 저장 모드 (disableResponseStorage: false)
previous_response_id와 새로운 입력 델타만 전송하는 방식이다. 이전 대화 내용은 OpenAI 서버에 저장되어 있으므로 매 요청의 페이로드가 작다. 네트워크 비용이 적고 토큰 계산도 서버에서 처리하므로 클라이언트 부담이 줄어드는 것이다.
클라이언트 측 전송 모드 (disableResponseStorage: true)
시스템 메시지를 제외한 전체 대화 이력(transcript: Array<ResponseInputItem>)을 매 요청에 포함한다. 서버에 상태를 남기지 않으므로 프라이버시 관점에서 유리하지만, 턴이 누적될수록 요청 크기가 선형으로 증가하는 트레이드오프가 있다.
| 모드 | 요청 크기 | 서버 상태 | 프라이버시 | 적합한 환경 |
|---|---|---|---|---|
| 서버 측 저장 | 델타만 전송 → 작음 | 유지 | 서버에 이력 저장됨 | 일반 개발 환경 |
| 클라이언트 측 전송 | 전체 이력 → 턴 수에 비례 | 없음 | 로컬에만 이력 존재 | 민감 데이터 처리, 에어갭 환경 |
엔터프라이즈 환경에서 보안 정책상 외부 서버에 코드를 저장할 수 없다면 클라이언트 측 모드가 사실상 유일한 선택이 된다. 반면 긴 세션을 자주 운영하는 환경이라면 서버 측 모드가 토큰 효율 면에서 유리한 편이다.
`disableResponseStorage` 설정 하나로 모드가 전환된다. 팀 내 보안 정책을 먼저 확인하고, 평균 세션 길이(턴 수)를 측정한 뒤 결정하는 것이 합리적이다. 턴이 20회를 넘는 세션이 빈번하다면 서버 측 모드의 토큰 절감 효과가 눈에 띄게 나타나기도 한다.
에러 처리와 재시도 메커니즘
에이전트 루프는 여러 턴에 걸쳐 API를 반복 호출하므로 네트워크 오류, 서버 오류, Rate Limit 등 다양한 실패 상황을 처리해야 한다. Codex CLI의 에러 처리 전략은 세 계층으로 구성되어 있다.
재시도 가능한 일시적 에러
timeout, 5xx 서버 에러, 연결 오류는 지수 백오프(exponential backoff)로 재시도한다. 최대 재시도 횟수는 MAX_RETRIES = 5로 고정되어 있다.
const RATE_LIMIT_RETRY_WAIT_MS = parseInt(
process.env["OPENAI_RATE_LIMIT_RETRY_WAIT_MS"] || "2500", 10
);
const MAX_RETRIES = 5;
429 Rate Limit 처리
Rate Limit 응답을 받으면 RATE_LIMIT_RETRY_WAIT_MS(기본 2500ms) × 2^(attempt-1)로 대기한다. 서버가 Retry-After 헤더로 대기 시간을 제안하면 그 값을 따르는 구조다. 환경 변수 OPENAI_RATE_LIMIT_RETRY_WAIT_MS로 기본 대기 시간을 조정할 수 있어서, API 플랜에 따라 튜닝이 가능하다.
토큰 초과 — 복구 불가 에러
요청이 모델의 컨텍스트 윈도우를 초과하면 재시도가 무의미하다. 이 경우 사용자에게 에러를 표시하고 요청을 즉시 중단한다. 에이전트 루프 전체가 종료되는 것이다.
`OPENAI_RATE_LIMIT_RETRY_WAIT_MS` 환경 변수를 너무 낮게 설정하면 연속 429 응답으로 오히려 대기 시간이 길어질 수 있다. 기본값 2500ms는 대부분의 API 플랜에서 안전한 시작점이며, 지수 백오프가 적용되므로 5회 재시도 시 최대 약 40초까지 대기하게 된다.
도구 실행과 샌드박스 격리
에이전트 루프에서 모델이 결정한 작업은 handleFunctionCall()을 통해 실제 shell 명령으로 실행된다. Codex CLI가 지원하는 도구는 shell 함수이며, 이 함수가 파일 생성, 수정, 빌드, 테스트 실행 등 다양한 작업을 수행하는 것이다.
샌드박스 보안 모델
도구 실행은 반드시 샌드박스 내에서 격리된다. OS별 구현 방식은 다음과 같다.
- macOS:
sandbox-exec+ Seatbelt 정책 파일로 파일시스템 접근, 네트워크 접근을 제한 - Linux: Landlock LSM(Linux Security Module)으로 파일시스템 접근을 제한하고, seccomp으로 시스템 콜을 필터링
이 샌드박스 계층이 에이전트 루프의 안전 장치 역할을 한다. 모델이 예상 밖의 명령을 생성하더라도 샌드박스 정책에 의해 차단되는 구조인 것이다.
확장 프로토콜
Codex CLI는 줄바꿈 구분 JSON(newline-delimited JSON) 와이어 프로토콜과 MCP(Model Context Protocol) 서버를 지원한다. 기본 shell 도구 외에 커스텀 도구를 추가하려면 MCP 서버를 구현하여 에이전트 루프에 연결할 수 있다. Codex CLI 저장소에서 설치 방법과 프로토콜 상세를 확인할 수 있다.
MCP 서버와 에이전트 루프 사이의 통신은 stdin/stdout 기반 줄바꿈 구분 JSON 스트림으로 이루어진다. 에이전트가 도구 호출을 결정하면 JSON 형태의 요청을 MCP 서버 프로세스에 전달하고, 서버는 실행 결과를 같은 형식으로 반환한다. 이 단순한 프로토콜 덕분에 Python, Go, Ruby 등 어떤 언어로든 MCP 서버를 작성할 수 있다.
도구 실행 결과의 output 필드는 문자열 타입이다. 바이너리 데이터나 구조화된 JSON을 반환하더라도 문자열로 직렬화해서 전달해야 한다. 에이전트 루프는 이 문자열을 그대로 다음 턴의 function_call_output으로 삽입하여 모델이 판단 근거로 사용하게 된다. tool call 결과가 길면 컨텍스트 윈도우를 빠르게 소모할 수 있으므로, MCP 서버 구현 시 출력 크기를 제한하는 설계가 필요하다.
project/
├── codex-cli/
│ └── src/
│ └── utils/
│ └── agent/
│ └── agent-loop.ts ← 에이전트 루프 핵심 로직
├── codex-rs/ ← Rust 재작성 코드
│ ├── core/ ← 루프 + 컨텍스트 관리
│ └── sandbox/ ← OS별 샌드박스 구현
└── docs/
OpenAI Codex 에이전트 루프 구조 커스터마이징 포인트
소스 코드 분석을 바탕으로 실제 커스터마이징이 가능한 지점을 정리한다.
1. parallel_tool_calls 플래그
기본값 false는 도구 호출을 순차 실행한다. 독립적인 파일 읽기 작업처럼 순서 의존성이 없는 경우 true로 변경하면 턴당 처리 속도가 개선될 수 있다. 다만 파일 쓰기 → 읽기 같은 의존 관계가 있으면 race condition이 발생할 수 있으므로 주의가 필요하다.
2. Rate Limit 대기 시간
OPENAI_RATE_LIMIT_RETRY_WAIT_MS 환경 변수로 기본 대기 시간을 조정 가능하다. API 사용량이 많은 팀이라면 이 값을 높여서 429 응답 빈도를 줄이는 전략이 유효한 경우가 있다.
3. 컨텍스트 모드 전환
disableResponseStorage 설정으로 서버 측 / 클라이언트 측 컨텍스트 관리를 전환할 수 있다. 보안 요구사항과 세션 길이에 따라 선택하면 된다.
4. 샌드박스 정책 조정
macOS의 Seatbelt 정책 파일이나 Linux의 Landlock 규칙을 수정하면 도구 실행의 접근 범위를 조정할 수 있다. 특정 디렉토리만 쓰기 허용하거나 네트워크 접근을 완전 차단하는 등의 세밀한 제어가 가능하다. 단, 샌드박스를 느슨하게 설정하면 보안 리스크가 증가하므로 최소 권한 원칙을 유지하는 것이 바람직하다.
5. MCP 서버를 통한 도구 확장
기본 shell 함수 외에 데이터베이스 쿼리, HTTP 요청, 파일 변환 같은 커스텀 도구를 MCP 서버로 구현하여 에이전트 루프에 연결할 수 있다. Codex 프로젝트의 Rust 전환 논의에서 확장 아키텍처의 설계 배경을 확인할 수 있다.
| 커스터마이징 포인트 | 변경 방법 | 영향 범위 | 주의사항 |
|---|---|---|---|
| parallel_tool_calls | API 호출 파라미터 | 턴당 처리 속도 | 의존 관계 있는 명령 시 race condition |
| Rate Limit 대기 | 환경 변수 | 재시도 간격 | 너무 낮으면 연속 429 발생 |
| 컨텍스트 모드 | disableResponseStorage | 요청 크기, 프라이버시 | 클라이언트 모드는 긴 세션에서 토큰 비용 증가 |
| 샌드박스 정책 | OS별 정책 파일 | 도구 실행 권한 | 최소 권한 원칙 위반 시 보안 리스크 |
| MCP 도구 확장 | MCP 서버 구현 | 도구 종류 | 프로토콜 호환성 검증 필요 |
실전 적용 시 고려해야 할 트레이드오프
에이전트 루프 구조를 실제 프로젝트에 적용할 때 고려할 요소를 정리한다.
비용 vs 정확도
턴 수가 늘어날수록 API 호출 비용이 선형으로 증가한다. 모델이 한 번에 정확한 코드를 생성하면 1턴으로 끝나지만, 빌드 에러를 만나 수정-재시도를 반복하면 5~10턴까지 늘어나기도 한다. 서버 측 컨텍스트 모드에서는 델타만 전송하므로 입력 토큰 비용은 억제되는 편이지만, 출력 토큰은 턴마다 전액 과금된다.
속도 vs 안전성
parallel_tool_calls: true로 바꾸면 독립 작업의 병렬 실행으로 속도가 빨라진다. 하지만 에이전트가 생성하는 명령 간 암묵적 의존성을 완벽히 파악하기 어렵기 때문에, 안전을 우선한다면 기본값 false를 유지하는 것이 합리적인 선택이다.
프라이버시 vs 효율
클라이언트 측 컨텍스트 모드는 서버에 상태를 남기지 않아 보안 감사(audit)에 유리하다. 그러나 30턴 이상의 긴 세션에서는 매 요청에 전체 이력을 전송하므로 네트워크 대역폭과 토큰 비용이 급증하게 된다. 세션 길이의 상한선을 정해두고 초과 시 새 세션으로 전환하는 운영 패턴이 효과적일 때가 있다.
2026-04-23 기준 platform.openai.com의 Codex 가이드 문서가 403으로 접근 불가한 상태다. API 수준의 공식 문서 팩트가 부재하므로, 이 글의 분석은 GitHub 소스 코드와 공개 토론을 기반으로 한다.
OpenAI Codex 에이전트 루프 구조는 while (turnInput.length > 0) 기반의 반복 실행, Responses API 스트리밍 호출, 순차 도구 실행, 지수 백오프 에러 처리가 핵심 골격이다. 컨텍스트 관리는 서버 측과 클라이언트 측 두 모드를 지원하며, 샌드박스 격리로 도구 실행의 안전성을 확보하는 설계다.
TypeScript에서 Rust로의 전환은 에이전트 루프의 런타임 효율을 근본적으로 개선한 변화이며, MCP 프로토콜 지원으로 도구 확장 경로도 열려 있다.
다음 단계로는 Codex 컨텍스트 컴팩션 전략이 주목할 영역이다. 긴 세션에서 컨텍스트 윈도우 관리 방식이 에이전트 성능에 직접 영향을 미치는데, 이 부분의 공식 스펙이 아직 미공개 상태이므로 업데이트를 주시할 필요가 있다. 그리고 Codex CLI 아키텍처를 참고하여 자체 AI 코딩 에이전트를 구축하는 방향도 고려할 만하다. OpenAI Responses API 기반으로 에이전트 루프를 직접 구현하면 Codex CLI의 설계 결정을 더 깊이 이해할 수 있고, 프로젝트 요구사항에 맞는 Codex 에이전트 루프 구조를 설계할 수 있게 된다.
관련 글
- GPT-5 Codex CLI 사용법 7단계 — 설치·인증·API 호출·에이전트 태스크 완전 정복 – OpenAI Codex CLI 설치, 인증, GPT-5-Codex 모델 API 호출, AGENTS.md 에이전트 태스크 설정, config…
- OpenAI Codex 보안 취약점 탐지 5단계: SQL 인젝션·XSS 자동 스캔 실전 가이드 – 레거시 PHP·Node.js 코드베이스에 OpenAI Codex를 붙여 SQL 인젝션과 XSS 취약점을 자동으로 찾아낸 경험. 프롬프트 설…