한 함수
RAG service 가 한 함수: build_rag_context(query) -> str | None. Claude-Pippa 의 chat route 우선으로 디자인 — 변형 생각 없이. 각 변형 route 가 한 줄 추가: rag_context = await build_rag_context(prompt_text). 함수가 어느 두뇌가 consume 할지 모름.
cross-contamination 없는 cross-cutting
RAG 가 shared 인 건 underlying 작업 (ChromaDB 위 semantic search) 이 두뇌 무관 진짜 같음. service는 공유하지만 route는 여전히 독립이야.
graceful degradation
configured embedding provider를 쓸 수 없으면 build_rag_context는 None을 반환해. route는 retrieved context 없이 진행하고, search failure 하나로 chat 전체를 막지 않아.
이 함수의 contract가 좁아서 provider를 바꿔도 caller는 안 흔들려. query를 받아 provenance가 붙은 context string이나 None을 돌려주고, 어느 brain이 읽을지는 묻지 않아. 반대로 prompt layout이나 brain-specific token budget까지 service가 결정하면 cross-cutting이 아니라 중앙집권이 돼.
Graceful degradation에도 선이 있어. retrieval이 없어도 대화를 계속할 수 있다는 뜻이지, 찾지 못한 기억을 찾았다고 꾸미라는 뜻이 아니야. UI와 log에는 RAG가 빠졌다는 사실을 남기고, answer는 현재 context만으로 만든다고 정직하게 범위를 좁혀.
사실 shared service의 기준은 여러 caller가 쓴다는 데 있지 않아. 같은 입력, 같은 책임, 같은 failure behavior를 가졌는지가 기준이야. 이 셋이 같으니 RAG retrieval은 공유하고, route별 prompt assembly는 각 vessel에 남겨.
RAG context는 답이 아니라 증거 후보라서 provenance가 빠지면 가치가 반으로 줄어. 어느 vault file과 어느 conversation에서 왔는지 보여 줘야 model도 아빠도 필요할 때 원문으로 돌아갈 수 있어.