모듈형 프롬프트 transpilation 운영법: 시스템 프롬프트를 CI에서 검증하는 방법
에이전트를 처음 만들 때는 시스템 프롬프트 하나로 충분하다. 역할, 금지사항, 도구 사용법, 출력 형식을 한 파일에 적으면 바로 작동한다. 문제는 운영이 시작된 뒤다. 안전 정책, 고객사별 규칙, 도메인 지식, 에스컬레이션 조건, 포맷 요구사항이 계속 붙으면서 프롬프트는 점점 “거대한 설정 덩어리”가 된다.
Google Developers Blog의 “Building scalable AI agents with modular prompt transpilation” 글은 이 문제를 소프트웨어 엔지니어링 관점으로 다룬다. 핵심 키워드는 “모듈형 프롬프트 transpilation”이다. 결론은 간단하다. 프롬프트를 텍스트가 아니라 build artifact로 다뤄야 한다.
출처: Google Developers Blog, Building scalable AI agents with modular prompt transpilation(2026-07-16).
왜 단일 시스템 프롬프트는 운영에서 깨지는가
단일 프롬프트가 커지면 세 가지 문제가 생긴다.
첫째, blast radius가 보이지 않는다. 코드에서는 함수, 모듈, 테스트가 있어 변경 영향 범위를 어느 정도 추적할 수 있다. 프롬프트는 다르다. 한 문장을 추가했는데 도구 호출 우선순위, 거절 정책, 답변 형식이 동시에 흔들릴 수 있다.
둘째, copy-paste drift가 생긴다. 여러 팀이 같은 안전 정책이나 PII 처리 규칙을 복사해서 각자 수정하면 버전이 갈라진다. 한 에이전트는 최신 정책을 따르고, 다른 에이전트는 3개월 전 문구를 계속 쓴다.
셋째, 런타임 오류가 늦게 발견된다. 템플릿 변수 이름이 틀렸거나 include 경로가 빠져도 배포 전에는 모를 수 있다. 특정 고객사의 드문 워크플로우가 실행될 때만 프롬프트 렌더링이 깨지는 식이다.
이건 프롬프트 문제가 아니라 빌드 시스템 문제다.
transpilation 패턴: source prompt와 rendered prompt를 나눈다
권장 구조는 프롬프트를 작은 파일로 쪼개고, 빌드 단계에서 하나의 완성본으로 렌더링하는 것이다.
예를 들어 SRE triage 에이전트라면 다음처럼 나눌 수 있다.
shared/safety.prompt.md: 공통 안전 정책.shared/tool-usage.prompt.md: 도구 호출 규칙.domains/sre/incident-flow.prompt.md: 장애 조사 순서.clients/acme/escalation.prompt.md: 고객사별 에스컬레이션 정책.agents/sre-agent.prompt.md: 최상위 조합 파일.
최상위 파일은 include와 변수만 가진다. 빌드 도구는 모든 include를 따라가고, 변수를 주입하고, 최종 rendered prompt를 만든다. 모델에는 이 rendered artifact만 전달한다.
중요한 점은 source와 artifact를 구분하는 것이다. 사람이 수정하는 건 source이고, 운영에 들어가는 건 빌드된 artifact다.
CI에서 반드시 검사할 항목
프롬프트 transpiler는 단순 문자열 합치기가 아니다. 최소한 다음 검사를 해야 한다.
| 검사 항목 | 실패 예시 | 막는 문제 |
|---|---|---|
| missing import | 없는 파일 include | 배포 후 렌더링 실패 |
| undefined variable | {{ environment }} 값 없음 | 특정 환경에서만 깨짐 |
| circular dependency | A가 B include, B가 A include | 무한 렌더링 |
| golden diff | source와 artifact 불일치 | 배포된 프롬프트 추적 불가 |
| policy presence | 안전 정책 누락 | 에이전트별 규칙 차이 |
| token budget | 렌더링 후 80k 초과 | 컨텍스트 낭비 |
| forbidden phrase | 금지된 약속·권한 문구 | 컴플라이언스 리스크 |
이 검사를 CI에 넣으면 프롬프트 변경도 코드 변경처럼 리뷰할 수 있다. PR에는 source diff와 rendered diff가 같이 보여야 한다. 리뷰어는 “이 문장이 어디에 들어가 최종 프롬프트가 어떻게 바뀌는지” 볼 수 있어야 한다.
dynamic skills는 전체 로딩이 아니라 점진적 로딩으로 설계한다
모듈이 많아지면 또 다른 문제가 생긴다. 모든 skill 파일을 매번 시스템 프롬프트에 넣으면 토큰이 낭비되고, 모델이 과도한 규칙 사이에서 흔들린다.
Google 글은 progressive disclosure를 제안한다. 기본 프롬프트에는 절대 바뀌면 안 되는 identity, safety boundary, tool approval 정책만 둔다. 작업별 세부 지식은 런타임 도구로 필요한 순간에 검색하거나 로드한다.
예를 들어 법무 문서 에이전트가 있다면 기본 프롬프트에는 “법률 자문을 단정하지 않는다”, “외부 전송은 승인 필요” 같은 정책만 둔다. NDA 검토가 들어왔을 때만 skills/legal/nda-review.md를 로드한다. 개인정보 처리 계약이면 skills/legal/dpa-review.md를 로드한다.
이 구조는 정확도와 비용 모두에 좋다. 모델이 당장 필요 없는 30개 규칙을 계속 들고 있을 이유가 없다.
에이전트가 자기 프롬프트를 고치는 워크플로우는 어떻게 안전하게 만들까
글에서 흥미로운 부분은 agent-authored updates다. 에이전트가 새로운 유형의 장애를 해결했을 때, 직접 운영 프롬프트를 바꾸는 게 아니라 새로운 skill module 초안을 만들고 PR을 열 수 있다.
이 차이가 중요하다. 에이전트가 실시간으로 자기 지시문을 변경하면 통제하기 어렵다. 반면 PR을 만들면 기존 소프트웨어 프로세스를 그대로 적용할 수 있다.
안전한 흐름은 다음과 같다.
- 에이전트가 반복된 실패 패턴을 감지한다.
- 새 skill 파일 또는 기존 skill 수정안을 작성한다.
- transpiler가 import, variable, token, policy 검사를 돌린다.
- eval suite가 대표 케이스를 실행한다.
- 사람 리뷰어가 diff와 eval 결과를 확인한다.
- merge 후 배포 파이프라인이 rendered prompt를 갱신한다.
이렇게 하면 “자기개선”은 가능하지만, 통제권은 여전히 코드 리뷰와 CI에 남는다.
작은 팀을 위한 파일 구조 예시
처음부터 거대한 플랫폼을 만들 필요는 없다. 다음 정도면 충분히 시작할 수 있다.
prompts/
agents/
support-agent.prompt.md
sre-agent.prompt.md
shared/
identity.prompt.md
safety.prompt.md
tool-approval.prompt.md
skills/
refund-policy.prompt.md
incident-triage.prompt.md
rendered/
support-agent.rendered.md
sre-agent.rendered.md
scripts/
build-prompts.ts
validate-prompts.ts
rendered/ 파일은 커밋할지 말지 팀마다 선택할 수 있다. 운영 추적이 중요하면 커밋하고 golden diff를 본다. 보안상 artifact를 저장하기 어렵다면 CI artifact로만 남긴다.
실행 체크리스트
- 시스템 프롬프트를 shared, domain, client, agent 단위로 나눈다.
- include 경로와 변수 목록을 빌드 타임에 검증한다.
- source prompt와 rendered prompt의 diff를 PR에 표시한다.
- 안전 정책이 모든 agent artifact에 포함되는지 테스트한다.
- rendered prompt의 토큰 수를 측정하고 예산을 넘으면 실패시킨다.
- 작업별 skill은 런타임에 필요한 것만 로드한다.
- 에이전트가 제안한 프롬프트 수정은 직접 반영하지 말고 PR로만 처리한다.
프롬프트가 길어질수록 “프롬프트 잘 쓰기”보다 “프롬프트를 안전하게 빌드하기”가 중요해진다. 운영 에이전트의 신뢰성은 모델 성능만으로 나오지 않는다. 지시문도 코드처럼 검증되고 배포되어야 한다.