
AI 에이전트에게 수동 프롬프트를 입력하는 시대는 끝났다: 루프를 설계하는 시대로
요약
AI 에이전트 운용 시 수동 프롬프트 대신 루프의 상태(State)와 종료 조건(Exit Condition)을 설계하는 방법론을 다룹니다. 상태 전이 정의와 역할 분담을 통해 재현성을 높이고 안정적인 자동화 시스템을 구축하는 실전 경험을 공유합니다.
핵심 포인트
- 만능 프롬프트보다 상태 전이(State Transition) 설계가 우선되어야 함
- 실패 시 재개 가능한 상태(State) 정의가 재현성의 핵심
- 단일 대화에 모든 역할을 맡기지 말고 단계를 나누어 설계할 것
- 성공 경로보다 어중간한 상태에 대한 정의가 중요함
서론
AI 에이전트를 사용한 일일 운용에서 재현성을 가장 크게 해치는 요인은 모델 성능보다 '매번 요청하는 방식'이었습니다. 저의 환경에서도 처음에는 "오늘은 이 기사를 써줘", "공개해줘", "URL을 확인해줘", "플래너도 업데이트해줘"와 같이 그때마다 프롬프트로 보완하곤 했습니다. 하지만 이렇게 하면 어디까지 끝났는지, 실패했을 때 어디서부터 재개해야 하는지, 오늘의 한도에 도달했는지 등이 대화 속에 묻혀버립니다.
2026-06-10에 Zenn의 일일 공개를 단일 automation으로 통합했고, 2026-06-12에는 공개 URL이 404 상태로 멈추는 케이스를, 2026-06-17에는 일반적인 1건의 공개까지 실전에서 통과시켰습니다. 그때 효과를 본 것은 좋은 지시문을 매번 생각하는 것이 아니라, 루프(Loop)의 상태와 종료 조건(Exit Condition)을 먼저 설계하는 것이었습니다.
이 기사에서는 실제로 읽어본 ~/.codex/automations/zenn-daily-writer/automation.toml
, ~/.codex/skills/zenn-daily-writer/SKILL.md
, ~/workspace/scripts/codex_orchestrator.py
, 그리고 Zenn automation log를 바탕으로, 수동 프롬프트 중심의 운용에서 벗어나기 위해 최소한으로 필요했던 설계를 정리합니다.
1. 먼저 만들어야 할 것은 만능 프롬프트가 아니라 상태 전이(State Transition)
일일 운용을 대화만으로 돌리던 시절에는 실패해도 "다시 한번 해"라고 할 수밖에 없었습니다. 이를 그만두기 위해 Zenn 측의 automation에서는 처음에 상태를 정의했습니다. 실제 운용 로그에 남기고 있는 주요 상태는 ALL_DONE_DAILY_LIMIT
, PENDING_PUBLISH_CHECK
, PUBLISHED
입니다.
예를 들어 2026-06-12에는 기사 자체는 push 되었으나 공개 URL만 404인 어중간한 상태가 발생했습니다. 이때 새로운 기사를 만들지 않고, publish_check_failed
의 재확인을 최우선으로 하는 분기를 미리 넣어두었기에, 일일 태스크가 "새로운 생성을 반복하며 문제를 숨기는" 동작으로 이어지지 않을 수 있었습니다. 실제 automation log에서도 07:12 JST 시점에는 PENDING_PUBLISH_CHECK
에서 멈추고, 21:20 JST에 URL이 200으로 돌아온 후 PUBLISHED
로 종료되었습니다.
이 경험을 통해 알게 된 것은, AI 운용에서는 성공 경로(Success Path)보다 "어중간하게 끝났을 때의 이름"이 중요하다는 점입니다. 상태명이 있으면 다음 실행(run) 시 대화의 문맥을 읽지 않고도 재개할 수 있습니다. 반대로 상태명이 없으면 매번 "지난번에 어디까지 했지?"라는 인간을 향한 확인 작업이 남게 됩니다.
실제 daily writer에서도 시작할 때 보고 있는 것은 프롬프트 본문이 아니라 다음과 같은 판단 조건입니다.
- 하루 최대 1건
- publish_check_failed가 있으면 새로운 생성보다 먼저 재확인
- published:false인 기존 기사가 있으면 새로운 생성보다 먼저 리뷰
...
사람이 매번 "오늘은 무엇을 우선해야 하는가"를 생각하는 것이 아니라, 루프 스스로 우선순위를 갖게 하는 것이 더 안정적이었습니다.
2. 역할을 나누면 프롬프트는 짧아질 수 있다
또 하나 컸던 점은 한 번의 대화에 모든 것을 떠맡기지 않는 것입니다. ~/workspace/scripts/codex_orchestrator.py
의 codex-cost-build-review
preset에서는 실제로 plan
, todo
, build
, 두 개의 review
, synthesis
의 6개 스테이지(stage)로 나누고 있습니다. 다음 예시는 그 구성을 공개용으로 일반화한 의사 코드(pseudo code)입니다.
"codex-cost-build-review": [
Stage("plan", "exec", "read-only"),
Stage("todo", "exec", "read-only"),
...
여기서 중요한 것은 똑똑한 다단계화 그 자체가 아닙니다. plan은 설계 판단, build는 구현, review는 읽기 전용(read-only), synthesis는 통합 판단으로 책임을 나눔으로써, "이번 대화에서 모든 것을 다 설명해야 한다"라는 압박을 줄이는 것입니다.
저 자신도 처음에는 긴 프롬프트로 모든 것을 제약하려 했지만, 실제로는 프롬프트가 두꺼워질수록 예외 상황에 대한 처리가 모호해졌습니다. 오히려 stage (단계) 별로 Done (완료) 조건을 고정하는 것이 각 지시 사항이 짧더라도 무너지지 않습니다. 수동 프롬프트 문화에서 벗어나기 위해서는, 멋진 문장 하나를 쓰는 것보다 어떤 판단을 어느 단계에서 종결할지를 결정하는 것이 우선이었습니다.
3. 좋은 루프는 "너무 많이 멈추지 않고" "재시도도 제한한다"
AI 운용에서 흔히 발생하는 실패는 너무 엄격해서 매번 멈추거나, 반대로 대충 재시도하여 망가뜨리는 것 중 하나입니다. 2026-06-10에 검토한 Zenn review에서는 이를 피하기 위해 최종 판정을 pass / warn / block의 3단계로 나누었습니다. block은 명확한 사실 오인이나 안전 위반만을 대상으로 하고, 경미한 익명화 누락이나 frontmatter (프론트매터)의 불일치는 warn으로 분류하여 자동 수정 후 다음으로 진행할 수 있도록 설계했습니다.
이 조정은 상당히 효과적이었습니다. 이전처럼 "근거가 조금 부족하다"는 이유만으로 정지했다면, 일일 운용은 금방 막혔을 것입니다. 반면 무엇이든 재시도하게 되면, 2026-06-12과 같은 404 케이스에서 published:false -> true를 반복해서 전환할 위험이 있습니다. 그래서 recovery (복구)도 1회로 제한했습니다. 실제 로그를 보면, 공개 URL 404, origin/main 동기 완료, GitHub raw 200, 로컬 확인 OK라는 조건이 모두 갖춰졌을 때만 빈 커밋(empty commit)으로 deploy (배포)를 재발화합니다. 그 결과, commit 5164e21 이후에 URL은 200으로 돌아왔습니다.
즉, 루프 설계에서 필요한 것은 "자동화할 것인가 말 것인가"가 아니라, 다음의 두 가지입니다.
- 어디까지라면 자동으로 수정해도 되는가
- 몇 회까지라면 재시도해도 되는가
이 경계가 없으면 AI 에이전트가 아무리 능숙해 보여도 운용자의 불안을 줄여주지 못합니다.
요약
- 수동 프롬프트를 줄이고 싶다면, 대화가 아니라 상태(state) 이름을 먼저 늘려라
- 일일 운용은 성공 경로(success path)보다
PENDING_PUBLISH_CHECK와 같은 중간 상태 설계가 효과적이다 - 하나의 긴 프롬프트에 몰아넣기보다
plan,build,review로 책임을 분리하는 것이 더 견고하다 - 품질 게이트(quality gate)는
block으로만 멈추지 말고,warn으로 흘려보낼 수 있는 범위를 명시하는 것이 운영에 유리하다 - 재시도는 자유롭게 두지 마라. 조건과 횟수를 제한해야 비로소 루프가 된다
Discussion

AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기