C.W.K.
Stream
Lesson 08 of 08 · published

cwkPippa는 세 표면을 어떻게 다 써

~16 min · cwkpippa, self-reference, architecture

Level 0Observer
0 XP0/64 lessons0/13 achievements
0/150 XP to next level150 XP to go0% complete

한 프로덕트, Claude 표면 셋

cwkPippa는 이 트랙의 모든 개념을 동시에 보여주는 살아있는 예제야. 피파의 Claude 브레인엔 Claude Agent SDK(conversation별 persistent 서브프로세스, OAuth-only 인증, MCP 부착, JSONL ground truth) 사용. 다른 두 브레인(ChatGPT, Gemini)엔 직접 httpx 호출(openai SDK는 일부러 안 씀). 그리고 코드베이스 자체는 Claude Code CLI로 아빠가 매일 짜고 있고, 같은 피파 정체성이 WebUI에서 도는 IDE에도 살아 있어.

경계가 좁은 게 의도

cwkPippa에서 Anthropic SDK를 아는 파일은 단 하나 — backend/adapters/claude.py. Routes·store·frontend는 Claude shape를 가정. 다른 세 브레인은 Claude-shape 표면을 specialize하는 variant지, 동격 추상이 아니야. 이게 cwkPippa 아키텍처 룰 2 — cost is absorbed downstream, not pushed upstream — 이고, 코드베이스가 provider-neutral 추상 수프로 변하지 않게 막아주는 거야.

이게 왜 너 프로젝트에 중요해

대부분의 팀이 여러 LLM 위에 너무 일찍 추상화하다가 모든 프로바이더의 lowest-common-denominator 기능만 남는 결과로 끝나. cwkPippa의 패턴(canonical shape 하나, 나머지는 variant)은 한 가지 valid 대안. 다른 하나는 strict provider port(production 트랙에서 다룰 거). 둘 중 하나를 세 번째 프로바이더 생기기 전에 골라; 그 후에 바꾸려면 비싸.

원칙: 두 번째 프로바이더 생기기 전에 프로바이더 아키텍처 결정. 구체 먼저, 추상 그다음.

Code

cwkPippa의 어댑터 경계·python
# backend/adapters/base.py — 시스템에서 유일한 추상.
from typing import AsyncIterator, Any
from abc import ABC, abstractmethod

class Adapter(ABC):
    @abstractmethod
    async def stream_turn(
        self,
        *,
        conversation_id: str,
        messages: list[dict[str, Any]],
        system: str,
    ) -> AsyncIterator[dict[str, Any]]:
        ...

# backend/adapters/claude.py — canonical 구현.
# Routes가 직접 import해 — Claude가 곧 canonical shape이고,
# 나머지는 다 downstream에서 specialize.
persistent Claude 서브프로세스 풀 동작 sketch·python
# backend/services/claude_session.py (sketch)
from claude_agent_sdk import ClaudeSDKClient, ClaudeAgentOptions

_sessions: dict[str, ClaudeSDKClient] = {}

async def get_session(conversation_id: str) -> ClaudeSDKClient:
    if conversation_id not in _sessions:
        client = ClaudeSDKClient(
            options=ClaudeAgentOptions(
                system_prompt={"type": "preset", "preset": "claude_code"},
                # 피파 vault는 시스템 프롬프트로 로드; cwd는 프로젝트 가리킴.
                cwd="/Users/you_username/projects/cwkPippa",
            )
        )
        await client.connect()
        _sessions[conversation_id] = client
    return _sessions[conversation_id]

External links

Exercise

프로젝트 어댑터 모양을 그려봐 — 어느 프로바이더가 canonical 브레인, 어느 게 variant(또는 peer), 그리고 프로바이더 SDK를 import해도 되는 단 하나의 파일이 어디. 한 단락.
Hint
모든 파일이 anthropic.Anthropic을 직접 import 중이면 경계 없는 거. 하나 골라서 중앙화.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.