Ubuntu 24.04 서버에서 Gitea Issue를 시작점으로 Codex CLI가 코드를 수정하고 Pull Request를 생성하는 Coding Agent Server를 구성하는 방법을 정리합니다.
이 구조에서는 Gitea Issue에 codex-ready label이 추가되면 Go 기반 Agent Server가 작업을 시작합니다. Agent Server는 Ticket별로 격리된 Docker Compose 환경을 만들고, Codex CLI를 실행하여 코드를 수정한 뒤 Validation, Git commit/push, Gitea Pull Request 생성까지 자동으로 처리합니다.
Pull Request의 최종 승인은 사람이 수행하며, 승인된 Agent PR에 대해서만 Agent Server가 Gitea API를 호출하여 dev branch까지 merge합니다.
HTTP Router는 go-chi v5를 사용합니다.
Coding Agent Server의 자동화 범위는
devmerge까지입니다.dev → stg → main승격, QA, 운영 배포는 사람이 담당하도록 경계를 분리합니다.
전체 구조
구성은 하나의 Ubuntu 24.04 서버에서 PostgreSQL, Gitea, Codex Agent Server를 서로 다른 실행 영역으로 분리합니다.
Ubuntu 24.04
│
├─ postgres-svc
│ └─ Rootless Docker daemon A
│ └─ PostgreSQL 18
│ ├─ DB: gitea / role: gitea
│ └─ DB: codex_agent / role: codex_agent
│
├─ gitea-svc
│ └─ Rootless Docker daemon B
│ └─ Gitea 1.27.3-rootless
│ └─ TCP -> HOST_PRIVATE_IP:5432 -> PostgreSQL
│
└─ codex-agentd
├─ Go Agent Server (native/systemd, go-chi)
│ ├─ Gitea Webhook / REST API
│ ├─ Worker workflow orchestration
│ ├─ approved agent PR -> dev merge
│ ├─ GET /healthz
│ └─ GET /readyz
│
└─ Rootless Docker daemon C
└─ Docker Compose ticket project
├─ workspace-init : credential 없음
├─ Git Prepare : Gitea credential O / OpenAI X
├─ Codex : Gitea credential X / OpenAI O
├─ Validation : Gitea X / OpenAI X / network 기본 O
├─ Git Finalize : Gitea O / OpenAI X
└─ workspace-read : read-only / credential 없음
PostgreSQL, Gitea, Coding Worker를 하나의 Docker daemon에 모두 넣지 않고 세 개의 Rootless Docker daemon으로 분리하는 것이 핵심입니다.
이렇게 구성하면 서비스별 Docker socket, container, volume, image, network 범위를 분리할 수 있습니다.
특히 Codex Worker가 사용하는 Docker daemon C가 PostgreSQL이나 Gitea container를 직접 제어할 수 없도록 분리할 수 있다는 점이 중요합니다.
실행 계층과 책임
이 절에서는 Agent Server를 구성하는 세 실행 계층의 책임을 구분합니다. Dockerfile은 실행 이미지를 정의하고, compose.yaml은 Worker별 실행 환경을 정의하며, Go Agent Server는 전체 실행 순서와 실패 처리를 제어합니다.
Worker 실행 구조는 Dockerfile, Docker Compose, Go Agent Server의 세 계층으로 나눕니다.
Dockerfile
↓
codex-agent:local image 정의
compose.yaml
↓
Worker별 실행 환경
credential
volume
resource
network 정책 정의
Go Agent Server
↓
docker compose run 실행 순서
timeout
실패 처리
PR 생성
merge workflow 제어
각 계층의 책임을 명확하게 나누는 것이 중요합니다.
Dockerfile: 실행 이미지 정의
Dockerfile은 Worker가 사용할 기본 실행 이미지를 정의합니다.
예를 들어 다음과 같은 도구가 포함될 수 있습니다.
Ubuntu base image
Git
OpenAI Codex CLI
Go
Java / Gradle 실행 환경
필요한 shell utility
이미지의 목적은 Worker 실행에 필요한 프로그램을 제공하는 것입니다.
Ticket 처리 순서나 Gitea credential 전달 여부 같은 workflow 정책을 Dockerfile에 넣지 않습니다.
Docker Compose: Worker 실행 환경 정의
compose.yaml은 각 Worker가 어떤 환경에서 실행되는지를 정의합니다.
주요 책임은 다음과 같습니다.
service
environment
volume
network
credential
CPU / memory 제한
working directory
예를 들어 같은 codex-agent:local 이미지를 사용하더라도 Worker별로 전달되는 credential을 다르게 구성합니다.
| Worker | Gitea Credential | OpenAI Credential | Workspace |
|---|---|---|---|
workspace-init |
X | X | write |
git-prepare |
O | X | write |
codex |
X | O | write |
validation |
X | X | write |
git-finalize |
O | X | write |
workspace-read |
X | X | read-only |
Codex container에는 Gitea credential을 전달하지 않고, Git 작업을 수행하는 Worker에는 OpenAI credential을 전달하지 않습니다.
이렇게 하면 하나의 Worker가 불필요하게 여러 credential을 동시에 가지는 것을 줄일 수 있습니다.
Credential을 container image에 포함시키지 않습니다.
실행 시점에 필요한 Worker에만 전달하고, 작업 종료 후 Ticket Compose project와 함께 제거할 수 있도록 구성하는 것이 좋습니다.
Go Agent Server: Workflow 제어
Go Agent Server는 전체 workflow를 제어합니다.
주요 책임은 다음과 같습니다.
Gitea Webhook 수신
Issue 상태 확인
중복 실행 방지
Ticket workspace 생성
docker compose Worker 실행
Worker timeout 관리
실패 처리
Validation 결과 확인
Pull Request 생성
PR approval webhook 처리
Gitea merge API 호출
Worker 자체가 다음 Worker를 실행하도록 구성하지 않습니다.
예를 들어 codex Worker가 성공했다고 해서 직접 validation Worker를 실행하지 않습니다.
항상 Go Agent Server가 다음 순서를 결정합니다.
workspace-init
↓
git-prepare
↓
codex
↓
validation
↓
git-finalize
↓
Pull Request
이 방식으로 구성하면 workflow 상태와 오류 처리를 하나의 Agent Server에서 관리할 수 있습니다.
Git Workflow와 자동화 범위
이 절에서는 Gitea Issue가 Agent 작업으로 전환되는 과정과, Agent Server가 어디까지 자동화하고 사람이 어디부터 담당하는지를 구분합니다.
Agent 작업은 Gitea Issue에서 시작합니다.
Gitea Issue
↓
codex-ready label
↓
Gitea Webhook
↓
Agent Server
↓
origin/dev 기준 branch 생성
↓
agent/issue-N
↓
Codex 수정
↓
Validation
↓
Git commit
↓
agent/issue-N push
↓
PR: agent/issue-N -> dev
↓
사람의 Review / Approve
↓
pull_request_review_approved webhook
↓
Agent Server
↓
Gitea Merge API
↓
dev merge
Agent branch는 항상 현재 origin/dev를 기준으로 생성합니다.
예를 들어 Issue 번호가 123이라면 다음과 같은 branch를 사용할 수 있습니다.
agent/issue-123
Git 처리 흐름은 다음과 같습니다.
origin/dev
↓
agent/issue-123
↓
Codex 변경
↓
Validation
↓
commit
↓
push
↓
Pull Request
agent/issue-123 -> dev
이 구조에서는 Agent가 dev에 직접 push하지 않습니다.
반드시 별도의 branch를 생성하고 Pull Request를 통해 변경 내용을 검토할 수 있도록 합니다.
사람이 담당하는 승격 범위
Coding Agent Server의 책임은 dev merge까지입니다.
그 이후 환경 승격은 사람이 담당합니다.
Agent 자동화
Issue
↓
agent branch
↓
Codex
↓
Validation
↓
PR
↓
Review / Approve
↓
dev merge
이후에는 다음과 같이 운영합니다.
dev
↓
stg
↓
main
역할을 구분하면 다음과 같습니다.
| 구간 | 담당 |
|---|---|
| Issue → Agent PR 생성 | Agent Server |
| Agent PR Review | 사람 |
| Agent PR → dev merge | Agent Server |
| dev → stg PR | 사람 |
| QA | 사람 |
| stg → main PR | 사람 |
| 운영 배포 | 사람 |
Coding Agent가 운영 branch인 main까지 자동 승격하도록 하지 않는 구조입니다.
Protected Branch와 승인 처리
dev branch에는 Gitea Protected Branch 정책을 적용합니다.
Agent Server는 force_merge를 사용하지 않습니다.
따라서 다음과 같은 Gitea 보호 정책을 우회하지 않습니다.
Required approvals
Rejected review
Required status checks
Protected branch policy
사람이 Agent PR을 승인하면 Gitea에서 다음 webhook을 받을 수 있습니다.
pull_request_review_approved
Agent Server는 해당 webhook을 받은 뒤 Gitea Merge API를 호출합니다.
이때 필수 status check가 이미 완료된 경우에는 바로 merge할 수 있습니다.
반면 approval이 먼저 발생하고 필수 check가 아직 진행 중이라면 다음 설정을 사용해 merge를 요청할 수 있습니다.
merge_when_checks_succeed=true
이 경우 Gitea가 필요한 check가 성공한 이후 merge를 수행하도록 맡길 수 있습니다.
중요한 점은 Agent Server가 branch protection을 우회하는 방식으로 merge하지 않는 것입니다.
Ticket 실행 환경과 격리
이 절에서는 하나의 Issue를 처리하기 위해 생성되는 Ticket별 Compose project와 그 안에서 순차적으로 실행되는 Worker를 설명합니다.
각 Issue 처리는 별도의 Docker Compose project로 실행합니다.
Compose project name은 예를 들어 다음과 같이 구성할 수 있습니다.
codex-team-order-service-123-<delivery-hash>
각 부분은 다음과 같은 의미를 가질 수 있습니다.
codex
└─ Agent Worker
team-order-service
└─ repository 식별자
123
└─ Gitea Issue 번호
<delivery-hash>
└─ webhook delivery 또는 실행 instance 식별값
Ticket별 project name을 다르게 만들면 Docker Compose가 생성하는 resource도 분리됩니다.
예를 들어 다음과 같은 resource를 Ticket 단위로 관리할 수 있습니다.
container
network
volume
동시에 여러 Issue가 실행되더라도 서로 다른 Compose project로 분리할 수 있습니다.
Worker 실행 순서
Go Agent Server는 Worker를 docker compose run을 이용하여 one-off container로 실행합니다.
첫 번째 단계는 workspace 초기화입니다.
docker compose \
-f /var/lib/codex-agent/worker/compose.yaml \
-p <ticket-project> \
run --rm --no-deps -T workspace-init
Git repository를 준비합니다.
docker compose \
-f /var/lib/codex-agent/worker/compose.yaml \
-p <ticket-project> \
run --rm --no-deps -T git-prepare
Codex CLI를 실행합니다.
docker compose \
-f /var/lib/codex-agent/worker/compose.yaml \
-p <ticket-project> \
run --rm --no-deps -T codex
변경된 코드를 검증합니다.
docker compose \
-f /var/lib/codex-agent/worker/compose.yaml \
-p <ticket-project> \
run --rm --no-deps -T validation
검증이 성공하면 Git commit과 push를 수행합니다.
docker compose \
-f /var/lib/codex-agent/worker/compose.yaml \
-p <ticket-project> \
run --rm --no-deps -T git-finalize
전체 실행 흐름은 다음과 같습니다.
workspace-init
↓
git-prepare
↓
codex
↓
validation
↓
git-finalize
↓
Pull Request 생성
--rm을 사용하기 때문에 각 one-off container는 실행 종료 후 제거됩니다.
--no-deps는 해당 Worker를 실행할 때 Compose에 정의된 다른 service를 자동으로 시작하지 않도록 합니다.
-T는 pseudo-TTY 할당을 비활성화합니다. Agent Server와 같은 비대화형 프로그램에서 Compose 명령을 실행할 때 적합합니다.
workspace-init
workspace-init은 Ticket에서 사용할 workspace를 생성하는 단계입니다.
이 Worker에는 외부 credential을 전달하지 않습니다.
Gitea credential : 없음
OpenAI credential: 없음
주요 역할은 다음과 같습니다.
Ticket volume 준비
workspace directory 생성
permission 설정
기존 잔여 파일 확인
이 단계에서는 Git clone이나 Codex 실행을 하지 않습니다.
git-prepare
git-prepare Worker는 Gitea repository를 가져오고 Agent branch를 생성합니다.
이 Worker에는 Gitea credential만 전달합니다.
Gitea credential : 있음
OpenAI credential: 없음
개념적인 작업 순서는 다음과 같습니다.
repository clone
↓
origin/dev fetch
↓
origin/dev checkout 기준 준비
↓
agent/issue-N branch 생성
예를 들면 다음과 같은 형태입니다.
git fetch origin dev
git switch -c agent/issue-123 origin/dev
이후 Gitea credential이 필요하지 않은 작업은 다른 Worker가 수행합니다.
codex
Codex Worker는 실제 코드를 수정합니다.
이 Worker에는 OpenAI credential만 전달합니다.
Gitea credential : 없음
OpenAI credential: 있음
따라서 Codex가 코드 수정 과정에서 직접 Gitea에 branch를 push하거나 Pull Request를 생성하지 못하도록 책임을 분리할 수 있습니다.
Codex의 역할은 기본적으로 다음 범위입니다.
Issue 내용 분석
repository 분석
코드 변경
필요한 테스트 코드 변경
작업 결과 반환
Git credential과 OpenAI credential을 하나의 container에 동시에 넣지 않는 것이 이 구조의 중요한 보안 경계입니다.
validation
Codex 작업이 끝나면 별도의 Validation Worker가 변경 내용을 검증합니다.
기본 설정은 다음과 같습니다.
VALIDATION_MODE=auto
프로젝트에 존재하는 marker 파일을 확인하여 validator를 선택합니다.
| Marker | 실행 명령 |
|---|---|
go.mod |
go test -v ./... |
gradlew |
./gradlew test --no-daemon |
| 둘 다 존재 | 두 validator 순차 실행 |
Go 프로젝트라면 다음 명령을 실행합니다.
go test -v ./...
Gradle 프로젝트라면 다음 명령을 실행합니다.
./gradlew test --no-daemon
두 marker가 모두 존재하면 두 validation을 순차적으로 수행합니다.
go test
↓
Gradle test
Validation이 실패하면 workflow를 중단합니다.
Validation 실패
↓
git-finalize 실행 안 함
↓
commit 안 함
↓
push 안 함
↓
Pull Request 생성 안 함
Validation Worker에는 Gitea와 OpenAI credential을 모두 전달하지 않습니다.
Gitea credential : 없음
OpenAI credential: 없음
다만 Go module이나 Gradle dependency를 처음 받아야 할 수 있기 때문에 network는 기본적으로 허용합니다.
Validation
Gitea credential X
OpenAI credential X
Network O
모든 dependency를 사전에 cache하거나 내부 repository mirror를 사용하는 환경이라면 Validation Worker의 외부 network를 추가로 제한하는 방법을 고려할 수 있습니다.
Validation network를 무조건 차단하면
go mod download, Maven Central, Gradle Plugin Portal 등의 의존성 다운로드 때문에 정상적인 프로젝트도 검증에 실패할 수 있습니다.
외부 네트워크 차단은 dependency 공급 방법이 준비된 환경에서 적용하는 것이 좋습니다.
git-finalize
Validation이 성공한 경우에만 git-finalize를 실행합니다.
이 Worker에는 Gitea credential만 전달합니다.
Gitea credential : 있음
OpenAI credential: 없음
주요 작업은 다음과 같습니다.
git status 확인
commit 생성
agent branch push
예를 들어 다음과 같은 흐름입니다.
git status
git add .
git commit -m "Fix issue #123"
git push origin agent/issue-123
Push가 성공하면 Agent Server가 Gitea REST API를 사용하여 Pull Request를 생성합니다.
agent/issue-123
↓
dev
Pull Request 생성은 Worker가 아니라 Agent Server가 담당하도록 구성할 수도 있습니다.
이렇게 하면 repository 작업과 workflow orchestration의 책임을 더 명확히 나눌 수 있습니다.
workspace-read
workspace-read는 문제 분석이나 결과 확인이 필요한 경우 workspace를 읽기 전용으로 접근하기 위한 Worker입니다.
workspace : read-only
Gitea credential : 없음
OpenAI credential: 없음
예를 들어 Agent Server가 작업 결과를 확인하기 위한 제한된 command를 실행하거나 향후 troubleshooting 기능을 추가할 때 사용할 수 있습니다.
기본 workflow에서는 반드시 실행해야 하는 단계는 아닙니다.
Ticket 작업 종료와 정리
Ticket 처리가 끝나면 해당 Compose project의 resource를 제거합니다.
docker compose \
-f /var/lib/codex-agent/worker/compose.yaml \
-p <ticket-project> \
down -v --remove-orphans
-v를 사용하면 해당 Compose project가 사용하는 volume도 함께 제거됩니다.
--remove-orphans는 현재 Compose 파일에 정의되지 않은 orphan container가 project에 남아 있는 경우 함께 정리합니다.
Ticket workspace가 작업 종료 후 반드시 보존되어야 하는 구조라면 volume 삭제 정책은 별도로 설계해야 합니다.
현재 구조에서는 Git commit과 push가 완료된 이후 Ticket workspace를 임시 작업 공간으로 보고 제거하는 방식입니다.
Agent Server 상태 확인
이 절에서는 프로세스 생존 여부와 실제 작업 가능 여부를 각각 확인하는 /healthz, /readyz의 의미를 구분합니다.
Agent Server는 두 개의 health endpoint를 제공합니다.
GET /healthz
GET /readyz
두 endpoint의 의미는 서로 다릅니다.
/healthz: Liveness
/healthz는 Agent Server process의 liveness를 확인합니다.
즉, 프로세스 자체가 HTTP 요청을 처리할 수 있는지를 확인하는 endpoint입니다.
예를 들면 정상 상태에서 다음과 같이 응답할 수 있습니다.
HTTP/1.1 200 OK
Content-Type: application/json
{
"status": "ok"
}
외부 dependency 상태까지 /healthz에서 모두 확인하지 않는 것이 좋습니다.
Gitea가 일시적으로 장애가 발생했다고 해서 Agent Server process 자체가 죽은 것은 아니기 때문입니다.
/readyz: Readiness
/readyz는 실제 Ticket을 처리할 준비가 되었는지를 확인합니다.
현재 확인 대상은 다음과 같습니다.
Agent 전용 Rootless Docker daemon
Gitea REST API
Docker daemon은 다음 명령과 동일한 성격의 검사를 수행할 수 있습니다.
docker info
Gitea는 다음 API를 호출하여 확인할 수 있습니다.
GET /api/v1/version
따라서 의미는 다음과 같이 구분할 수 있습니다.
/healthz
↓
Agent Server process가 살아 있는가?
/readyz
↓
새로운 Ticket을 실제로 처리할 준비가 되었는가?
상태 관리와 PostgreSQL
이 절에서는 Gitea용 DB와 Agent Server용 DB의 역할, 그리고 현재 메모리 기반 상태를 향후 PostgreSQL로 이전할 수 있는 범위를 설명합니다.
PostgreSQL 18에는 두 개의 database와 role을 준비합니다.
PostgreSQL 18
│
├─ DB: gitea
│ └─ role: gitea
│
└─ DB: codex_agent
└─ role: codex_agent
gitea database는 Gitea에서 사용합니다.
codex_agent database는 Agent Server의 durable state를 저장하기 위한 용도입니다.
현재 MVP 단계에서는 다음 정보가 아직 process memory에 존재합니다.
webhook delivery dedup
issue active lock
즉, Agent Server가 재시작되면 memory 기반 상태가 사라질 수 있습니다.
codex_agent database는 향후 다음과 같은 상태를 영속적으로 관리하기 위한 준비입니다.
job state
webhook delivery idempotency
active issue lock
workflow execution
retry state
PR mapping
ticket execution history
초기 MVP에서는 DB를 먼저 만들어 두되, 실제 workflow 상태를 한 번에 모두 PostgreSQL로 옮기지 않아도 됩니다.
Webhook 중복 처리
Gitea Webhook은 같은 event가 다시 전달될 가능성을 고려해야 합니다.
따라서 단순히 codex-ready label event를 받았다는 이유만으로 새로운 Worker를 실행하면 안 됩니다.
예를 들어 동일한 Issue에 대해 다음 상황을 방지해야 합니다.
Webhook A
↓
Issue #123 실행
Webhook A 재전송
↓
Issue #123 다시 실행
MVP에서는 process memory 기반 delivery dedup과 active issue lock을 사용할 수 있습니다.
개념적으로 다음 두 상태를 구분할 수 있습니다.
delivery dedup
↓
같은 webhook delivery의 중복 처리 방지
issue active lock
↓
같은 Issue에서 여러 Agent workflow가 동시에 실행되는 것 방지
향후 codex_agent PostgreSQL DB로 이전하면 Agent Server가 재시작되더라도 이 상태를 유지할 수 있습니다.
Workflow 제어
이 절에서는 Worker 실행 중 실패가 발생했을 때의 중단 기준과 장시간 실행 작업에 대한 timeout 제어 방식을 설명합니다.
Worker workflow는 이전 단계가 성공해야 다음 단계로 넘어가도록 구성합니다.
workspace-init
↓ 성공
git-prepare
↓ 성공
codex
↓ 성공
validation
↓ 성공
git-finalize
↓ 성공
PR
중간에 실패하면 이후 단계는 실행하지 않습니다.
예를 들어 Codex가 실패했다면 다음과 같습니다.
workspace-init 성공
git-prepare 성공
codex 실패
validation 실행 안 함
git-finalize 실행 안 함
PR 생성 안 함
Validation이 실패한 경우도 동일합니다.
codex 성공
validation 실패
git-finalize 실행 안 함
push 실행 안 함
PR 생성 안 함
이 구조는 검증되지 않은 Agent 변경 사항이 원격 repository로 전달되는 것을 방지하는 데 도움이 됩니다.
Timeout 관리
Codex나 Validation 작업은 예상보다 오래 실행될 수 있기 때문에 각 Worker에는 timeout을 두는 것이 좋습니다.
Timeout은 container 내부 shell script보다 Agent Server에서 관리하는 것이 전체 workflow 상태를 파악하기 쉽습니다.
Go에서는 context.WithTimeout을 사용할 수 있습니다.
개념적으로 다음과 같은 구조입니다.
ctx, cancel := context.WithTimeout(
parentCtx,
workerTimeout,
)
defer cancel()
이 ctx를 exec.CommandContext에 전달하면 timeout이나 상위 context 취소가 발생했을 때 실행 중인 command를 종료시키는 흐름을 구성할 수 있습니다.
Go Agent Server
↓
context.WithTimeout
↓
docker compose run
↓
Worker
Worker별로 timeout 값을 다르게 적용할 수도 있습니다.
예를 들어:
workspace-init : 짧음
git-prepare : 중간
codex : 김
validation : 김
git-finalize : 중간
실제 값은 프로젝트 규모와 CI 실행 시간을 측정한 뒤 결정하는 것이 좋습니다.
설치 경로와 문서 구성
이 절에서는 Agent Server의 실행 파일, 설정, Worker 파일을 배치하는 경로와 설치 문서의 역할을 구분합니다.
Agent Server 설치 경로는 다음과 같이 구성할 수 있습니다.
/var/lib/codex-agent/
├─ worker/
│ ├─ Dockerfile
│ ├─ compose.yaml
│ └─ scripts/
│ ├─ workspace-init.sh
│ ├─ git-prepare.sh
│ ├─ codex.sh
│ ├─ validation.sh
│ └─ git-finalize.sh
│
├─ data/
└─ logs/
Agent Server 실행 binary는 /usr/local/bin에 둘 수 있습니다.
/usr/local/bin/codex-agentd
설정은 /etc 아래에 둘 수 있습니다.
/etc/codex-agent/
└─ config.env
즉, 역할을 다음처럼 나눌 수 있습니다.
| 경로 | 용도 |
|---|---|
/usr/local/bin/codex-agentd |
Agent Server 실행 파일 |
/etc/codex-agent |
설정 |
/var/lib/codex-agent |
Worker와 상태 데이터 |
| systemd | Agent Server lifecycle 관리 |
설치 문서 순서
전체 환경은 다음 순서로 설치합니다.
docs/INSTALL-POSTGRESQL-DOCKER.md
↓
docs/INSTALL-GITEA-DOCKER.md
↓
docs/INSTALL-UBUNTU.md
↓
docs/MONITORING-AGENT-SERVER.md
각 문서의 역할은 다음과 같습니다.
| 문서 | 역할 |
|---|---|
INSTALL-POSTGRESQL-DOCKER.md |
PostgreSQL Rootless Docker daemon과 DB 설치 |
INSTALL-GITEA-DOCKER.md |
Gitea Rootless Docker daemon과 PostgreSQL 연결 |
INSTALL-UBUNTU.md |
Codex Agent Server와 Worker 실행 환경 구성 |
MONITORING-AGENT-SERVER.md |
Agent Server 운영 및 monitoring 구성 |
전체 인프라 관계는 다음 문서에서 확인합니다.
docs/INFRASTRUCTURE-ARCHITECTURE.md
이 문서는 개별 설치 명령보다는 PostgreSQL, Gitea, Agent Server, Worker가 어떤 관계로 구성되는지를 설명하는 기준 문서로 사용하는 것이 좋습니다.
전체 운영 흐름
전체 workflow를 한 번에 보면 다음과 같습니다.
Developer
↓
Gitea Issue
↓
codex-ready label
↓
Gitea Webhook
↓
Go Agent Server
↓
Ticket Compose Project
│
├─ workspace-init
│
├─ git-prepare
│
├─ codex
│
├─ validation
│
└─ git-finalize
│
↓
agent/issue-N push
↓
Gitea Pull Request
↓
Human Review
↓
Approve
↓
Gitea Webhook
↓
Agent Server
↓
Gitea Merge API
↓
dev
그 이후 release workflow는 별도입니다.
dev
↓
사람이 PR 생성
↓
stg
↓
QA
↓
사람이 PR 생성
↓
main
↓
운영 배포
Agent 자동화와 release 자동화를 하나의 workflow로 묶지 않는 것이 현재 구조의 중요한 원칙입니다.
결론
이 Codex Agent Server 구조는 AI가 직접 Git repository 전체 권한을 가지고 임의로 작업하는 방식이 아니라, 작업 단계와 credential을 명확하게 분리한 Coding Agent workflow입니다.
핵심 구조는 다음 세 가지입니다.
Dockerfile
↓
Worker 실행 이미지 정의
Docker Compose
↓
credential / volume / network / resource 격리
Go Agent Server
↓
workflow / timeout / failure / PR / merge 제어
Ticket 단위 작업도 별도의 Compose project로 분리합니다.
Issue
↓
isolated workspace
↓
Codex
↓
Validation
↓
Agent branch
↓
Pull Request
↓
Human approval
↓
dev merge
Codex에는 OpenAI credential만 전달하고 Git Worker에는 Gitea credential만 전달하여 credential 범위를 분리합니다.
Validation에는 두 credential 모두 전달하지 않으며, 검증에 성공한 변경만 commit, push, Pull Request 단계로 진행합니다.
또한 Agent Server는 Gitea Protected Branch 정책을 우회하지 않고, 사람의 Pull Request 승인 이후에만 Gitea Merge API를 호출합니다.
이를 통해 AI Coding Agent가 코드 작성은 자동화하면서도 다음 영역은 사람이 통제할 수 있습니다.
PR Review
QA
stg 승격
main 승격
운영 배포
현재 MVP에서는 webhook dedup과 Issue active lock이 process memory 기반이지만, 미리 준비한 codex_agent PostgreSQL database를 이용해 durable job state와 idempotency 상태로 확장할 수 있습니다.
결과적으로 이 구조는 단순한 Codex CLI 자동 실행기가 아니라 Gitea Issue를 입력으로 받아 격리된 Worker에서 코드를 수정하고, 검증된 변경만 Pull Request로 전달한 뒤 사람의 승인을 거쳐 dev에 반영하는 Agent 기반 개발 workflow라고 볼 수 있습니다.
참고 자료
Docker Rootless Mode
https://docs.docker.com/engine/security/rootless/Docker Compose
run
https://docs.docker.com/reference/cli/docker/compose/run/Docker Compose Project Name
https://docs.docker.com/compose/how-tos/project-name/PostgreSQL Official Docker Image
https://hub.docker.com/_/postgresGitea Rootless Docker 설치
https://docs.gitea.com/installation/install-with-docker-rootless/Gitea Webhooks
https://docs.gitea.com/usage/repository/webhooks/Gitea Pull Request Merge API
https://docs.gitea.com/api/operations/repo-merge-pull-request/Go
contextPackage
https://pkg.go.dev/contextGo
os/execPackage
https://pkg.go.dev/os/execOpenAI Codex CLI
https://github.com/openai/codex
'AI Development > Workflow' 카테고리의 다른 글
| Rootless Docker daemon에 Gitea 설치 (1) | 2026.09.04 |
|---|---|
| Rootless Docker daemon에 PostgreSQL 18 설치하기 (0) | 2026.09.02 |
| Codex Agent Server 인프라 설계 — PostgreSQL / Gitea / Coding Agent의 3-daemon 분리 (0) | 2026.09.02 |
댓글