출처·저작권 본문은 OpenAI의 기술 글 Unlocking the Codex harness: how we built the App Server 및 한국어 페이지를 참고해 옮기고 다듬었습니다. Codex, App Server, harness, MCP, JSON-RPC, TUI, stdio, JSONL, SSE 같은 전문 용어는 원문 표기를 유지했습니다. 아래 그림 URL은 원문 페이지에 삽입된 것과 동일한 Contentful
images.ctfassets.net주소입니다.
작성: Celia Chen (OpenAI, Member of the Technical Staff) — 원문 게시 2026년 2월 4일.
OpenAI의 코딩 에이전트 Codex는 웹 앱, CLI, IDE 확장, Codex macOS 앱처럼 여러 surface에서 쓰입니다. 안쪽에서는 모두 같은 Codex harness—모든 Codex 경험의 밑바탕이 되는 agent loop와 로직—으로 돌아갑니다. 그 사이를 잇는 고리가 Codex App Server 입니다. 클라이언트가 쓰기 좋은 양방향 JSON-RPC API이고, 엄밀히는 아래 각주 1처럼 JSON-RPC lite + JSONL over stdio 형태입니다.
이 글에서는 App Server를 소개하고, 제품에 Codex를 붙일 때 지금까지 배운 점—아키텍처·프로토콜·여러 Codex surface에서의 통합, 코드 리뷰·SRE 에이전트·코딩 어시스턴트로 쓰는 팁까지—을 정리합니다.
App Server가 생기기까지
아키텍처로 들어가기 전에 짧은 배경이 있습니다. 처음 App Server는 여러 제품에서 Codex harness를 재쓰기 위한 실용적인 해법이었고, 점차 표준 프로토콜로 자리 잡았습니다.
Codex CLI는 TUI(터미널 UI)로 시작했습니다. 즉 Codex는 터미널로 접근됩니다. VS Code 확장처럼 IDE에 더 맞는 방식이 필요해졌을 때, 같은 harness로 같은 agent loop를 IDE UI에서 돌리되, 다시 구현하지는 않는 길이 필요했습니다. request/response 너머로, 워크스페이스 탐색, 추론 중 진행 상황 스트리밍, diff 출력 같은 풍부한 패턴이 필요했습니다. 먼저 Codex를 MCP server로 노출하는 실험을 했지만, VS Code에 맞게 MCP 시맨틱을 유지하는 일이 어렵다는 판단이 났습니다. 대신 TUI loop를 닮은 JSON-RPC 프로토콜을 넣었고, 그검이 비공식 첫 App Server이 되었습니다. 당시에는 다른 클라이언트가 App Server에 의존할 거라 예상하지 않아, 안정적인 API로는 설계되어 있지 않았습니다.
몇 달간 Codex 도입이 넓어지면서, 내부 팀과 외부 파트너는 같은 harness를 자기 제품에 넣고 싶어했습니다. JetBrains·Xcode는 IDE급 에이전트 경험을, 데스크톱 앱은 여러 Codex 에이전트를 병렬로 조율하는 쪽을 원했습니다. 그래서 우리 제품과 파트너 통합이 시간이 지나도 안전하게 의존할 수 있는 플랫폼 surface를 설계하게 되었습니다. 통합은 쉽게, backward compatible하게—프로토콜을 바꿔도 기존 클라이언트가 깨지지 않게—가 요구였습니다.
Codex harness 안과 App Server의 역할
Codex harness 안에 무엇이 있는지, App Server가 클라이언트에 어떻게 이를 드러내는지부터 보겠습니다. 이전 Codex 글에서는 사용자·모델·tool 사이를 조율하는 핵심 agent loop를 풀었습니다. 그것이 harness의 핵심 로직이지만, 전체 에이전트 경험에는 더 있습니다.
-
Thread 생명주기와 지속성. Thread는 사용자와 에이전트 사이의 Codex 대화입니다. Codex는 thread를 만들고, 재개·포크·보관하고, 이벤트 기록을 남겨 클라이언트가 다시 붙어도 같은 타임라인을 그릴 수 있게 합니다.
-
설정과 인증. Codex는 설정을 읽고, 기본값을 관리하며, “Sign in with ChatGPT” 같은 인증 흐름과 자격 증명 상태를 다룹니다.
-
Tool 실행과 확장. Codex는 sandbox에서 shell/file tool을 실행하고, MCP server·skills 같은 통합을 묶어, 같은 policy 모델 아래에서 agent loop에 참여시킵니다.
여기까지 말한 에이전트 로직(핵심 agent loop 포함)은 Codex CLI 코드베이스의 Codex core 에 있습니다. Codex core는 에이전트 코드가 모인 라이브러리이자, agent loop를 돌리고 하나의 Codex thread 지속성을 관리하는 런타임입니다.
Codex harness가 쓰이려면 클라이언트가 여기에 닿아야 합니다. 그 지점이 App Server입니다.
App Server는 클라이언트와 서버 사이의 JSON-RPC 프로토콜이면서, Codex core thread를 호스팅하는 장기 실행 프로세스입니다. 아래 그림처럼, 프로세스에는 stdio reader, Codex message processor, thread manager, core threads 네 덩어리가 있습니다. Thread manager가 thread마다 core session을 하나씩 띄우고, message processor가 각 core session과 직접 통신해 클라이언트 요청을 넣고 업데이트를 받습니다.
클라이언트 요청 하나가 많은 이벤트 업데이트로 이어질 수 있고, 그 세부 이벤트 덕분에 App Server 위에 풍부한 UI를 얹을 수 있습니다. stdio reader와 message processor는 클라이언트와 Codex core thread 사이의 번역 계층입니다. 클라이언트 JSON-RPC 요청을 Codex core 작업으로 바꾸고, Codex core 내부 이벤트 스트림을 듣다가, 낮은 수준의 이벤트를 적고 안정적이며 UI에 쓰기 좋은 소수의 JSON-RPC notification으로 바꿉니다.
클라이언트와 App Server 사이의 JSON-RPC는 완전 양방향입니다. 전형적인 thread에는 클라이언트 요청과 여러 서버 알림이 있습니다. 또 에이전트가 승인 같은 입력이 필요하면 서버가 요청을 먼저 보낼 수 있고, 클라이언트가 응답할 때까지 turn을 잠시 멈출 수 있습니다.
대화 프리미티브 (Item, Turn, Thread)
App Server 프로토콜의 기본 블록인 conversation primitives를 나눕니다. Agent loop용 API 설계는 까다롭습니다. 사용자·에이전트 상호작용이 단순 request/response가 아니기 때문입니다. 사용자 요청 하나가 구조화된 행동의 나열로 펼쳐질 수 있고, 클라이언트는 그걸 충실히 표현해야 합니다—사용자 입력, 에이전트의 점진적 진행, 중간 산출물(예: diff)까지요. 그 스트림을 여러 UI에서 통합·복원하기 쉽게 하려고, 경계와 생명주기가 분명한 세 가지 primitive에 맞췄습니다.
-
Item — Codex에서 입출력의 원자 단위입니다. 타입이 정해져 있고(예: 사용자 메시지, 에이전트 메시지, tool 실행, 승인 요청, diff), 각 타입마다 명시적인 생명주기가 있습니다.
- 시작:
item/started - 스트리밍 타입이면 선택적으로
item/*/delta - 끝:
item/completed
클라이언트는started에서 바로 그리기 시작하고,delta로 조각을 이어 받고,completed로 마무리합니다.
- 시작:
-
Turn — 사용자 입력으로 시작하는 에이전트 작업의 한 단위입니다. 클라이언트가 입력(예: “run tests and summarize failures”)을 내면 시작하고, 에이전트가 그 입력에 대한 출력을 다 만들면 끝납니다. 한 turn 안에는 중간 단계와 산출물을 나타내는 item들의 순서가 들어갑니다.
-
Thread — 사용자와 에이전트 사이 진행 중인 Codex 세션을 담는 지속 컨테이너입니다. 여러 turn을 포함합니다. 만들고, 재개·포크·보관할 수 있고, 기록은 유지되어 클라이언트가 다시 연결해도 같은 타임라인을 그릴 수 있습니다.
initialize 핸드셰이크
대화가 시작될 때 클라이언트와 서버는 initialize handshake를 맞춥니다. 클라이언트는 다른 메서드보다 먼저 단일 initialize 요청을 보내야 하고, 서버는 응답으로 확인합니다. 서버가 capability를 알릴 수 있고, 본 작업 전에 프로토콜 버전, feature flag, 기본값에 합의할 수 있습니다.
Thread / turn 알림
클라이언트가 새 요청을 하면 서버는 thread를 만들고 이어서 turn을 만듭니다. 진행을 thread/started, turn/started 같은 알림으로 돌려보냅니다. 사용자 메시지처럼 item으로 등록되는 입력도 함께 보냅니다.
Tool 호출과 선택적 승인
Tool 호출도 클라이언트에는 item으로 전달됩니다. 서버는 실행 전에 클라이언트 승인을 묻는 server-initiated request를 보낼 수 있고, 클라이언트가 “allow” 또는 “deny”로 답할 때까지 turn이 멈춥니다. VS Code 확장에서의 승인 흐름은 아래 그림과 같습니다.

마지막으로 서버는 에이전트 메시지를 보내고 turn/completed로 turn을 닫습니다. 에이전트 메시지는 delta 이벤트로 조각 스트리밍되다가 item/completed로 확정됩니다.
다이어그램의 메시지는 읽기 쉽게 단순화되어 있습니다. 한 turn 전체 JSON을 보려면 Codex CLI 저장소에서 테스트 클라이언트를 실행할 수 있습니다.
codex debug app-server send-message-v2 "run tests and summarize failures"클라이언트 통합
App Server로 여러 surface에서 Codex를 어떻게 심는지, 로컬 앱·IDE, Codex Web, TUI 세 패턴으로 보겠습니다.
공통으로 전송은 stdio 위의 JSON-RPC(JSONL)입니다. JSON-RPC면 원하는 언어로 클라이언트 바인딩을 만들기 쉽습니다. Codex surface와 파트너 통합은 Go, Python, TypeScript, Swift, Kotlin 등으로 App Server 클라이언트를 구현했습니다. TypeScript는 Rust 프로토콜에서 정의를 바로 뽑을 수 있습니다.
codex app-server generate-ts다른 언어는 JSON Schema 묶음을 만들어 코드 생성기에 넣으면 됩니다.
codex app-server generate-json-schema로컬 앱·IDE
로컬 클라이언트는 보통 플랫폼별 App Server 바이너리를 번들하거나 받아와 장기 실행 child process로 띄우고, JSON-RPC용 양방향 stdio 채널을 유지합니다. VS Code 확장·데스크톱 앱 예시에서는 배포 아티팩트에 플랫폼별 Codex 바이너리가 들어가고, 검증된 버전에 고정되어 클라이언트가 항상 같은 비트를 돌립니다.
모든 통합이 클라이언트 업데이트를 자주 낼 수 있는 것은 아닙니다. Xcode 같은 파트너는 클라이언트는 안정적으로 두고, 필요할 때 더 새 App Server 바이너리를 가리키게 해 릴리스 주기를 분리합니다. 그러면 Codex core의 auto-compaction 개선이나 새 config 키 지원 같은 서버 쪽 개선과 버그 수정을, 클라이언트 릴리스를 기다리지 않고 적용할 수 있습니다. App Server의 JSON-RPC 표면은 backward compatible하게 설계되어, 오래된 클라이언트도 새 서버와 안전하게 통신합니다.

Codex Web
Codex Web은 Codex harness를 쓰되 컨테이너 환경에서 돌립니다. worker가 체크아웃된 워크스페이스로 컨테이너를 준비하고, 안에서 App Server 바이너리를 띄우며, stdio를 통해 장기 JSON-RPC 채널을 유지합니다(호스팅 환경에서는 각주 2처럼 네트워크로 터널링될 수 있음). 브라우저 탭의 웹 앱은 HTTP와 SSE로 Codex 백엔드와 말하고, worker가 만든 작업 이벤트를 스트리밍합니다. 브라우저 UI는 가볍게 두면서도 데스크톱과 웹에서 같은 런타임을 쓰는 그림입니다.
웹 세션은 수명이 짧습니다(탭 종료, 네트워크 끊김). 그래서 장시간 작업의 진실한 소스는 브라우저가 아니라 서버에 두는 편이 낫습니다. 상태·진행을 서버에 두면 탭이 사라져도 작업은 이어집니다. 스트리밍 프로토콜과 저장된 thread 세션이 있으면 새 세션이 다시 붙어, 클라이언트에서 상태를 다시 짓지 않고도 따라잡을 수 있습니다.

TUI / Codex CLI
예전에는 TUI가 agent loop와 같은 프로세스에서 도는 “네이티브” 클라이언트였고, app-server 프로토콜이 아니라 Rust core 타입과 직접 통신했습니다. 초기 반복은 빨랐지만 TUI만 예외 surface가 되기도 했습니다.
이제 App Server가 있으니, TUI를 리팩터링해 다른 클라이언트처럼—App Server child를 띄우고 stdio로 JSON-RPC를 말하고, 같은 스트리밍 이벤트·승인을 그리도록—옮길 계획입니다. 그러면 TUI가 원격 머신의 Codex 서버에 붙는 흐름도 가능해지고, 에이전트는 compute에 가깝게 두고 노트북이 절전·단절되어도 작업은 이어지며, 로컬에서는 여전히 라이브 업데이트와 제어를 줄 수 있습니다.

어떤 프로토콜을 쓸지
Codex App Server는 앞으로 1순위로 유지·발전시킬 통합 방식이지만, 기능이 더 제한적인 다른 길도 있습니다. 기본적으로는 App Server를 권하지만, 선택지를 알아두는 것이 좋습니다.
JSON-RPC 계열
-
Codex를 MCP server로 —
codex mcp-server를 실행하고 stdio server를 지원하는 MCP 클라이언트(예: OpenAI Agents SDK)에서 연결합니다. 이미 MCP 기반 워크플로가 있고 Codex를 호출 가능한 tool로 쓰고 싶을 때 맞습니다. 단, MCP가 노출하는 범위만 쓸 수 있어, diff 업데이트처럼 더 풍부한 session semantics에 기대는 Codex 전용 상호작용은 MCP 엔드포인트에 깔끔히 매핑되지 않을 수 있습니다. -
공급자 간 agent harness 프로토콜 — 여러 모델 공급자·런타임을 겨냥한 이식 가능한 인터페이스입니다. 여러 에이전트를 한 추상화로 조율할 때 맞을 수 있습니다. 대신 능력의 공통 부분집합으로 수렴하기 쉬워, 공급자별 tool·session semantics가 중요할 때는 더 풍부한 표현이 어려울 수 있습니다. 이 공간은 빠르게 변하고, skills 같은 공통 표준이 더 나올 것으로 봅니다.
-
Codex App Server — 전체 Codex harness를 안정적이고 UI 친화적인 이벤트 스트림으로 노출하고 싶을 때 고릅니다. agent loop 전체 기능뿐 아니라 Sign in with ChatGPT, 모델 탐색, 설정 관리 같은 주변 기능도 함께 씁니다. 비용은 통합 작업—언어별 JSON-RPC 바인딩을 직접 짜야 한다는 점—에서 옵니다. 다만 JSON Schema와 문서를 주면 Codex가 상당 부분을 대신 짜 주기도 했고, 함께 일한 팀들은 비교적 빨리 동작하는 통합에 도달했습니다.
그 밖에 Codex를 심는 방법
-
Codex Exec — 일회성 작업·CI용 가벼운 스크립트형 CLI. 한 명령이 non-interactive로 끝까지 돌고, 로그용 구조화 출력을 스트리밍하며, 성공·실패 신호와 함께 종료하는 자동화·파이프라인에 맞습니다.
-
Codex SDK — 자기 애플리케이션 안에서 로컬 Codex 에이전트를 코드로 제어하는 TypeScript 라이브러리입니다. 별도 JSON-RPC 클라이언트 없이 서버 측 도구·워크플로에 네이티브 라이브러리 인터페이스가 필요할 때 맞습니다. App Server보다 먼저 나와 지금은 언어·표면이 더 좁습니다. 수요가 있으면 App Server 프로토콜을 감싼 추가 SDK로 harness 표면을 더 넓히는 방향도 고려할 수 있습니다.
마치며
이 글에서는 에이전트와 상호작용하는 새 표준을 어떻게 설계하는지, Codex harness를 안정적이고 클라이언트 친화적인 프로토콜로 꺼내는지를 공유했습니다. App Server가 Codex core를 노출하고, 클라이언트가 전체 agent loop를 구동하게 하며, TUI·로컬 IDE 통합·웹 런타임까지 넓은 surface를 받치는 방식을 다뤘습니다.
직접 워크플로에 Codex를 붙이는 아이디어가 떠올랐다면 App Server를 한번 돌려보는 것을 권합니다. 소스는 Codex CLI 오픈소스 저장소에 있습니다. 피드백과 기능 요청은 언제든 환영합니다.
각주
-
JSON-RPC lite 변형을 씁니다. 요청·응답·알림 형태는 유지하되
"jsonrpc": "2.0"헤더는 생략하고, 엄격한 JSON-RPC 2.0이 아니라 stdio 위 JSONL로 프레이밍합니다. -
여기서 stdio는 컨테이너 안 app-server의 stdin/stdout을 가리킵니다. 호스팅 구성에서는 이 스트림이 지속적인 네트워크 연결(WebSocket류)로 런타임에 터널링되는 경우가 많아, 문자 그대로의 로컬 파이프가 아니어도 stdio처럼 동작합니다.
더 읽기 (원문 링크)
- 모델에서 에이전트까지: Responses API에 computer environment 제공 (2026-03-11)
- 사용 한도 너머: Codex와 Sora 접근 확장 (2026-02-13)
- Harness engineering: agent-first 세계에서 Codex 활용 (2026-02-11)