5계층
1. Templates Layer core/llm/prompts/*.md — 8 markdown files
2. Axes Layer core/llm/prompts/axes.py — optional evaluator axes
3. Hash Versioning core/llm/prompts/__init__.py — SHA-256[:12] x 18 pinned entries
4. Assembly core/llm/prompt_assembler.py — base + skill + memory + bootstrap
(6 phases, append-only by default)
5. Skill Injection core/skills/skill_registry.py — frontmatter + body, 5-tier discoverySOT (Source of Truth)
프롬프트 텍스트는 마크다운 파일(analyst.md, evaluator.md, synthesizer.md, router.md, cross_llm.md, commentary.md 등) 과 하나의 외부 도메인 플러그인이 제공하는 axes 데이터에 살고 있습니다.
import 시점에 core/llm/prompts/__init__.py 가 각 템플릿을 Python 상수(ANALYST_SYSTEM, EVALUATOR_SYSTEM 등) 로 읽고, SHA-256[:12] 해시를 계산해 PROMPT_VERSIONS 레지스트리에 노출합니다.
드리프트 감지
병렬 딕셔너리 _PINNED_HASHES 는 18개 항목 각각의 기대 해시를 유지합니다. verify_prompt_integrity() 가 라이브 해시와 핀 해시를 비교해 드리프트 리스트를 반환합니다. CI 는 이 함수를 raise_on_drift=True 로 호출하므로 어떤 불일치도 빌드를 깨뜨립니다.
의도적 프롬프트 변경 시의 재핀 워크플로는 프롬프트 해싱 참조.
조립
파이프라인 노드는 템플릿에 직접 .format() 을 호출하지 않습니다.PromptAssembler.assemble() 을 호출해 6단계를 실행합니다:
- 오버라이드 (기본은 append-only)
- 스킬 주입 (priority 정렬, 최대 3개, body 캡 500자)
- 메모리 컨텍스트 (
_llm_summary우선, 폴백 경로) - 부트스트랩 추가 명령 (최대 5개, 각 100자)
- 예산 관찰성 (4000자 초과 시 경고)
- 해시 + Hook 발행 (
PROMPT_ASSEMBLED이벤트)
결과는 frozen=True 인 불변 AssembledPromptdataclass — 빌드 후에는 어떤 코드 경로도 수정할 수 없습니다.
캐싱
Anthropic 의 경우, core/agent/system_prompt.py 의 build_system_prompt() 가 정적 섹션 (라우터 템플릿 + 정체성) 과 동적 섹션 (날짜, 모델 카드, 메모리) 사이에 경계 마커 (__GEODE_PROMPT_CACHE_BOUNDARY__) 를 삽입합니다. Anthropic 어댑터가 이 마커에서 분할해 정적 블록에만 cache_control: ephemeral 을 적용합니다. 자세한 내용은 프롬프트 캐싱 참조.
관찰성
PROMPT_ASSEMBLED hook 이벤트는 메타데이터만 전달합니다 — 노드명, 역할 타입, base 와 assembled 해시, fragment 목록, 그리고 조건부 필드인 skill_hashes 와 truncation_events. 원본 프롬프트 텍스트는 payload 에 포함되지 않으므로 hook 핸들러와 OTLP exporter 는 이 채널을 통해 프롬프트 내용을 보지 못합니다.
관측성은 내장 hook, RunLog, usage JSONL 로 기본 기록됩니다. 외부 span 이 필요하면 [obs] extra 와 OTLP endpoint 로 OpenLLMetry exporter 를 활성화합니다.
이 설계의 이유
- 외부 마크다운 은 프롬프트를 1급 버전 관리 산출물로 만듭니다. 프롬프트 변경에 대한
git diff가 명확합니다. - 해시 ratchet 은 프롬프트 변경을 보이지 않는 편집에서 의식적으로 리뷰 가능한 코드 변경(re-pin 필요) 으로 전환합니다.
- Frozen 결과 는 어셈블과 LLM 호출 사이의 우발적 변조를 방지합니다.
- Append-only override 는 prompt-injection 채널 (env, config, untrusted state) 이 시스템 프롬프트를 통째로 교체하지 못하게 막습니다.