7P by darjeeling 9시간전 | ★ favorite | 댓글 2개

요약:

  • 에이전트 루프(Agent Loop)의 구조: Codex CLI가 사용자 입력, 모델 추론, 도구(Tool) 실행을 조율하여 실제 작업을 수행하는 순환적 프로세스를 상세히 설명합니다.
  • 프롬프트 구성 및 Responses API: 시스템 명령, 도구 정의, 로컬 환경 컨텍스트가 Responses API의 JSON 페이로드로 변환되는 과정과 데이터 흐름을 분석합니다.
  • 성능 최적화 및 상태 관리: 프롬프트 캐싱(Prompt Caching)을 극대화하기 위한 전략과 컨텍스트 윈도우 제한을 극복하기 위한 대화 압축(Compaction) 기술, 그리고 ZDR(Zero Data Retention)을 위한 무상태(Stateless) 설계 원칙을 다룹니다.

상세요약:
OpenAI 엔지니어링 팀은 로컬 소프트웨어 에이전트인 Codex CLI의 핵심 로직인 '에이전트 루프(Agent Loop)'의 작동 원리를 심층 분석한 기술 아티클을 공개했습니다. 이 글은 사용자의 명령을 받아 모델과 상호작용하고, 도구를 실행하며 결과를 반환하는 전체 라이프사이클을 기술적인 관점에서 설명합니다.

1. 에이전트 루프 (The Agent Loop)

에이전트 루프는 사용자의 입력을 받아 작업을 완료할 때까지 모델과 상호작용하는 순환 구조입니다.

  • 프로세스: 사용자 입력 -> 프롬프트 생성 -> 모델 추론(Inference) -> (도구 호출 요청 -> 도구 실행 -> 결과 첨부 -> 재추론) 반복 -> 최종 응답.
  • 턴(Turn): 사용자의 입력부터 모델이 최종적으로 사용자에게 메시지(Assistant Message)를 보낼 때까지의 과정을 하나의 '턴'이라고 합니다. 이 과정에서 에이전트는 수백 번의 도구 호출(예: ls 실행, 파일 수정 등)을 수행할 수 있습니다.

2. 모델 추론과 Responses API

Codex CLI는 Responses API를 통해 모델과 통신합니다. 이 API는 https://chatgpt.com/backend-api/codex/responses, https://api.openai.com/v1/responses, 또는 로컬 호스트(Ollama 등)와 같이 설정 가능합니다.

초기 프롬프트 구성 (Building the Initial Prompt)

프롬프트는 단순한 텍스트가 아니라 instructions, tools, input 등으로 구성된 구조화된 데이터입니다.

  • Instructions: 시스템 또는 개발자 메시지로, 모델의 행동 지침을 정의합니다. (예: ~/.codex/config.toml 설정 파일 참조)
  • Tools: 모델이 사용할 수 있는 도구 정의 목록입니다. 쉘(shell) 실행, 계획 업데이트(update_plan), 웹 검색, 그리고 사용자 정의 MCP(Model Context Protocol) 서버 도구 등이 포함됩니다.
  • Input: 모델에 전달되는 실제 데이터 목록입니다. 여기에는 샌드박스 권한 설정, 프로젝트별 지침, 그리고 현재 작업 디렉토리(cwd) 및 쉘 종류와 같은 환경 컨텍스트(Environment Context) 가 포함됩니다.

JSON 페이로드 예시:

{  
  "type": "message",  
  "role": "user",  
  "content": [  
    {  
      "type": "input_text",  
      "text": "README.md에 아키텍처 다이어그램을 추가해줘"  
    }  
  ]  
  // ... 이전에 정의된 환경 컨텍스트 및 권한 설정 등이 함께 전송됨  
}  
  

3. 도구 실행과 데이터 흐름

모델이 도구 호출(Function Call)을 요청하면, 에이전트는 이를 실행하고 결과를 대화 기록에 추가하여 다시 모델을 호출합니다.

도구 실행 후 재요청 JSON 예시:

[  
  /* ... 이전 입력 항목들 ... */  
  {  
    "type": "reasoning", // 모델의 추론 과정 (CoT)  
    "summary": [...],  
    "encrypted_content": "gAAAAABpaDW..." // 암호화된 추론 내용  
  },  
  {  
    "type": "function_call",  
    "name": "shell",  
    "arguments": "{\"command\":\"cat README.md\",\"workdir\":\"/Users/mbolin/code/codex5\"}",  
    "call_id": "call_8675309..."  
  },  
  {  
    "type": "function_call_output", // 도구 실행 결과  
    "call_id": "call_8675309...",  
    "output": "<p align=\"center\"><code>npm i -g @openai/codex</code>..."  
  }  
]  
  

이전 프롬프트가 새 프롬프트의 정확한 접두사(Prefix) 가 되도록 구성하는 것이 중요합니다. 이는 후술할 프롬프트 캐싱 효율을 결정짓습니다.

4. 성능 고려사항: 캐싱과 ZDR

대화가 길어질수록 프롬프트의 크기는 선형적으로 증가하며, 이는 비용과 지연 시간을 증가시킵니다.

  • 프롬프트 캐싱(Prompt Caching): OpenAI 모델은 프롬프트의 앞부분이 일치할 경우(Prefix Match) 이전 연산 결과를 재사용하여 속도를 높입니다.

  • 캐시 미스(Cache Miss) 방지: 도구 목록 변경, 샌드박스 설정 변경 등이 대화 중간에 발생하면 캐시가 깨질 수 있습니다. 이를 방지하기 위해 Codex는 설정 변경을 기존 메시지 수정이 아닌 새 메시지 추가(Append) 방식으로 처리합니다.

  • 무상태(Stateless) 및 ZDR: previous_response_id와 같은 파라미터를 사용하지 않고 매번 전체 문맥을 전송합니다. 이는 서버에 데이터를 저장하지 않는 Zero Data Retention (ZDR) 정책을 준수하기 위함입니다. 암호화된 추론 내용(encrypted_content)을 클라이언트가 받아 다시 서버로 보내는 방식을 통해, 서버는 상태를 저장하지 않고도 이전 추론 문맥을 복원할 수 있습니다.

5. 컨텍스트 윈도우 관리 (Compaction)

토큰 제한을 넘지 않기 위해 Codex는 /responses/compact 엔드포인트를 사용해 대화 기록을 압축합니다. 단순 요약이 아니라, 모델의 잠재적 이해(Latent understanding)를 보존하는 encrypted_content를 포함한 압축된 항목 리스트를 반환받아 기존 입력을 대체합니다.